#!/bin/bash

# 根据调用名称确定使用哪个原始命令
SCRIPT_NAME=$(basename "$0")
if [ "$SCRIPT_NAME" = "apt-get" ]; then
    ORIGINAL_CMD="/usr/bin/apt-get.orig"
elif [ "$SCRIPT_NAME" = "apt" ]; then
    ORIGINAL_CMD="/usr/bin/apt.orig"
else
    ORIGINAL_CMD="/usr/bin/apt.orig"  # 默认使用apt.orig
fi

hostname=$(hostname)
apt_cache_dir="/tmp/kysdk-package/apt-cache"

log() {
    timestamp=$(date -Iseconds)
    logger -t "apt_wrapper" "${timestamp} ${hostname} apt_wrapper: $1"
}

parse_apt_args() {
    local -n __packages=$1
    local -n __options=$2
    shift 2
    
    __packages=()
    __options=()
    
    while [ $# -gt 0 ]; do
        case "$1" in
            -o|--option|-c|--config-file)
                __options+=("$1")
                shift
                # 检查下一个参数是否存在且不是选项
                if [ $# -gt 0 ] && [[ ! "$1" =~ ^- ]]; then
                    __options+=("$1")
                    shift
                else
                    log "警告: 选项 $1 需要参数"
                fi
                ;;
            
            -*)
                __options+=("$1")
                shift
                ;;
            
            *)
                __packages+=("$1")
                shift
                ;;
        esac
    done
}


# 判断是否在 Live Build 环境的函数 (POSIX 兼容)
is_live_build() {
    if [ -d "/lib/live" ] || [ -d "/usr/lib/live" ]; then
        log "检测到Live Build环境: 存在/lib/live或/usr/lib/live"
        return 0
    fi
    
    if grep -q "boot=live" /proc/cmdline 2>/dev/null; then
        log "检测到Live Build环境: 内核参数包含boot=live"
        return 0
    fi
    
    if [ -e "/etc/live" ] || [ -e "/lib/live/mount/medium" ] || [ -e "/var/lib/live" ]; then
        log "检测到Live Build环境: 存在Live标志文件"
        return 0
    fi
    
    if [ -n "$LIVE_BUILD" ] || [ -n "$LB_BUILD_IMAGE" ]; then
        log "检测到Live Build环境: 存在Live环境变量"
        return 0
    fi
    
    return 1
}


# 判断是否为 Live CD 环境的函数（POSIX 兼容）
is_live_cd() {
    if grep -q "boot=casper" /proc/cmdline 2>/dev/null; then
        log "检测到Live CD环境: 内核参数包含boot=casper"
        return 0
    fi

    return 1
}

is_normal_mode() {
    boot_mode=$(gdbus call --system \
        -d com.kylin.MaintainMode \
        -o /com/kylin/MaintainMode/Object \
        -m com.kylin.MaintainMode.interface.GetBootMode 2>/dev/null | awk -F\' '{print $2}' 2>/dev/null)

    if [ "$boot_mode" = "normal" ]; then
        log "检测到normal模式"
        return 0
    fi
    
    log "当前不是normal模式: $boot_mode"
    return 1
}

# 判断是否在 unshare -m 创建的挂载命名空间中（POSIX 兼容）
is_unshare_mount_ns() {
    if [ ! -e "/proc/self/ns/mnt" ] || [ ! -e "/proc/1/ns/mnt" ]; then
        return 1
    fi
    
    current_mnt_ns=$(readlink /proc/self/ns/mnt 2>/dev/null)
    init_mnt_ns=$(readlink /proc/1/ns/mnt 2>/dev/null)
    
    if [ -z "$current_mnt_ns" ] || [ -z "$init_mnt_ns" ]; then
        return 1
    fi
    
    if [ "$current_mnt_ns" != "$init_mnt_ns" ]; then
        log "检测到unshare -m挂载命名空间: 当前命名空间($current_mnt_ns) != init命名空间($init_mnt_ns)"
        return 0
    fi
    
    return 1
}

# 检查是否应该执行操作
should_execute_operation() {
    # 如果在unshare空间，执行原生命令
    if is_unshare_mount_ns; then
        log "检测到unshare -m命名空间，执行原生命令"
        return 1
    fi

    # 如果不是Live Build环境 且 不是chroot环境 且 不是Live CD环境 且 是normal模式
    if ! is_live_build && ! $(ischroot) && ! is_live_cd && is_normal_mode; then
        log "满足所有条件: 非Live Build、非chroot、非Live CD、normal模式"
        return 0  # 应该执行操作
    fi
    
    # 记录不满足的具体条件
    if is_live_build; then
        log "不满足条件: 当前是Live Build环境"
    fi
    
    if $(ischroot); then
        log "不满足条件: 当前是chroot环境"
    fi
    
    if is_live_cd; then
        log "不满足条件: 当前是Live CD环境"
    fi
    
    if ! is_normal_mode; then
        log "不满足条件: 当前不是normal模式"
    fi
    
    return 1  # 不应该执行操作
}

# 成功搜索返回0 否则返回1
# 用户模式下dpkg -l结果由kypkg_list提供
pkg_in_sys()
{
    package_name=$1
    res=`dpkg -l | grep "^ii[[:space:]]\+${package_name}[[:space:]]"`
    return_code=$?
    # 如果为kare软件包 $4的值为 kare_v10sp1或 kare_shadow
    # 这两个值由sdk接口提供
    echo $res | awk '{print $4}'
    return $return_code
}

# 专门处理带选项的卸载操作
handle_remove_with_options() {
    local operation=$1
    shift
    local options=()
    local packages=()
    
    parse_apt_args packages options "$@"
    options+=("-y")
    log "处理带选项的安装: options=[${options[*]}], packages=[${packages[*]}]"

    #如果包是空的直接general处理
    if [ ${#packages[@]} -eq 0 ] ; then
        log "kypackage_general传入参数: ${options[*]}"
        /usr/bin/kypackage_general apt.orig "${operation}" "${options[@]}"
        return 0
    fi
    #is a non-privileged package and cannot be uninstalled
    for package_name in "${packages[@]}"; do
        pkg_env=$(pkg_in_sys $package_name)
        pkg_status=$?
        if [ $pkg_status -ne 0 ];then
            printf "软件包 ${package_name} 未安装，所以不会被卸载\n"
        else
            # 检查包是否存在，如果存在则执行kare -P
            if [[ $pkg_env = "kare_"* ]]; then
                log "检测到kare环境包 ${package_name}，环境为 ${pkg_env}"
                /usr/bin/kypackage_remove "${package_name}"
            # kconf2读取的包列表带单引号，比较时也应添加单引号
            elif is_in_white_list ${package_name} || is_in_privilege_list \'${package_name}\'; then
                log "检测到特权包 ${package_name}, 使用原生apt"
                /usr/bin/kypackage_desktop  "--remove" $package_name
                /usr/bin/kypackage_general apt.orig "${operation}" "${options[@]}" "${package_name}"
                local search_result=$(dpkg -l | grep "^ii[[:space:]]\+${package_name}[[:space:]]" 2>/dev/null)
                if [ -z "$search_result" ]; then
                    printf "卸载成功，软件包已从核心系统中移除\n"
                fi
            else
                printf "当前模式下,非特权包不允许卸载\n"
            fi
        fi
    done
    return 0
}

# 专门处理带选项的安装操作
# 注意！先不考虑通配符号支持，是通过apt源码中的CacheSetHelper::PackageFromFnmatch函数实现的，脚本中实现困难
handle_install_with_options() {
    #参数解析
    local operation=$1
    shift
    local options=()
    local packages=()
    
    parse_apt_args packages options "$@"
    options+=("-y")
    log "处理带选项的安装: options=[${options[*]}], packages=[${packages[*]}]"

    #如果包是空的直接general处理
    if [ ${#packages[@]} -eq 0 ] ; then
        log "kypackage_general传入参数: ${options[*]}"
        /usr/bin/kypackage_general apt.orig ${operation} "${options[@]}"
        return 0
    fi

    # 1.区分.deb文件和包名
    local deb_packages=()
    local apt_packages=()
    
    for pkg in "${packages[@]}"; do
        if [[ "$pkg" == *.deb ]]; then
            deb_packages+=("$pkg")
        else
            apt_packages+=("$pkg")
        fi
    done
    
    # 处理.deb文件，使用dpkg安装
    if [ ${#deb_packages[@]} -gt 0 ]; then
        log "处理本地deb包: [${deb_packages[*]}]"
        for deb_file in "${deb_packages[@]}"; do
            absolute_path=$(realpath "$deb_file" 2>/dev/null)
            if [ -f "$absolute_path" ]; then
                log "分析本地软件包: $absolute_path"
                result=$(/usr/bin/kypackage_check "$absolute_path")
                if [[ "$result" =~ "将要安装的环境为kare v11" ]]; then
                    if is_package_installed_in_sys "$absolute_path" ; then
                        printf "软件包已安装在kare v11容器中\n"
                    else
                        log "通过kare安装本地软件包: $absolute_path"
                        /usr/bin/kypackage_inst "$absolute_path"
                    fi
                elif [[ "$result" =~ "将要安装的环境为kare v10sp1" ]]; then
                    if is_package_installed_in_sys "$absolute_path" ; then
                        printf "软件包已安装在kare v10sp1容器中\n"
                    else
                        log "通过kare安装本地软件包: $absolute_path"
                        /usr/bin/kypackage_inst "$absolute_path"
                    fi
                else
                    if is_package_installed_in_sys "$absolute_path" ; then
                        printf "软件包已安装在核心系统中\n"
                    else
                        package_name="$(dpkg-deb -f "$absolute_path" Package)"
                        log "通过kypackage_general安装本地软件包: $absolute_path"

                        if ! kylinsigntool -v $absolute_path > /dev/null;then
                            echo "麒麟签名验证不通过，安装失败"
                            return 1
                        else
                            echo "麒麟签名验证通过"
                        fi

                        # 区分白名单包和特权标签包
                        if is_in_white_list ${package_name};then
                            switch_status=$(get_whitelist_runtime_check)
                            switch_return=$?
                            if [ $switch_return -eq 0 ];then
                                if [[ $switch_status == 'true' ]];then
                                    init_tmpdir
                                    uncompress_deb_to_tmp ${absolute_path}
                                    uncompress_status=$?
                                    if [ $uncompress_status -eq 0 ];then
                                        runtime_version=$(get_compat_field_value $tmpdir runtime_version)
                                        if [[ $runtime_version != *v11* ]] && [[ $runtime_version != *ok2* ]];then
                                            echo "软件包标签匹配失败"
                                            del_tmpdir
                                            return 1
                                        fi
                                    else
                                        echo "解压软件包失败"
                                        del_tmpdir
                                        return 1
                                    fi
                                    del_tmpdir
                                fi
                            else
                                echo "获取白名单开关失败"
                                return 1
                            fi
                        else
                            # 特权标签包
                            switch_status=$(get_privilege_runtime_check)
                            switch_return=$?
                            if [ $switch_return -eq 0 ];then
                                if [[ $switch_status == 'true' ]];then
                                    init_tmpdir
                                    uncompress_deb_to_tmp ${absolute_path}
                                    uncompress_status=$?
                                    if [ $uncompress_status -eq 0 ];then
                                        runtime_version=$(get_compat_field_value $tmpdir runtime_version)
                                        if [[ $runtime_version == *v11* ]] || [[ $runtime_version == *ok2* ]];then
                                            # 验签
                                            bare_metal=$(get_compat_field_value $tmpdir bare_metal)
                                            if [[ $bare_metal == "yes" ]];then
                                                local plaintxt="${tmpdir}/plain.txt"
                                                local signtxt="${tmpdir}/sign.txt"
                                                local signtxtsig="${signtxt}.sig"
                                                data_size=$(get_data_size_in_deb ${absolute_path})
                                                deb_sha512=$(get_deb_sha512sum $data_size $absolute_path)
                                                echo -n "${deb_sha512}${bare_metal}" > $plaintxt
                                                bare_metal_sig=$(get_compat_field_value $tmpdir bare_metal_sig)
                                                echo -n ${bare_metal_sig} > $signtxt
                                                base64 -d $signtxt > $signtxtsig
                                                import_gpg_key
                                                gpg_verify $signtxtsig $plaintxt
                                                verify_status=$?
                                                if [ $verify_status -ne 0 ];then
                                                    echo gpg验签失败
                                                    unset_gpg
                                                    return 1
                                                fi
                                                unset_gpg
                                            else
                                                echo "软件包内无标签"
                                                return 1
                                            fi
                                        else
                                            echo "软件包标签匹配失败"
                                            del_tmpdir
                                            return 1
                                        fi
                                    else
                                        echo "解压软件包失败"
                                        del_tmpdir
                                        return 1
                                    fi
                                    del_tmpdir
                                fi
                            else
                                echo "获取特权标签开关失败"
                                return 1
                            fi
                        fi

                        /usr/bin/kypackage_general apt.orig install "${options[@]}" "$absolute_path"
                        if is_package_installed_in_sys "$absolute_path" ; then
                            /usr/bin/kypackage_desktop "--create" "$absolute_path"
                            add_to_privilege_list $package_name
                            printf "安装成功，安装的环境为核心系统\n"
                        fi
                    fi
                fi
            else
                log "错误: 文件不存在 $absolute_path"
            fi
        done
    fi
    
    # 处理远程包名，使用apt下载后安装
    if [ ${#apt_packages[@]} -gt 0 ]; then
        if [ ! -d $apt_cache_dir ]; then
            mkdir -p $apt_cache_dir
        fi
        pushd $apt_cache_dir > /dev/null
        if [ $? -ne 0 ]; then
            log "路径切换失败，退出！"
            return 1
        fi
        apt.orig download "${apt_packages[@]}"

        # 2.逐个包判断安装策略
        for file in *.deb; do
            if [ -f "$file" ]; then
                log "分析软件包: $file"
                deb_name=$(realpath "$file")
                result=$(/usr/bin/kypackage_check $deb_name)
                if [[ "$result" =~ "将要安装的环境为kare v11" ]]; then
                    if is_package_installed_in_sys "$deb_name" ; then
                        printf "软件包已安装在kare v11容器中\n"
                    else
                        log "通过kare安装软件包:${deb_name}"
                        /usr/bin/kypackage_inst "${deb_name}"
                    fi
                elif [[ "$result" =~ "将要安装的环境为kare v10sp1" ]]; then
                    if is_package_installed_in_sys "$deb_name" ; then
                        printf "软件包已安装在kare v10sp1容器中\n"
                    else
                        log "通过kare安装软件包:${deb_name}"
                        /usr/bin/kypackage_inst "${deb_name}"
                    fi
                else
                    if is_package_installed_in_sys "$deb_name" ; then
                        printf "软件包已安装在核心系统中\n"
                    else
                        package_name="$(dpkg-deb -f ${deb_name} Package)"
                        log "通过kypackage_general安装软件包:${package_name}"

                        if ! kylinsigntool -v $deb_name > /dev/null;then
                            echo "麒麟签名验证不通过，安装失败"
                            return 1
                        else
                            echo "麒麟签名验证通过"
                        fi

                        # 区分白名单包和特权标签包
                        if is_in_white_list ${package_name};then
                            switch_status=$(get_whitelist_runtime_check)
                            switch_return=$?
                            if [ $switch_return -eq 0 ];then
                                if [[ $switch_status == 'true' ]];then
                                    init_tmpdir
                                    uncompress_deb_to_tmp ${deb_name}
                                    uncompress_status=$?
                                    if [ $uncompress_status -eq 0 ];then
                                        runtime_version=$(get_compat_field_value $tmpdir runtime_version)
                                        if [[ $runtime_version != *v11* ]] && [[ $runtime_version != *ok2* ]];then
                                            echo "软件包标签匹配失败"
                                            del_tmpdir
                                            return 1
                                        fi
                                    else
                                        echo "解压软件包失败"
                                        del_tmpdir
                                        return 1
                                    fi
                                    del_tmpdir
                                fi
                            else
                                echo "获取白名单开关失败"
                                return 1
                            fi
                        else
                            # 特权标签包
                            switch_status=$(get_privilege_runtime_check)
                            switch_return=$?
                            if [ $switch_return -eq 0 ];then
                                if [[ $switch_status == 'true' ]];then
                                    init_tmpdir
                                    uncompress_deb_to_tmp ${deb_name}
                                    uncompress_status=$?
                                    if [ $uncompress_status -eq 0 ];then
                                        runtime_version=$(get_compat_field_value $tmpdir runtime_version)
                                        if [[ $runtime_version == *v11* ]] || [[ $runtime_version == *ok2* ]];then
                                            # 验签
                                            bare_metal=$(get_compat_field_value $tmpdir bare_metal)
                                            if [[ $bare_metal == "yes" ]];then
                                                local plaintxt="${tmpdir}/plain.txt"
                                                local signtxt="${tmpdir}/sign.txt"
                                                local signtxtsig="${signtxt}.sig"
                                                data_size=$(get_data_size_in_deb ${deb_name})
                                                deb_sha512=$(get_deb_sha512sum $data_size $deb_name)
                                                echo -n "${deb_sha512}${bare_metal}" > $plaintxt
                                                bare_metal_sig=$(get_compat_field_value $tmpdir bare_metal_sig)
                                                echo -n ${bare_metal_sig} > $signtxt
                                                base64 -d $signtxt > $signtxtsig
                                                import_gpg_key
                                                gpg_verify $signtxtsig $plaintxt
                                                verify_status=$?
                                                if [ $verify_status -ne 0 ];then
                                                    echo gpg验签失败
                                                    unset_gpg
                                                    return 1
                                                fi
                                                unset_gpg
                                            else
                                                echo "软件包内无标签"
                                                return 1
                                            fi
                                        else
                                            echo "软件包标签匹配失败"
                                            del_tmpdir
                                            return 1
                                        fi
                                    else
                                        echo "解压软件包失败"
                                        del_tmpdir
                                        return 1
                                    fi
                                    del_tmpdir
                                fi
                            else
                                echo "获取特权标签开关失败"
                                return 1
                            fi
                        fi

                        /usr/bin/kypackage_general  apt.orig ${operation}  ${options[*]} ${package_name}
                        if is_package_installed_in_sys "$deb_name" ; then
                            /usr/bin/kypackage_desktop  "--create" $deb_name
                            add_to_privilege_list $package_name
                            printf "安装成功，安装的环境为核心系统\n"
                        fi
                    fi
                fi
            fi
        done
        popd 2&>1 /dev/null
        rm -rf "$apt_cache_dir"
    fi
    return 0
}

handle_install_in_maintain_mode()
{
    local operation=$1
    shift
    local options=()
    local packages=()
    
    parse_apt_args packages options "$@"
    options+=("-y")
    log "处理带选项的安装: options=[${options[*]}], packages=[${packages[*]}]"

    #如果包是空的直接general处理
    if [ ${#packages[@]} -eq 0 ] ; then
        log "kypackage_general传入参数: ${options[*]}"
        /usr/bin/kypackage_general apt.orig ${operation} "${options[@]}"
        return 0
    fi

    local deb_packages=()
    local apt_packages=()
    
    for pkg in "${packages[@]}"; do
        if [[ "$pkg" == *.deb ]]; then
            deb_packages+=("$pkg")
        else
            apt_packages+=("$pkg")
        fi
    done

    "$ORIGINAL_CMD" "$operation" "$@" 2>&1
    local return_code=$?
    if [ $return_code -eq 0 ]; then
        printf "安装成功，安装的环境为核心系统\n"
        #处理本地包
        if [ ${#deb_packages[@]} -gt 0 ]; then
            log "维护模式下, 处理本地deb包: [${deb_packages[*]}]"
            for deb_file in "${deb_packages[@]}"; do
                absolute_path=$(realpath "$deb_file" 2>/dev/null)
                if [ -f "$absolute_path" ]; then
                    log "维护模式下，分析本地软件包: $absolute_path"
                    result=$(/usr/bin/kypackage_check "$absolute_path")
                    if [[ "$result" =~ "将要安装的环境为kare" ]]; then
                        log "维护模式下,非特权包,无需加入特权列表"
                    else
                        package_name="$(dpkg-deb -f "$absolute_path" Package)"
                        add_to_privilege_list $package_name
                        log "维护模式下,特权包加入特权列表"
                    fi
                else
                    log "错误: 文件不存在 $absolute_path"
                fi
            done
        fi
    else
        printf "软件包安装失败\n" 2>&1 
        return $return_code
    fi
}

run_by_root()
{
    if [ $EUID -ne 0 ]; then
        echo "请使用 root 用户执行命令"
        exit -1
    fi
}


func_lib_path="/usr/bin/wrapper_common"
if [ -f $func_lib_path ];then
    source $func_lib_path
fi


# 只有在非live-build且非chroot且是normal模式时才执行操作拦截
if  should_execute_operation; then
    
    # 需要处理的操作类型
    case "$1" in
        install|reinstall)
            run_by_root
            log "通过wrapper执行操作: $1"
            handle_install_with_options "$@"
            exit $?
            ;;

        remove|purge)
            run_by_root
            log "通过wrapper执行操作: $1"
            handle_remove_with_options "$@"
            exit $?
            ;;

        autoremove|auto-remove|autopurge)
            run_by_root
            log "通过wrapper执行操作: $1"
            /usr/bin/kypackage_general "$ORIGINAL_CMD" "$@"
            exit $?
            ;;
            
        upgrade|full-upgrade|dist-upgrade)
            run_by_root
            log "通过wrapper执行操作: $1"
            log "禁止操作: $1"
            printf "当前模式下禁止该操作: $1\n"
            # /usr/bin/kypackage_general "$ORIGINAL_CMD" "$@"
            exit 1
            ;;
        *)
            log "通过原生$ORIGINAL_CMD执行操作: $1"
            exec "$ORIGINAL_CMD" "$@" 2>&1
            ;;
    esac
else
    log "不满足拦截条件，通过原生$ORIGINAL_CMD执行操作: $1"
    case "$1" in
        install|reinstall)
            run_by_root
            handle_install_in_maintain_mode "$@" 2>&1
            ;;
        *)
            exec "$ORIGINAL_CMD" "$@" 2>&1
            ;;
    esac
fi