#!/bin/bash
set -euo pipefail

# ========================== 全局配置 ==========================
# 脚本版本
SCRIPT_VERSION="1.8"
# 默认K8s版本
DEFAULT_K8S_VERSION="1.30.5"
# 阿里云K8s镜像基础路径（验证有效）
ALIBABA_MIRROR_BASE="https://mirrors.aliyun.com/kubernetes-new/core/stable"
# 用户指定的nerdctl内网下载地址
NERDCTL_DOWNLOAD_URL="http://10.102.32.207:5588/k8s/nerdctl-1.5.0-linux-amd64.tar.gz"

# 颜色定义（终端兼容）
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # 无颜色

# 打印工具函数（统一格式）
info() { echo -e "${YELLOW}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
step() { echo -e "\n${YELLOW}[STEP $1/$2]${NC} $3"; }


# ========================== 帮助信息 ==========================
usage() {
    cat << EOF
Kubernetes Master组件 + nerdctl 完整安装脚本（适配内网nerdctl下载）
脚本版本：${SCRIPT_VERSION}

功能：
  1. 安装：K8s组件（kubelet/kubeadm/kubectl）、nerdctl，配置crictl和kubectl补全
  2. 卸载：K8s组件、nerdctl及相关配置（保留containerd）

前提：
  - 需预先安装containerd（脚本会自动检测）
  - 确保能访问内网nerdctl下载地址：${NERDCTL_DOWNLOAD_URL}

用法: $0 [选项]

选项:
  --install        执行组件安装及配置
  --uninstall      执行组件卸载及配置清理（保留containerd）
  --version <ver>  指定K8s版本（格式x.y.z，如1.30.5，仅与--install配合）
  --help           显示此帮助信息
  --script-version 显示脚本当前版本

示例:
  1. 安装默认版本（${DEFAULT_K8S_VERSION}）:
     sudo $0 --install

  2. 安装指定版本（如1.30.5）:
     sudo $0 --install --version 1.30.5

  3. 卸载（需二次确认）:
     sudo $0 --uninstall
EOF
    exit 1
}


# ========================== 前置检查 ==========================
# 检查是否为root用户
check_root() {
    if [ "$(id -u)" -ne 0 ]; then
        error "请使用root权限运行脚本，命令格式：sudo $0 ..."
        exit 1
    fi
    success "root权限检查通过"
}

# 检查containerd是否已安装并运行
check_containerd() {
    step 1 1 "检查containerd状态"
    
    # 检查是否安装
    if ! command -v containerd &> /dev/null; then
        error "未检测到containerd，请先执行以下命令安装："
        exit 1
    fi
    
    # 检查版本
    local containerd_ver=$(containerd --version | head -n1 | awk '{print $3}')
    info "已检测到containerd，版本：${containerd_ver}"
    
    # 检查运行状态
    if ! systemctl is-active --quiet containerd; then
        info "containerd未运行，尝试启动..."
        if systemctl start containerd; then
            success "containerd启动成功"
        else
            error "containerd启动失败，请手动执行 'systemctl status containerd' 检查原因"
            exit 1
        fi
    else
        success "containerd已处于运行状态"
    fi
}

# 校验K8s版本格式（x.y.z）
validate_version() {
    local version=$1
    if ! [[ $version =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
        error "无效的K8s版本格式：'${version}'，正确格式为 x.y.z（如1.30.5）"
        exit 1
    fi
    success "K8s版本格式校验通过：${version}"
}

# 提取主版本（如1.30.5 -> 1.30）
get_major_version() {
    local version=$1
    echo "$version" | cut -d '.' -f 1,2
}


# ========================== 安装相关函数 ==========================
# 配置kubectl命令补全
configure_kubectl_completion() {
    step 4 4 "配置kubectl命令补全"
    
    # 安装bash-completion依赖
    info "安装bash-completion依赖..."
    if apt-get install -y -qq bash-completion; then
        success "bash-completion安装完成"
    else
        error "bash-completion安装失败"
        exit 1
    fi
    
    # 写入补全配置到全局profile（所有用户生效）
    local bash_profile="/etc/profile.d/kubectl-completion.sh"
    if ! grep -q "source <(kubectl completion bash)" "$bash_profile" 2>/dev/null; then
        info "添加kubectl补全配置到 ${bash_profile}..."
        echo "source <(kubectl completion bash)" | tee -a "$bash_profile" > /dev/null
        success "kubectl补全配置写入成功（所有用户生效）"
    else
        info "kubectl补全配置已存在，跳过写入"
    fi
    
    # 立即生效当前会话
    info "使当前会话生效kubectl补全..."
    source <(kubectl completion bash)
    success "kubectl命令补全配置完成（当前会话已生效）"
}

# 安装nerdctl（使用用户指定的内网下载地址）
install_nerdctl() {
    step 3 4 "安装nerdctl并配置crictl"
    
    # 优先通过系统仓库安装（兼容性更好）
    if apt-cache show nerdctl &> /dev/null; then
        info "系统仓库存在nerdctl，通过apt安装..."
        if apt-get install -y -qq nerdctl; then
            success "nerdctl通过系统仓库安装完成"
        else
            error "nerdctl系统仓库安装失败"
            exit 1
        fi
    else
        # 系统仓库无则使用内网地址下载二进制包
        info "系统仓库无nerdctl，从内网地址下载：${NERDCTL_DOWNLOAD_URL}"
        
        # 下载二进制包到临时目录
        info "开始下载nerdctl压缩包..."
        if curl -fsSL "$NERDCTL_DOWNLOAD_URL" -o /tmp/nerdctl.tar.gz; then
            success "nerdctl压缩包下载完成（保存到 /tmp/nerdctl.tar.gz）"
        else
            error "nerdctl下载失败，请检查："
            echo "  1. 内网地址是否可访问：${NERDCTL_DOWNLOAD_URL}"
            echo "  2. 网络连通性（可执行 curl ${NERDCTL_DOWNLOAD_URL} 测试）"
            exit 1
        fi
        
        # 解压到/usr/local/bin（系统可执行路径）
        info "解压nerdctl到 /usr/local/bin..."
        if tar -zxf /tmp/nerdctl.tar.gz -C /usr/local/bin nerdctl; then
            success "nerdctl解压完成"
        else
            error "nerdctl解压失败"
            exit 1
        fi
        
        # 清理临时文件
        info "清理临时压缩包..."
        rm -f /tmp/nerdctl.tar.gz
        success "临时文件清理完成"
    fi

    # 配置crictl连接containerd
    info "配置crictl连接containerd运行时..."
    if crictl config runtime-endpoint unix:///run/containerd/containerd.sock; then
        success "crictl配置完成（已关联containerd）"
    else
        error "crictl配置失败"
        exit 1
    fi

    # 验证nerdctl安装
    info "验证nerdctl版本..."
    local nerdctl_ver=$(nerdctl --version | awk '{print $3}')
    success "nerdctl安装完成，版本：${nerdctl_ver}"
}

# 安装Kubernetes组件（核心流程）
install_k8s() {
    local k8s_version=$1
    local major_version=$(get_major_version "$k8s_version")
    local deb_version="${k8s_version}-1.1"

    # 前置检查：containerd
    check_containerd

    info "开始执行Kubernetes组件安装，目标版本：${k8s_version}"

    # 1. 更新系统并安装基础依赖
    step 1 4 "安装K8s基础依赖"
    info "更新系统包索引..."
    if apt-get update -qq; then
        success "系统包索引更新完成"
    else
        error "系统包索引更新失败，请检查网络"
        exit 1
    fi
    
    info "安装基础依赖（apt-transport-https/ca-certificates等）..."
    if apt-get install -y -qq apt-transport-https ca-certificates curl lsb-release bash-completion; then
        success "基础依赖安装完成"
    else
        error "基础依赖安装失败"
        exit 1
    fi
    
    # 确保密钥目录存在
    info "创建apt密钥目录（/etc/apt/keyrings）..."
    mkdir -p /etc/apt/keyrings
    success "apt密钥目录准备完成"

    # 2. 添加阿里云K8s GPG密钥
    step 2 4 "添加K8s GPG密钥与软件源"
    local key_url="${ALIBABA_MIRROR_BASE}/v${major_version}/deb/Release.key"
    info "下载K8s GPG密钥，地址：${key_url}"
    if curl -fsSL "$key_url" | gpg --dearmor > /etc/apt/keyrings/kubernetes-apt-keyring.gpg 2>/dev/null; then
        success "K8s GPG密钥添加完成（保存到 /etc/apt/keyrings/kubernetes-apt-keyring.gpg）"
    else
        error "K8s GPG密钥获取失败，URL：${key_url}"
        echo "  建议：手动访问URL检查是否有效，或更换网络环境"
        exit 1
    fi

    # 3. 添加K8s软件源
    local repo_url="${ALIBABA_MIRROR_BASE}/v${major_version}/deb/"
    info "配置K8s软件源，地址：${repo_url}"
    echo "deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] $repo_url /" | \
        tee /etc/apt/sources.list.d/kubernetes.list > /dev/null
    success "K8s软件源配置完成（保存到 /etc/apt/sources.list.d/kubernetes.list）"

    # 4. 刷新软件源
    info "刷新新配置的软件源..."
    if apt-get update -qq; then
        success "软件源刷新完成"
    else
        error "软件源刷新失败，请检查网络或源地址"
        exit 1
    fi

    # 5. 安装指定版本的K8s组件
    step 3 4 "安装K8s核心组件（kubelet/kubeadm/kubectl）"
    info "安装目标版本：${deb_version}..."
    #调试 历史去掉-qq
    if apt-get install -y  --allow-downgrades\
        kubelet="$deb_version" \
        kubeadm="$deb_version" \
        kubectl="$deb_version"; then
        success "K8s组件安装完成（版本：${k8s_version}）"
    else
        error "K8s组件安装失败，可能原因："
        echo "  1. 版本 ${deb_version} 不存在（可执行 'apt-cache madison kubeadm' 查看可用版本）"
        echo "  2. 软件源配置错误（检查 /etc/apt/sources.list.d/kubernetes.list）"
        exit 1
    fi

    # 6. 配置kubelet（锁定版本+自启）
    info "锁定K8s组件版本（防止意外升级）..."
    apt-mark hold kubelet kubeadm kubectl > /dev/null
    success "K8s组件版本锁定完成"
    
    info "设置kubelet开机自启并启动..."
    if systemctl enable kubelet --now; then
        success "kubelet配置完成（已开机自启并启动）"
    else
        error "kubelet启动失败，请执行 'systemctl status kubelet' 检查原因"
        exit 1
    fi

    # 验证K8s组件安装
    info "验证K8s组件版本..."
    local kubelet_ver=$(kubelet --version | awk '{print $2}')
    success "K8s核心组件安装验证通过，版本：${kubelet_ver}"

    # 安装nerdctl（使用内网地址）
    install_nerdctl

    # 配置kubectl补全
    configure_kubectl_completion

    # 安装完成汇总
    echo -e "\n========================================"
    success "所有组件安装及配置全部完成！"
    echo -e "${YELLOW}[汇总信息]${NC}"
    echo "  - K8s版本：${k8s_version}"
    echo "  - nerdctl版本：$(nerdctl --version | awk '{print $3}')"
    echo "  - 下一步：执行 'kubeadm init' 初始化集群（需根据网络配置参数）"
    echo -e "========================================"
}


# ========================== 卸载相关函数 ==========================
# 卸载组件及配置（保留containerd）
uninstall_k8s() {
    # 二次确认（防止误操作）
    echo -e "\n${RED}[WARNING]${NC} 即将执行卸载操作，将移除以下内容："
    echo "  1. K8s组件：kubelet、kubeadm、kubectl"
    echo "  2. 工具：nerdctl"
    echo "  3. 配置：crictl配置、kubectl补全、K8s软件源及密钥"
    echo "  4. 数据目录：/var/lib/kubelet、/etc/kubernetes、/var/lib/etcd等"
    echo -e "${RED}注意：此操作不可逆，且会保留containerd！${NC}"
    read -p "请确认是否继续卸载？[y/N] " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        info "用户取消卸载操作，脚本退出"
        exit 0
    fi

    info "开始执行卸载流程，共6个步骤"

    # 1. 停止kubelet服务
    step 1 6 "停止kubelet服务"
    if systemctl is-active --quiet kubelet; then
        info "kubelet当前处于运行状态，正在停止..."
        if systemctl stop kubelet; then
            success "kubelet停止成功"
        else
            error "kubelet停止失败，将强制继续卸载"
        fi
    else
        info "kubelet已处于停止状态，跳过停止步骤"
    fi

    # 2. 卸载K8s组件
    step 2 6 "卸载K8s核心组件"
    if dpkg -l | grep -qE "kubelet|kubeadm|kubectl"; then
        info "检测到K8s组件，正在卸载..."
        if apt-get purge -y -qq kubelet kubeadm kubectl; then
            success "K8s组件卸载完成"
        else
            error "K8s组件卸载失败，建议手动执行 'apt-get purge -y kubelet kubeadm kubectl'"
            exit 1
        fi
    else
        info "未检测到K8s组件，跳过卸载步骤"
    fi

    # 3. 卸载nerdctl
    step 3 6 "卸载nerdctl"
    if command -v nerdctl &> /dev/null; then
        info "检测到nerdctl，正在卸载..."
        # 根据安装方式选择卸载方法（系统仓库或二进制）
        if dpkg -l | grep -q nerdctl; then
            # 系统仓库安装：apt卸载
            if apt-get purge -y -qq nerdctl; then
                success "nerdctl（系统仓库版）卸载完成"
            else
                error "nerdctl卸载失败"
                exit 1
            fi
        else
            # 二进制安装：删除文件
            if rm -f /usr/local/bin/nerdctl; then
                success "nerdctl（二进制版）删除完成"
            else
                error "nerdctl删除失败，建议手动执行 'rm -f /usr/local/bin/nerdctl'"
                exit 1
            fi
        fi
    else
        info "未检测到nerdctl，跳过卸载步骤"
    fi

    # 4. 清理依赖残留
    step 4 6 "清理系统依赖残留"
    info "执行autoremove清理无用依赖..."
    if apt-get autoremove -y -qq; then
        success "系统依赖残留清理完成"
    else
        error "依赖残留清理失败，建议手动执行 'apt-get autoremove -y'"
    fi

    # 5. 解锁版本锁定
    step 5 6 "解除版本锁定"
    info "解除K8s组件和nerdctl的版本锁定..."
    apt-mark unhold kubelet kubeadm kubectl nerdctl > /dev/null 2>&1 || true
    success "版本锁定解除完成（无锁定则跳过）"

    # 6. 清理配置文件和数据目录
    step 6 6 "清理配置文件与数据目录"
    local clean_items=(
        "/etc/apt/sources.list.d/kubernetes.list"          # K8s软件源
        "/etc/apt/keyrings/kubernetes-apt-keyring.gpg"    # K8s GPG密钥
        "/var/lib/kubelet"                                # kubelet数据目录
        "/etc/kubernetes"                                 # K8s配置目录
        "/var/lib/etcd"                                   # etcd数据目录（若存在）
        "/var/lib/cni"                                    # CNI网络配置
        "/etc/crictl.yaml"                                # crictl配置
        "/etc/profile.d/kubectl-completion.sh"            # kubectl补全脚本
    )

    for item in "${clean_items[@]}"; do
        if [ -e "$item" ]; then
            info "清理文件/目录：${item}"
            if rm -rf "$item"; then
                success "清理完成：${item}"
            else
                error "清理失败：${item}（权限不足？）"
            fi
        else
            info "文件/目录不存在，跳过：${item}"
        fi
    done

    # 刷新软件源（确保清理生效）
    info "刷新系统软件源，确保配置清理生效..."
    apt-get update -qq > /dev/null
    success "软件源刷新完成"

    # 卸载完成汇总
    echo -e "\n========================================"
    success "卸载流程全部完成！"
    echo -e "${YELLOW}[残留说明]${NC}"
    echo "  - 已保留：containerd及相关配置"
    echo "  - 建议：若需重新安装，直接执行 '--install' 选项即可"
    echo -e "========================================"
}


# ========================== 主逻辑 ==========================
main() {
    local install=0
    local uninstall=0
    local k8s_version=""

    # 解析命令行参数
    while [[ $# -gt 0 ]]; do
        case "$1" in
            --install)
                install=1
                shift
                ;;
            --uninstall)
                uninstall=1
                shift
                ;;
            --version)
                if [[ -z "$2" ]]; then
                    error "--version选项需指定K8s版本（如1.30.5）"
                    usage
                fi
                k8s_version="$2"
                shift 2
                ;;
            --help)
                usage
                ;;
            --script-version)
                echo "脚本版本：${SCRIPT_VERSION}"
                exit 0
                ;;
            *)
                error "未知参数：'$1'"
                usage
                ;;
        esac
    done

    # 检查参数冲突
    if [[ $install -eq 1 && $uninstall -eq 1 ]]; then
        error "不能同时指定--install和--uninstall选项"
        usage
    fi
    if [[ $install -eq 0 && $uninstall -eq 0 ]]; then
        error "必须指定--install（安装）或--uninstall（卸载）选项"
        usage
    fi

    # 检查root权限（安装/卸载均需）
    check_root

    # 处理安装逻辑
    if [[ $install -eq 1 ]]; then
        # 未指定版本则使用默认
        if [[ -z "$k8s_version" ]]; then
            k8s_version="$DEFAULT_K8S_VERSION"
            info "未指定K8s版本，使用默认版本：${k8s_version}"
        fi
        # 校验版本格式
        validate_version "$k8s_version"
        # 执行安装
        install_k8s "$k8s_version"
    fi

    # 处理卸载逻辑
    if [[ $uninstall -eq 1 ]]; then
        uninstall_k8s
    fi
}

# 启动主逻辑
main "$@"
