#!/bin/bash

# IP配置交换脚本
# 用法: ./swap_ip_config.sh <目标服务器IP> [用户名] [端口]

set -e

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 参数检查
if [ $# -lt 1 ]; then
    log_error "用法: $0 <目标服务器IP> [用户名] [端口]"
    log_error "示例: $0 192.168.1.100 root 2233"
    exit 1
fi

TARGET_IP=$1
USERNAME=${2:-root}
PORT=${3:-2233}

log_info "目标服务器: $TARGET_IP"
log_info "用户名: $USERNAME"
log_info "端口: $PORT"

# 检查必要的命令
for cmd in ssh scp ping; do
    if ! command -v $cmd &> /dev/null; then
        log_error "命令 $cmd 不存在，请先安装"
        exit 1
    fi
done

# 获取本机网络接口配置文件路径
INTERFACES_FILE="/etc/network/interfaces"
if [ ! -f "$INTERFACES_FILE" ]; then
    log_error "本机网络配置文件 $INTERFACES_FILE 不存在"
    exit 1
fi

# 创建备份文件名（带序列号）
create_backup_name() {
    local base_name="$1"
    local counter=0
    local backup_name="${base_name}.BAK"
    
    if [ ! -f "$backup_name" ]; then
        echo "$backup_name"
        return
    fi
    
    counter=1
    while [ -f "${base_name}.BAK${counter}" ]; do
        ((counter++))
    done
    
    echo "${base_name}.BAK${counter}"
}

# 获取本机网卡名称
get_local_interface() {
    # 从配置文件中提取网卡名称（排除lo）
    local interface=$(grep "^auto " "$INTERFACES_FILE" | grep -v "lo" | head -1 | awk '{print $2}')
    if [ -z "$interface" ]; then
        log_error "无法从配置文件中获取本机网卡名称"
        exit 1
    fi
    echo "$interface"
}

# 测试网络连通性
test_network() {
    log_info "测试网络连通性..."
    local count=0
    local max_attempts=6  # 2分钟，每20秒测试一次
    
    while [ $count -lt $max_attempts ]; do
        if ping -c 1 -W 3 1.1.1.1 &> /dev/null; then
            log_success "网络连通性测试通过"
            return 0
        fi
        
        count=$((count + 1))
        if [ $count -lt $max_attempts ]; then
            log_warning "网络连通性测试失败，20秒后重试... ($count/$max_attempts)"
            sleep 20
        fi
    done
    
    log_warning "请告知客服更新VLAN配置"
    
    # 继续测试直到网络恢复或用户中断
    log_info "继续监控网络连通性，按Ctrl+C中断..."
    while true; do
        if ping -c 1 -W 3 1.1.1.1 &> /dev/null; then
            log_success "网络连通性恢复"
            return 0
        fi
        sleep 10
    done
    
    return 1
}

# 恢复备份配置
restore_backup() {
    local backup_file=$1
    local interface=$2
    
    log_warning "恢复备份配置文件..."
    if [ -f "$backup_file" ]; then
        cp "$backup_file" "$INTERFACES_FILE"
        log_info "重启网络接口 $interface..."
        ifdown "$interface" 2>/dev/null || true
        sleep 2
        ifup "$interface"
        log_success "配置已恢复"
    else
        log_error "备份文件 $backup_file 不存在"
        return 1
    fi
}

# 主函数
main() {
    log_info "开始IP配置交换过程..."
    
    # 获取本机网卡名称
    LOCAL_INTERFACE=$(get_local_interface)
    log_info "本机网卡: $LOCAL_INTERFACE"
    
    # 创建备份
    BACKUP_FILE=$(create_backup_name "$INTERFACES_FILE")
    log_info "备份本机配置到: $BACKUP_FILE"
    cp "$INTERFACES_FILE" "$BACKUP_FILE"
    
    # 临时文件
    TEMP_TARGET_CONFIG="/tmp/target_interfaces_$(date +%s)"
    TEMP_LOCAL_CONFIG="/tmp/local_interfaces_$(date +%s)"
    
    # 清理函数
    cleanup() {
        rm -f "$TEMP_TARGET_CONFIG" "$TEMP_LOCAL_CONFIG"
    }
    trap cleanup EXIT
    
    # 提示用户在目标机器上运行相同的脚本
    log_warning "================================================"
    log_warning "重要提醒："
    log_warning "请在目标服务器 ($TARGET_IP) 上运行以下命令："
    log_warning "./swap_ip_config.sh $(hostname -I | awk '{print $1}') $USERNAME $PORT"
    log_warning "================================================"
    
    read -p "请确认目标服务器已经开始运行相同的脚本，按回车继续..."
    
    # 从目标服务器获取网络配置
    log_info "从目标服务器获取网络配置..."
    if ! scp -P "$PORT" -o ConnectTimeout=10 -o StrictHostKeyChecking=no \
         "$USERNAME@$TARGET_IP:$INTERFACES_FILE" "$TEMP_TARGET_CONFIG"; then
        log_error "无法从目标服务器获取网络配置文件"
        exit 1
    fi
    
    # 发送本机配置到目标服务器
    log_info "发送本机配置到目标服务器..."
    if ! scp -P "$PORT" -o ConnectTimeout=10 -o StrictHostKeyChecking=no \
         "$INTERFACES_FILE" "$USERNAME@$TARGET_IP:$TEMP_LOCAL_CONFIG"; then
        log_error "无法发送本机配置到目标服务器"
        exit 1
    fi
    
    # 获取目标服务器的网卡名称
    TARGET_INTERFACE=$(grep "^auto " "$TEMP_TARGET_CONFIG" | grep -v "lo" | head -1 | awk '{print $2}')
    if [ -z "$TARGET_INTERFACE" ]; then
        log_error "无法从目标配置文件中获取网卡名称"
        exit 1
    fi
    log_info "目标服务器网卡: $TARGET_INTERFACE"
    
    # 修改配置文件，替换网卡名称
    log_info "修改网络配置文件..."
    cp "$TEMP_TARGET_CONFIG" "$INTERFACES_FILE"
    
    # 替换网卡名称
    if [ "$TARGET_INTERFACE" != "$LOCAL_INTERFACE" ]; then
        log_info "将网卡名称从 $TARGET_INTERFACE 替换为 $LOCAL_INTERFACE"
        sed -i "s/^auto $TARGET_INTERFACE$/auto $LOCAL_INTERFACE/g" "$INTERFACES_FILE"
        sed -i "s/^iface $TARGET_INTERFACE /iface $LOCAL_INTERFACE /g" "$INTERFACES_FILE"
        # 如果配置文件中有引用网卡名称的地方，也需要替换
        sed -i "s/ $TARGET_INTERFACE/ $LOCAL_INTERFACE/g" "$INTERFACES_FILE"
    fi
    
    # 显示新的配置
    log_info "新的网络配置:"
    cat "$INTERFACES_FILE"
    
    log_warning "即将应用新的网络配置，这可能会导致连接中断..."
    read -p "按回车继续..."
    
    # 创建网络重启和测试脚本
    NETWORK_SCRIPT="/tmp/network_restart_test.sh"
    cat > "$NETWORK_SCRIPT" << 'EOF'
#!/bin/bash

# 网络重启和测试脚本
INTERFACE=$1
BACKUP_FILE=$2
INTERFACES_FILE="/etc/network/interfaces"

# 日志函数
log_info() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $1" | tee -a /tmp/network_swap.log
}

log_success() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $1" | tee -a /tmp/network_swap.log
}

log_warning() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [WARNING] $1" | tee -a /tmp/network_swap.log
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $1" | tee -a /tmp/network_swap.log
}

# 重启网络接口
log_info "应用新的网络配置..."
log_info "停止网络接口 $INTERFACE..."
ifdown "$INTERFACE" 2>/dev/null || true
sleep 3

log_info "启动网络接口 $INTERFACE..."
ifup "$INTERFACE"
sleep 5

# 测试网络连通性
log_info "测试网络连通性..."
test_count=0
max_attempts=12  # 2分钟，每10秒测试一次

while [ $test_count -lt $max_attempts ]; do
    if ping -c 1 -W 3 1.1.1.1 &> /dev/null; then
        log_success "网络连通性测试通过"
        log_success "网络配置交换完成！"
        log_info "备份文件保存在: $BACKUP_FILE"
        
        # 显示当前IP配置
        log_info "当前网络配置:"
        ip addr show "$INTERFACE" | grep -E "inet |link" | tee -a /tmp/network_swap.log
        exit 0
    fi
    
    test_count=$((test_count + 1))
    if [ $test_count -eq 6 ]; then
        log_warning "请告知客服更新VLAN配置"
    fi
    
    if [ $test_count -lt $max_attempts ]; then
        log_warning "网络连通性测试失败，10秒后重试... ($test_count/$max_attempts)"
        sleep 10
    fi
done

# 网络测试失败，恢复备份
log_error "网络连通性测试失败，恢复备份配置..."
if [ -f "$BACKUP_FILE" ]; then
    cp "$BACKUP_FILE" "$INTERFACES_FILE"
    log_info "重启网络接口 $INTERFACE..."
    ifdown "$INTERFACE" 2>/dev/null || true
    sleep 3
    ifup "$INTERFACE"
    sleep 5
    
    # 测试恢复后的网络
    if ping -c 1 -W 3 1.1.1.1 &> /dev/null; then
        log_success "备份配置恢复成功，网络已恢复"
        exit 0
    else
        log_error "严重错误：无法恢复网络连接，请通过控制台手动检查配置"
        exit 1
    fi
else
    log_error "备份文件 $BACKUP_FILE 不存在，请手动恢复配置"
    exit 1
fi
EOF

    chmod +x "$NETWORK_SCRIPT"
    
    # 应用新配置并在后台运行网络测试
    log_warning "即将应用新的网络配置..."
    log_warning "注意：SSH连接可能会中断，脚本将继续在后台运行"
    log_warning "请查看日志文件 /tmp/network_swap.log 了解执行状态"
    
    read -p "按回车继续..."
    
    # 在后台运行网络重启和测试
    nohup "$NETWORK_SCRIPT" "$LOCAL_INTERFACE" "$BACKUP_FILE" > /dev/null 2>&1 &
    
    log_info "网络配置更新脚本已在后台启动"
    log_info "请等待约2-3分钟，然后尝试使用新IP连接"
    log_info "可以通过以下命令查看执行日志："
    log_info "tail -f /tmp/network_swap.log"
}

# 运行主函数
main "$@"
