#!/bin/bash

set -e

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'
BOLD='\033[1m'

VERSION="1.2.1"
COPYRIGHT="版权归 OfoCa Space 所有 | https://blog.ofoca.net"

print_header() {
    clear
    echo -e "${CYAN}==============================================================================${NC}"
    echo -e "${BOLD}${CYAN}   内核自定义 RPM 打包工具 v${VERSION}${NC}"
    echo -e "${CYAN}   专为 CentOS/RHEL 8 设计的专业内核管理工具${NC}"
    echo -e "${CYAN}==============================================================================${NC}"
    echo -e "${MAGENTA}   ${COPYRIGHT}${NC}"
    echo -e "${CYAN}==============================================================================${NC}"
    echo ""
}

print_error() { echo -e "${RED}❌ 错误：$1${NC}"; }
print_success() { echo -e "${GREEN}✅ 成功：$1${NC}"; }
print_info() { echo -e "${BLUE}ℹ️  提示：$1${NC}"; }
print_warn() { echo -e "${YELLOW}⚠️  警告：$1${NC}"; }

check_root() {
    if [ "$EUID" -ne 0 ]; then
        print_error "请使用 root 权限运行此脚本 (例如：sudo ./kernel-packer.sh)"
        exit 1
    fi
}

detect_kernel_files() {
    [ -f "/boot/vmlinuz-$1" ] && return 0 || return 1
}

fix_missing_configs() {
    local ver=$1
    local src_dir="/root/linux-${ver}"
    local fixed=0

    if [ ! -f "/boot/config-${ver}" ]; then
        print_warn "未找到 /boot/config-${ver}，正在尝试修复..."
        if [ -f "${src_dir}/.config" ]; then
            cp "${src_dir}/.config" "/boot/config-${ver}"
            print_success "已从源码目录复制 .config"
            fixed=1
        else
            local found=$(find /root -name ".config" -path "*/linux-${ver}/*" 2>/dev/null | head -n 1)
            if [ -n "$found" ]; then
                cp "$found" "/boot/config-${ver}"
                print_success "已找到并复制 .config"
                fixed=1
            else
                print_error "无法找到 .config 文件，请先编译内核或指定路径"
                return 1
            fi
        fi
    fi

    if [ ! -f "/boot/System.map-${ver}" ]; then
        print_warn "未找到 /boot/System.map-${ver}，正在尝试修复..."
        if [ -f "${src_dir}/System.map" ]; then
            cp "${src_dir}/System.map" "/boot/System.map-${ver}"
            print_success "已从源码目录复制 System.map"
        else
            local found=$(find /root -name "System.map" -path "*/linux-${ver}/*" 2>/dev/null | head -n 1)
            [ -n "$found" ] && cp "$found" "/boot/System.map-${ver}" && print_success "已找到并复制 System.map"
        fi
    fi
    return 0
}

build_rpm() {
    local pkg_name=$1
    local version=$2
    local release=$3
    local summary=$4
    local packager=$5

    print_info "开始构建流程..."
    print_info "包名前缀 : ${pkg_name}"
    print_info "内核版本 : ${version}"
    print_info "Release  : ${release}"
    echo ""

    if ! command -v rpmbuild &> /dev/null; then
        echo -n "正在安装构建工具... "
        dnf install -y rpmdevtools rpm-build spectool > /dev/null 2>&1
        print_success "完成"
    else
        print_success "构建工具已就绪"
    fi

    # --- 修复路径逻辑 START ---
    # 强制使用当前实际用户的家目录，如果是 sudo root 运行，则直接用 /root
    if [ "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
        USER_HOME="/home/$SUDO_USER"
        # 如果该用户家目录不存在，回退到 /root
        if [ ! -d "$USER_HOME" ]; then
            USER_HOME="/root"
        fi
    else
        USER_HOME="/root"
    fi
    
    local build_root="${USER_HOME}/rpmbuild"
    
    # 确保目录结构存在
    mkdir -p "${build_root}"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
    
    # 如果是非 root 用户拥有的目录，修正权限以防后续 su 切换失败
    if [ "$USER_HOME" != "/root" ]; then
        chown -R "$SUDO_USER":"$(id -gn $SUDO_USER)" "${build_root}" 2>/dev/null || true
    fi
    # --- 修复路径逻辑 END ---

    local spec_file="${build_root}/SPECS/${pkg_name}.spec"
    print_info "生成 Spec 文件：${spec_file}"

    # 再次确认目录存在，防止罕见错误
    if [ ! -d "$(dirname "$spec_file")" ]; then
        print_error "无法创建目录：$(dirname "$spec_file")"
        exit 1
    fi

    cat > "${spec_file}" <<EOF
Name:           ${pkg_name}
Version:        ${version}
Release:        ${release}%{?dist}
Summary:        ${summary}
License:        GPL v2
Group:          System Environment/Kernel
URL:            https://www.kernel.org
BuildArch:      x86_64
Vendor:         OfoCa Space Custom Build
Packager:       ${packager}

%description
由 OfoCa Space 工具打包的自定义 Linux 内核 ${version}。
支持通过 rpm/dnf 进行安装、查询和卸载管理。
构建主机：$(hostname)
构建时间：$(date)

%prep
echo "正在准备打包文件..."

%build
echo "无需编译，使用预编译二进制文件。"

%install
rm -rf %{buildroot}
mkdir -p %{buildroot}/boot
mkdir -p %{buildroot}/lib/modules/${version}

cp /boot/vmlinuz-${version} %{buildroot}/boot/
[ -f /boot/config-${version} ] && cp /boot/config-${version} %{buildroot}/boot/
[ -f /boot/System.map-${version} ] && cp /boot/System.map-${version} %{buildroot}/boot/

if ls /boot/initramfs-${version}*.img 1> /dev/null 2>&1; then
    cp /boot/initramfs-${version}*.img %{buildroot}/boot/
fi

if [ -d "/lib/modules/${version}" ]; then
    cp -a /lib/modules/${version}/* %{buildroot}/lib/modules/${version}/
fi

%files
/boot/vmlinuz-${version}
%config(noreplace) /boot/config-${version}
%config(noreplace) /boot/System.map-${version}
/boot/initramfs-${version}*.img
/lib/modules/${version}

%changelog
* $(date '+%a %b %d %Y') ${packager} - ${version}-${release}
- 由 OfoCa Space 内核打包工具 v${VERSION} 自动构建
- 自定义构建版本 ${version}
EOF

    print_info "正在编译 RPM 包..."
    cd "${build_root}"
    
    # 打印调试信息（可选，出错时很有用）
    # echo "DEBUG: Build Root = ${build_root}"
    # echo "DEBUG: Spec File = ${spec_file}"
    # ls -l "${spec_file}"

    if [ "$USER_HOME" != "/root" ] && [ "$SUDO_USER" ] && [ "$SUDO_USER" != "root" ]; then
        # 切换到普通用户执行构建，避免 root 权限污染文件
        su - "$SUDO_USER" -c "cd ${build_root} && rpmbuild -bb SPECS/${pkg_name}.spec --define '_topdir ${build_root}'"
    else
        # 直接在 root 下执行
        rpmbuild -bb SPECS/${pkg_name}.spec --define "_topdir ${build_root}"
    fi

    local rpm_file=$(find "${build_root}/RPMS" -name "${pkg_name}-${version}-${release}*.rpm" | head -n 1)
    
    if [ -z "$rpm_file" ]; then
        print_error "构建失败！未生成 RPM 文件。"
        print_error "请检查日志或手动运行：rpmbuild -bb ${spec_file}"
        exit 1
    fi

    print_success "RPM 构建成功：$(basename $rpm_file)"
    
    echo ""
    echo -n "是否立即安装此 RPM？(将覆盖现有文件) [y/N]: "
    read -r confirm
    if [[ "$confirm" =~ ^[Yy]$ ]]; then
        print_info "正在安装 RPM (强制替换)..."
        rpm -ivh --replacefiles --replacepkgs "$rpm_file"
        print_success "安装完成！"
        
        echo ""
        print_info "验证信息："
        rpm -qi "$pkg_name" | grep -E "Name|Version|Release|Install Date|Packager|Summary"
    else
        print_info "已跳过安装。RPM 文件位于：$rpm_file"
        print_info "稍后你可以手动安装：rpm -ivh --replacefiles $rpm_file"
    fi
}

cleanup_rpm_menu() {
    check_root
    echo ""
    echo -e "${RED}--- 清理/移除模式 ---${NC}"
    echo "当前已安装的非官方内核包:"
    rpm -qa | grep "^kernel-" | grep -v "4.18" | grep -v "tools" | grep -v "headers" | grep -v "modules-core" || echo "未找到。"
    echo ""
    
    echo -n "输入要操作的包名前缀 (例如 kernel-ml): "
    read -r del_name
    
    if [ -z "$del_name" ]; then
        print_error "包名不能为空。"
        return
    fi
    
    local del_ver=$(rpm -q --qf '%{VERSION}' "$del_name" 2>/dev/null)
    if [ -z "$del_ver" ]; then
        echo -n "未在数据库中找到版本，请手动输入版本 (例如 6.19.4): "
        read -r del_ver
    fi
    [ -z "$del_ver" ] && del_ver="6.19.4"

    echo ""
    echo -e "${BOLD}请选择操作方式：${NC}"
    echo -e "  ${RED}1)${NC} 完全删除 (移除记录 + 删除文件)"
    echo -e "  ${YELLOW}2)${NC} 仅移除记录 (保留文件)"
    echo -e "  ${CYAN}0)${NC} 取消"
    echo -n "请输入选项 [0-2]: "
    read -r cleanup_choice

    case $cleanup_choice in
        1)
            print_warn "警告：这将永久删除内核文件！"
            echo -n "确认删除？输入 'YES_DELETE'： "
            read -r confirm
            if [ "$confirm" == "YES_DELETE" ]; then
                rpm -e --nodeps "$del_name" 2>/dev/null && print_success "已从数据库移除包记录。" || print_info "包记录不存在。"
                rm -f /boot/vmlinuz-${del_ver}*
                rm -f /boot/config-${del_ver}*
                rm -f /boot/System.map-${del_ver}*
                rm -f /boot/initramfs-${del_ver}*
                rm -rf /lib/modules/${del_ver}
                print_success "相关文件已彻底清理。"
            else
                print_info "操作已取消。"
            fi
            ;;
        2)
            print_warn "注意：文件将保留在磁盘上，但系统将不再通过 RPM 管理它们。"
            echo -n "确认仅移除记录？ [Y/n]: "
            read -r confirm
            if [[ "$confirm" =~ ^[Yy]$ ]] || [ -z "$confirm" ]; then
                rpm -e --nodeps "$del_name" 2>/dev/null && print_success "已成功移除 RPM 记录，文件已保留。" || print_info "包记录不存在，无需移除。"
                print_info "文件位置："
                echo "  - /boot/vmlinuz-${del_ver}*"
                echo "  - /lib/modules/${del_ver}/"
            else
                print_info "操作已取消。"
            fi
            ;;
        0)
            print_info "已取消。"
            ;;
        *)
            print_error "无效选项。"
            ;;
    esac
}

get_latest_custom_kernel() {
    local latest=""
    for file in /boot/vmlinuz-*; do
        [ -e "$file" ] || continue
        local fname=$(basename "$file")
        local ver_str=${fname#vmlinuz-}
        
        if [[ $ver_str =~ ^([0-9]+\.[0-9]+\.[0-9]+) ]]; then
            local clean_ver="${BASH_REMATCH[1]}"
            if [[ $clean_ver == 4.18* ]]; then
                continue
            fi
            if [ -z "$latest" ]; then
                latest="$clean_ver"
            else
                local higher=$(echo -e "$clean_ver\n$latest" | sort -V | tail -n1)
                if [ "$higher" == "$clean_ver" ]; then
                    latest="$clean_ver"
                fi
            fi
        fi
    done
    
    if [ -z "$latest" ]; then
        echo "6.19.4"
    else
        echo "$latest"
    fi
}

main_menu() {
    while true; do
        print_header
        
        local detected_ver=$(get_latest_custom_kernel)
        
        echo -e "${BOLD}请选择一个操作：${NC}"
        echo -e "  ${GREEN}1)${NC} 全新生成 (版本：${detected_ver})"
        echo -e "  ${CYAN}2)${NC} 自定义构建"
        echo -e "  ${RED}3)${NC} 删除 / 清理"
        echo -e "  ${YELLOW}0)${NC} 退出"
        echo ""
        echo -e "${MAGENTA}   ${COPYRIGHT}${NC}"
        echo -e "${CYAN}==============================================================================${NC}"
        echo -n "请输入选项 [0-3]: "
        
        read -r choice
        
        case $choice in
            1)
                local ver=$detected_ver
                if ! detect_kernel_files "$ver"; then
                    print_error "未在 /boot 中找到版本为 $ver 的内核文件。请先编译内核。"
                    read -p "按回车键返回..."
                    continue
                fi
                
                if ! fix_missing_configs "$ver"; then
                    read -p "按回车键返回..."
                    continue
                fi
                
                local def_name="kernel-ml"
                local def_rel="1.el8.elrepo"
                
                echo ""
                print_info "检测到内核版本：${ver}"
                print_info "目标 RPM 名称：${def_name}-${ver}-${def_rel}.el8.x86_64"
                echo -n "确认构建？ [Y/n]: "
                read -r conf
                if [[ "$conf" =~ ^[Nn]$ ]]; then continue; fi
                
                build_rpm "$def_name" "$ver" "$def_rel" "主线内核 ${ver} (ELRepo 风格)" "$(whoami)@$(hostname)"
                read -p "按回车键返回..."
                ;;
                
            2)
                echo ""
                echo -e "${BOLD}--- 自定义配置 ---${NC}"
                
                echo -n "内核版本 (默认 ${detected_ver}): "
                read -r c_ver
                [ -z "$c_ver" ] && c_ver=$detected_ver
                
                if ! detect_kernel_files "$c_ver"; then
                    print_error "未找到版本 $c_ver 的文件。尝试修复..."
                    if ! fix_missing_configs "$c_ver"; then
                        read -p "按回车键返回..."
                        continue
                    fi
                fi
                
                echo -n "包名前缀 (例如 kernel-ml): "
                read -r c_name
                [ -z "$c_name" ] && c_name="kernel-custom"
                
                echo -n "Release 标签 (例如 1.el8.elrepo): "
                read -r c_rel
                [ -z "$c_rel" ] && c_rel="1.el8.custom"
                
                echo -n "简要描述: "
                read -r c_sum
                [ -z "$c_sum" ] && c_sum="自定义编译内核 ${c_ver}"
                
                echo -n "打包者信息: "
                read -r c_pack
                [ -z "$c_pack" ] && c_pack="$(whoami)@$(hostname)"
                
                echo ""
                print_info "配置摘要:"
                echo "  名称 : ${c_name}-${c_ver}-${c_rel}"
                echo "  版本 : ${c_ver}"
                echo -n "确认构建？ [Y/n]: "
                read -r conf
                if [[ "$conf" =~ ^[Nn]$ ]]; then continue; fi
                
                build_rpm "$c_name" "$c_ver" "$c_rel" "$c_sum" "$c_pack"
                read -p "按回车键返回..."
                ;;
                
            3)
                cleanup_rpm_menu
                read -p "按回车键返回..."
                ;;
                
            0)
                echo -e "${GREEN}退出程序。感谢使用 OfoCa Space 工具！${NC}"
                echo -e "${MAGENTA}   ${COPYRIGHT}${NC}"
                exit 0
                ;;
                
            *)
                print_error "无效选项，请重试。"
                sleep 1
                ;;
        esac
    done
}

main_menu