#!/bin/bash

# 一键Linux换源脚本
# 支持 Debian, Ubuntu, CentOS, AlmaLinux, Rocky Linux

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 "${GREEN}[INFO]${NC} $1"
}

log_warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

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

# 检测系统类型
detect_os() {
    if [ -f /etc/os-release ]; then
        . /etc/os-release
        OS_NAME=$ID
        OS_VERSION=$VERSION_ID
    else
        log_error "无法检测操作系统类型"
        exit 1
    fi
    
    case $OS_NAME in
        debian|ubuntu|centos|almalinux|rocky)
            log_info "检测到系统: $OS_NAME $OS_VERSION"
            ;;
        *)
            log_error "不支持的操作系统: $OS_NAME"
            exit 1
            ;;
    esac
}

# 备份原始源文件
backup_sources() {
    local backup_file="sources_backup_$(date +%Y%m%d_%H%M%S).tar.gz"
    local backup_files=()
    
    case $OS_NAME in
        debian|ubuntu)
            backup_files=("/etc/apt/sources.list" "/etc/apt/sources.list.d/")
            ;;
        centos|almalinux|rocky)
            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                backup_files=("/etc/yum.repos.d/CentOS-Base.repo")
            elif [ -f /etc/yum.repos.d/almalinux.repo ]; then
                backup_files=("/etc/yum.repos.d/almalinux.repo")
            elif [ -f /etc/yum.repos.d/rocky.repo ]; then
                backup_files=("/etc/yum.repos.d/rocky.repo")
            fi
            backup_files+=("/etc/yum.repos.d/")
            ;;
    esac
    
    tar -czf "$backup_file" "${backup_files[@]}" 2>/dev/null || true
    log_info "已备份源文件到: $backup_file"
}

# 选择镜像源
select_mirror() {
    echo -e "\n${BLUE}请选择镜像源:${NC}"
    echo "1) 清华镜像站 (TUNA)"
    echo "2) 阿里云镜像站"
    echo "3) 华为云镜像站"
    echo "4) 中科大镜像站 (USTC)"
    echo "5) 网易镜像站"
    echo "6) 腾讯云镜像站"
    echo "7) 恢复默认源"
    echo "8) 退出"
    
    read -p "请输入选择 [1-8]: " choice
    
    case $choice in
        1) MIRROR="tuna" ;;
        2) MIRROR="aliyun" ;;
        3) MIRROR="huawei" ;;
        4) MIRROR="ustc" ;;
        5) MIRROR="163" ;;
        6) MIRROR="tencent" ;;
        7) MIRROR="default" ;;
        8) log_info "退出脚本"; exit 0 ;;
        *) log_error "无效选择"; select_mirror ;;
    esac
}

# 获取镜像URL
get_mirror_url() {
    local mirror_type=$1
    local os_name=$2
    local version=$3
    
    case $mirror_type in
        tuna)
            case $os_name in
                debian) echo "https://mirrors.tuna.tsinghua.edu.cn/debian/" ;;
                ubuntu) echo "https://mirrors.tuna.tsinghua.edu.cn/ubuntu/" ;;
                centos|almalinux|rocky) echo "https://mirrors.tuna.tsinghua.edu.cn/centos/" ;;
            esac
            ;;
        aliyun)
            case $os_name in
                debian) echo "https://mirrors.aliyun.com/debian/" ;;
                ubuntu) echo "https://mirrors.aliyun.com/ubuntu/" ;;
                centos|almalinux|rocky) echo "https://mirrors.aliyun.com/centos/" ;;
            esac
            ;;
        huawei)
            case $os_name in
                debian) echo "https://mirrors.huaweicloud.com/debian/" ;;
                ubuntu) echo "https://mirrors.huaweicloud.com/ubuntu/" ;;
                centos|almalinux|rocky) echo "https://mirrors.huaweicloud.com/centos/" ;;
            esac
            ;;
        ustc)
            case $os_name in
                debian) echo "https://mirrors.ustc.edu.cn/debian/" ;;
                ubuntu) echo "https://mirrors.ustc.edu.cn/ubuntu/" ;;
                centos|almalinux|rocky) echo "https://mirrors.ustc.edu.cn/centos/" ;;
            esac
            ;;
        163)
            case $os_name in
                debian) echo "https://mirrors.163.com/debian/" ;;
                ubuntu) echo "https://mirrors.163.com/ubuntu/" ;;
                centos|almalinux|rocky) echo "https://mirrors.163.com/centos/" ;;
            esac
            ;;
        tencent)
            case $os_name in
                debian) echo "https://mirrors.cloud.tencent.com/debian/" ;;
                ubuntu) echo "https://mirrors.cloud.tencent.com/ubuntu/" ;;
                centos|almalinux|rocky) echo "https://mirrors.cloud.tencent.com/centos/" ;;
            esac
            ;;
    esac
}

# 更换Debian/Ubuntu源
change_apt_sources() {
    local mirror_url=$1
    
    # 备份原始sources.list
    cp /etc/apt/sources.list /etc/apt/sources.list.backup
    
    # 生成新的sources.list
    if [ "$OS_NAME" = "debian" ]; then
        cat > /etc/apt/sources.list << EOF
# 由一键换源脚本生成
deb ${mirror_url} $(lsb_release -cs) main contrib non-free
deb ${mirror_url} $(lsb_release -cs)-updates main contrib non-free
deb ${mirror_url} $(lsb_release -cs)-backports main contrib non-free
deb ${mirror_url}-security $(lsb_release -cs)-security main contrib non-free
EOF
    else  # Ubuntu
        cat > /etc/apt/sources.list << EOF
# 由一键换源脚本生成
deb ${mirror_url} $(lsb_release -cs) main restricted universe multiverse
deb ${mirror_url} $(lsb_release -cs)-security main restricted universe multiverse
deb ${mirror_url} $(lsb_release -cs)-updates main restricted universe multiverse
deb ${mirror_url} $(lsb_release -cs)-backports main restricted universe multiverse
EOF
    fi
    
    log_info "已更新APT源"
}

# 更换CentOS/AlmaLinux/Rocky Linux源
change_yum_sources() {
    local mirror_url=$1
    
    # 安装epel-release（如果不存在）
    if ! rpm -q epel-release >/dev/null 2>&1; then
        log_info "安装EPEL仓库..."
        yum install -y epel-release || dnf install -y epel-release
    fi
    
    # 根据具体系统类型处理
    case $OS_NAME in
        centos)
            if [ -f /etc/yum.repos.d/CentOS-Base.repo ]; then
                sed -i "s|^mirrorlist=|#mirrorlist=|g" /etc/yum.repos.d/CentOS-Base.repo
                sed -i "s|^#baseurl=|baseurl=|g" /etc/yum.repos.d/CentOS-Base.repo
                sed -i "s|^baseurl=http://mirror.centos.org/\$contentdir/\$releasever/|baseurl=${mirror_url}\$releasever/|g" /etc/yum.repos.d/CentOS-Base.repo
            fi
            ;;
        almalinux|rocky)
            # 对于AlmaLinux和Rocky Linux，我们主要替换EPEL源和其他可能存在的CentOS兼容源
            find /etc/yum.repos.d/ -name "*.repo" -exec sed -i "s|https://download.example.com|${mirror_url}|g" {} \; || true
            ;;
    esac
    
    # 更新EPEL源
    if [ -f /etc/yum.repos.d/epel.repo ]; then
        sed -i "s|^metalink=|#metalink=|g" /etc/yum.repos.d/epel.repo
        sed -i "s|^#baseurl=|baseurl=|g" /etc/yum.repos.d/epel.repo
        sed -i "s|^baseurl=https://download.example.com/epel/|baseurl=${mirror_url}epel/|g" /etc/yum.repos.d/epel.repo
    fi
    
    log_info "已更新YUM/DNF源"
}

# 恢复默认源
restore_default_sources() {
    case $OS_NAME in
        debian|ubuntu)
            # 对于Debian/Ubuntu，生成默认官方源
            if [ "$OS_NAME" = "debian" ]; then
                cat > /etc/apt/sources.list << EOF
deb http://deb.debian.org/debian $(lsb_release -cs) main contrib non-free
deb http://deb.debian.org/debian $(lsb_release -cs)-updates main contrib non-free
deb http://deb.debian.org/debian $(lsb_release -cs)-backports main contrib non-free
deb http://security.debian.org/debian-security $(lsb_release -cs)-security main contrib non-free
EOF
            else
                cat > /etc/apt/sources.list << EOF
deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs) main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-security main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu $(lsb_release -cs)-backports main restricted universe multiverse
EOF
            fi
            ;;
        centos|almalinux|rocky)
            # 对于这些系统，恢复操作比较复杂，建议用户手动恢复备份
            log_warn "请手动从备份文件恢复或重新安装系统仓库配置"
            return 1
            ;;
    esac
    log_info "已恢复默认源"
}

# 更新软件包缓存
update_package_cache() {
    log_info "更新软件包缓存..."
    
    case $OS_NAME in
        debian|ubuntu)
            apt update
            ;;
        centos|almalinux|rocky)
            if command -v dnf >/dev/null 2>&1; then
                dnf makecache
            else
                yum makecache
            fi
            ;;
    esac
    
    log_info "软件包缓存更新完成"
}

# 主函数
main() {
    echo -e "${BLUE}=== 一键Linux换源脚本 ===${NC}"
    
    # 检查root权限
    if [ "$EUID" -ne 0 ]; then
        log_error "请使用root权限运行此脚本"
        echo "尝试: sudo $0"
        exit 1
    fi
    
    detect_os
    select_mirror
    
    # 备份当前源
    backup_sources
    
    if [ "$MIRROR" = "default" ]; then
        restore_default_sources
    else
        # 获取镜像URL
        MIRROR_URL=$(get_mirror_url "$MIRROR" "$OS_NAME" "$OS_VERSION")
        log_info "使用镜像: $MIRROR_URL"
        
        # 根据系统类型更换源
        case $OS_NAME in
            debian|ubuntu)
                change_apt_sources "$MIRROR_URL"
                ;;
            centos|almalinux|rocky)
                change_yum_sources "$MIRROR_URL"
                ;;
        esac
    fi
    
    # 更新缓存
    read -p "是否更新软件包缓存? [y/N]: " -n 1 -r
    echo
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        update_package_cache
    fi
    
    log_info "换源完成!"
    
    # 显示后续操作建议
    echo -e "\n${YELLOW}后续操作建议:${NC}"
    case $OS_NAME in
        debian|ubuntu)
            echo "运行: sudo apt update && sudo apt upgrade"
            ;;
        centos|almalinux|rocky)
            if command -v dnf >/dev/null 2>&1; then
                echo "运行: sudo dnf update"
            else
                echo "运行: sudo yum update"
            fi
            ;;
    esac
}

# 运行主函数
main "$@"