#!/bin/bash
set -o pipefail

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

# ====================== 自动获取内核版本（全局变量，全脚本复用） ======================
# 1. 获取当前源码将要编译的内核版本（如 6.18.7）
get_kernel_source_ver() {
    if [ ! -f "Makefile" ]; then echo "unknown"; return 1; fi
    local v=$(awk '/^VERSION =/ {print $3}' Makefile)
    local p=$(awk '/^PATCHLEVEL =/ {print $3}' Makefile)
    local s=$(awk '/^SUBLEVEL =/ {print $3}' Makefile)
    echo "${v}.${p}.${s}"
}

# 2. 获取当前系统正在使用的内核配置版本（如 6.12.65-amd64-desktop-rolling）
get_running_config_ver() {
    echo "$(uname -r)"
}

# 定义全局版本变量
KERNEL_SOURCE_VER=$(get_kernel_source_ver)
KERNEL_CONFIG_VER=$(get_running_config_ver)
CONFIG_FILE="/boot/config-${KERNEL_CONFIG_VER}"

# ====================== 日志函数（原样保留） ======================
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"
}

# ====================== 依赖检查（原样保留） ======================
check_and_install_dependencies() {
    log_info "开始检查内核编译依赖包..."
    
    local dependencies=(
    "gcc" "make" "libncurses-dev" "flex" "bison" "libssl-dev"
    "bc" "build-essential" "zstd" "libelf-dev" "git" "debhelper"
    "pahole" "openssl" "dwarves"
    "libc6-dev" "fakeroot" "dpkg-dev" "libtool" "autoconf" "automake"
    "libdw-dev"  "rsync"
)
    
    local missing_deps=()
    for dep in "${dependencies[@]}"; do
        if ! dpkg-query -W -f='${Status}' "$dep" 2>/dev/null | grep -q "install ok installed"; then
            log_warning "✗ $dep 未安装"
            missing_deps+=("$dep")
        else
            log_success "✓ $dep 已安装"
        fi
    done
    
    if [ ${#missing_deps[@]} -gt 0 ]; then
        log_info "发现 ${#missing_deps[@]} 个缺失依赖包：${missing_deps[*]}"
        log_info "开始自动安装缺失依赖..."
        apt update -y || log_warning "软件源更新出现警告，继续尝试安装"
        apt install -y "${missing_deps[@]}" || { log_error "依赖安装失败"; exit 1; }
        log_success "依赖安装完成"
    else
        log_success "所有必需依赖均已安装"
    fi
    
    # 关键版本验证
    log_info "\n关键工具版本验证："
    for tool in gcc make; do
        if command -v $tool &>/dev/null; then
            log_info "  $tool: $($tool --version | head -n1 | awk '{print $NF}')"
        fi
    done
}

# ====================== 预清理（原样保留） ======================
pre_cleanup() {
    log_info "\n开始预清理编译残留文件..."
    log_warning "此操作将删除之前的编译产物和配置文件"
    
    [ ! -f "Makefile" ] && { log_error "未找到Makefile，请在内核源码目录执行"; exit 1; }
    
    log_info "执行: make clean"
    make clean &>/dev/null && log_success "make clean 完成" || log_warning "make clean 执行完毕（含原有残留清理）"
    
    log_info "执行: make mrproper"
    make mrproper && log_success "make mrproper 完成" || { log_error "make mrproper 失败"; exit 1; }
    
    log_success "预清理完成，源码目录已恢复干净状态"
}

# ====================== 复制当前内核配置 + 完整性校验 ======================
copy_current_config() {
    log_info "\n正在复制当前运行内核配置: ${CONFIG_FILE}"
    
    [ ! -f "$CONFIG_FILE" ] && {
        log_error "未找到系统内核配置文件：${CONFIG_FILE}"
        exit 1
    }
    
    cp "$CONFIG_FILE" .config || { log_error "复制配置文件失败"; exit 1; }
    
    log_info "验证配置文件完整性..."
    if ! make silentoldconfig &>/dev/null; then
        log_warning "配置文件存在兼容性警告，尝试自动修复适配 ${KERNEL_SOURCE_VER} 内核..."
        yes "" | make olddefconfig &>/dev/null
        log_warning "已自动完成配置项兼容修复，可继续后续流程"
    else
        log_success "配置文件完整性验证通过"
    fi
    
    log_success "当前系统内核配置已完成复制与适配"
}

# ====================== 配置更新（原样保留） ======================
update_config() {
    log_info "\n统一更新并确认 ${KERNEL_SOURCE_VER} 内核全部配置项..."
    yes "" | make olddefconfig &>/dev/null
    log_success "内核配置已全部更新完成"
}

# ====================== 仅本机硬件驱动配置（补全你提供的详细说明） ======================
localmodconfig_setup() {
    log_info "\n============================================="
    log_info "           仅编译本机硬件驱动配置选项           "
    log_info "============================================="
    # 补全你提供的功能原理
    log_info "【功能原理】"
    log_info "  make localmodconfig 会扫描当前系统："
    log_info "  1. /proc/modules (已加载的驱动模块)"
    log_info "  2. /sys/devices (已识别的硬件设备)"
    log_info "  自动删除.config中所有非本机硬件的驱动配置，仅保留当前硬件所需驱动"
    
    # 补全你提供的核心优势
    log_info "\n【核心优势】"
    log_info "  ✓ 编译时间减少50%-80%（无需编译无用驱动）"
    log_info "  ✓ 生成的内核体积减小60%以上"
    log_info "  ✓ 系统运行时内存/磁盘占用更低"
    
    # 补全你提供的重要禁忌/注意事项
    log_warning "\n【重要禁忌/注意事项】"
    log_warning "  ❗ 执行前必须接好所有常用外设（U盘、打印机、蓝牙设备等），否则对应驱动会被剔除"
    log_warning "  ❗ 不要在虚拟机/容器中执行此操作（会识别虚拟硬件，物理机使用时驱动缺失）"
    log_warning "  ❗ 若后续新增硬件（如网卡、显卡），需重新编译内核并再次执行此配置"
    log_warning "  ❗ Deepin 25对内核版本有兼容性要求，建议使用官方适配的内核源码"
    log_warning "  ❗ 执行后仍可通过make menuconfig手动补加需要的驱动配置"
    
    # 保留自动版本差异警告
    if [ "$KERNEL_SOURCE_VER" != "$KERNEL_CONFIG_VER" ]; then
        log_warning ""
        log_warning "  ❗ 你当前编译 ${KERNEL_SOURCE_VER} 内核，配置来自 ${KERNEL_CONFIG_VER}，版本差异"
        log_warning "  ❗ 跨版本使用 localmodconfig 可能出现配置异常，建议谨慎选择"
        log_warning "  ❗ 如非必要，建议选择 N，使用完整配置编译更稳定"
    fi
    log_info "=============================================\n"
    
    read -p "是否启用【仅编译本机现有硬件驱动】？(y/N) " -n 1 -r
    echo
    
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        log_info "开始执行 make localmodconfig，仅保留本机硬件驱动..."
        cp .config .config.bak.$(date +%Y%m%d%H%M%S)
        log_info "已备份当前配置至 .config.bak.*"
        
        if yes "" | make localmodconfig; then
            log_success "localmodconfig 执行完成，已仅保留本机硬件驱动配置"
        else
            log_error "localmodconfig 执行失败"
            read -p "是否继续使用完整配置编译？(y/N) " -n 1 -r
            echo
            [[ ! $REPLY =~ ^[Yy]$ ]] && { log_info "用户取消，脚本退出"; exit 0; }
            log_warning "将继续使用完整配置进行编译"
        fi
    else
        log_info "已选择不启用仅本机驱动编译，保留完整驱动配置"
    fi
}

# ====================== 手动配置调整（原样保留） ======================
manual_config() {
    log_info "\n============================================="
    log_info "               手动内核配置调整               "
    log_info "============================================="
    read -p "是否需要手动打开 menuconfig 调整内核配置？(y/N) " -n 1 -r
    echo
    
    if [[ $REPLY =~ ^[Yy]$ ]]; then
        log_info "启动内核配置界面：make menuconfig"
        log_info "操作说明：方向键导航，空格选中/取消，Tab 切换，保存后 Exit 退出"
        make menuconfig
        log_success "手动配置已完成并保存"
    else
        log_info "跳过手动配置，使用当前自动生成的配置"
    fi
}

# ====================== 编译内核并打包 deb ======================
build_kernel() {
    local cpu_cores=$(nproc)
    log_info "\n============================================="
    log_info "              开始编译 ${KERNEL_SOURCE_VER} 内核              "
    log_info "============================================="
    log_info "检测到 CPU 核心数：${cpu_cores}，使用 -j${cpu_cores} 并行编译"
    log_info "编译命令：make bindeb-pkg -j${cpu_cores}"
    
    # 自动版本警告
    log_warning ""
    log_warning "注意：编译 ${KERNEL_SOURCE_VER} 内核可能需要 1-3 小时，请耐心等待..."
    log_warning "编译期间请勿关闭终端、勿执行高负载任务，避免编译中断"
    log_warning "若编译卡死或失败，可尝试降低并行数（如 -j4）重新编译"
    log_info "=============================================\n"
    
    if make bindeb-pkg -j${cpu_cores}; then
        log_success "${KERNEL_SOURCE_VER} 内核编译 && deb 包生成完成！"
        log_info "\n生成的 deb 包位于上级目录："
        ls -lh ../*.deb 2>/dev/null || log_warning "未在上级目录找到 deb 包，请检查编译路径"
    else
        log_error "${KERNEL_SOURCE_VER} 内核编译失败！"
        read -p "是否查看最后 100 行错误日志？(y/N) " -n 1 -r
        echo
        [[ $REPLY =~ ^[Yy]$ ]] && tail -n 100 logs.txt 2>/dev/null || tail -n 100 Makefile.log 2>/dev/null
        exit 1
    fi
}

# ====================== 主函数（完整流程） ======================
main() {
    clear
    echo "============================================="
    echo "           Deepin 内核编译与 deb 打包脚本           "
    echo "============================================="
    log_info "待编译内核版本：${KERNEL_SOURCE_VER}"
    log_info "系统配置来源版本：${KERNEL_CONFIG_VER}"
    if [ "$KERNEL_SOURCE_VER" != "$KERNEL_CONFIG_VER" ]; then
        log_warning "检测到跨大版本编译，存在配置兼容风险，脚本已启用自动适配"
    fi
    echo "=============================================\n"
    
    # root 权限检查
    [ "$(id -u)" -ne 0 ] && { log_error "请使用 sudo 权限执行此脚本"; exit 1; }
    
    # 源码目录检查
    [ ! -f "Makefile" ] && { log_error "请进入内核源码根目录再执行脚本"; exit 1; }
    
    read -p "确认开始内核编译流程？(y/N) " -n 1 -r
    echo
    [[ ! $REPLY =~ ^[Yy]$ ]] && { log_info "用户取消，脚本退出"; exit 0; }
    
    # 执行完整流程 - 调整顺序为：配置复制 -> update_config -> 本机驱动优化 -> 手动配置
    check_and_install_dependencies
    pre_cleanup
    copy_current_config
    update_config
    localmodconfig_setup
    manual_config
    build_kernel
    
    log_info "\n============================================="
    log_success "全部流程执行完毕！"
    log_info "安装命令：sudo dpkg -i ../linux-image-*.deb ../linux-headers-*.deb"
    log_info "安装后执行：sudo update-grub && reboot 生效新内核"
    log_info "============================================="
}

# 启动脚本
main "$@"