#!/bin/bash

# set -x
# set -e

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

# 判断是否在 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() {
    # 检查内核参数中是否包含 boot=casper
    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  # 是normal模式返回0
    fi
    
    log "当前不是normal模式: $boot_mode"
    return 1  # 不是normal模式返回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  # 不应该执行操作
}

# 处理多个包名操作
handle_multiple_packages() {
    local operation=$1  # 要执行的操作(install/remove)
    local exit_code=0
    log "operation:$operation"	    
    # 遍历所有参数
    shift   # 移除操作参数
    local options=()
    local packages=()
    
    local processing_options=true
    for arg in "$@"; do
        if [ "$processing_options" = true ] && [[ "$arg" == -* ]]; then
            options+=("$arg")
        elif [ "$processing_options" = true ] && [[ "$arg" == "--" ]]; then
            processing_options=false
        else
            processing_options=false
            packages+=("$arg")
        fi
    done
    log "处理带选项的安装: options=[${options[*]}], packages=[${packages[*]}]"

    
    for arg in "${packages[@]}"; do
        log "进入循环，处理参数: $arg"
        # 直接处理文件参数，转换为绝对路径
        absolute_path=$(realpath "$arg" 2>/dev/null || readlink -f "$arg" 2>/dev/null || echo "$arg")
        if [ "$operation" = "install" ]; then
            log "通过kypackage_inst安装软件包:${absolute_path}"

            result=$(/usr/bin/kypackage_check "$absolute_path")
            if [[ "$result" =~ "将要安装的环境为kare v11" ]]; then
                log "通过kare安装本地软件包: $absolute_path"
                /usr/bin/kypackage_inst "$absolute_path"
            elif [[ "$result" =~ "将要安装的环境为kare v10sp1" ]]; then
                log "通过kare安装本地软件包: $absolute_path"
                /usr/bin/kypackage_inst "$absolute_path"
            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 dpkg.orig "${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

        elif [ "$operation" = "unpack" ]; then
            log "解压deb包: $absolute_path"
            /usr/bin/kypackage_unpack "$absolute_path"
        fi
        current_exit_code=$?
        if [ $current_exit_code -ne 0 ]; then
            exit_code=$current_exit_code
        fi
    done
    
    return $exit_code
}

# 解析命令行参数
parse_arguments() {

    # 检查无效的参数组合
    local list_opt=0
    local pkg_opt=0
    local unknown_opt=0
    local configure_opt=0
    local unpack_opt=0
    
    for arg in "$@"; do
        case "$arg" in
            --unpack)
                unpack_opt=1
                ;;
            -l|--list)
                list_opt=$((list_opt + 1))
                ;;
            -i|--install|-P|--purge|-r|--remove|--unpack)
                pkg_opt=$((pkg_opt + 1))
                ;;
            --configure|-a|--pendinig)
                configure_opt=$((configure_opt + 1))
                ;;
            --*|-*)
                unknown_opt=$((unknown_opt + 1))
                ;;
        esac
    done

    # 有未知的参数且没有安装、卸载相关操作，直接转交dpkg
    if [ $unknown_opt -gt 0 ] && [ $pkg_opt -ne 1 ]; then
        log "存在未知的操作选项: $@ 执行原生dpkg"
        exec /usr/bin/dpkg.orig "$@"
        exit 1
    fi
    
    # 检验包列表和安装/卸载/解压冲突
    local pkg_or_list_opts=$((list_opt + pkg_opt + unpack_opt))
    if [ $pkg_or_list_opts -gt 1 ]; then
        log "错误: 操作符冲突 $@"
        exec /usr/bin/dpkg.orig "$@"
        exit 1
    fi

    # 检验configure参数完整性
    if [ $configure_opt -ne 0 ] && [ $configure_opt -ne 2 ]; then
        log "错误: configure操作异常 $@"
        exec /usr/bin/dpkg.orig "$@"
        exit 1
    fi
    
    # 检验configure
    local total_opts=$((list_opt + pkg_opt + configure_opt + unpack_opt))
    
    if [ $total_opts -gt 2 ]; then
        log "错误: configure操作与其他操作冲突 $@"
        exec /usr/bin/dpkg.orig "$@"
        exit 1
    fi
}

# 判断是否为通配符模式（包含 * 或 ?）
is_wildcard_pattern() {
    local pattern="$1"
    [[ "$pattern" == *"*"* ]] || [[ "$pattern" == *"?"* ]]
}

# 成功搜索返回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 #挪走操作符号
    for package_name in "$@"; do
        if [[ "$package_name" == -* ]]; then
            continue
        fi
        log "尝试删除deb包: $package_name"
        pkg_env=$(pkg_in_sys $package_name)
        pkg_status=$?
        if [ $pkg_status -ne 0 ];then
            # 定义字体样式
            RESET='\033[0m'
            BOLD='\033[1m'
            YELLOW='\033[33m'
            printf "${BOLD}dpkg: ${YELLOW}警告:${RESET} 忽略删除 ${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}, 使用原生dpkg"
                /usr/bin/kypackage_desktop  "--remove" $package_name
                /usr/bin/kypackage_general dpkg.orig "${operation}" "${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
}

handle_install_in_maintain_mode()
{
    local operation=$1
    shift
    local options=()
    local packages=()
    
    local processing_options=true
    for arg in "$@"; do
        if [ "$processing_options" = true ] && [[ "$arg" == -* ]] && [[ "$arg" != *"upgrade"* ]]; then
            options+=("$arg")
        elif [ "$processing_options" = true ] && [[ "$arg" == "--" ]]; then
            processing_options=false
        else
            processing_options=false
            packages+=("$arg")
        fi
    done

    /usr/bin/dpkg.orig $operation "$@" 2>&1
    local return_code=$?
    if [ $return_code -eq 0 ]; then
        printf "安装成功，安装的环境为核心系统\n"
        if [ ${#packages[@]} -gt 0 ]; then
            log "维护模式下, 处理本地deb包: [${packages[*]}]"
            for deb_file in "${packages[@]}"; do
                absolute_path=$(realpath "$deb_file" 2>/dev/null)
                if [ -f "$absolute_path" ]; then
                    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
}


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
    parse_arguments "$@"
    
    # 需要阻止的操作类型
    case "$1" in
        --configure)
            log "通过wrapper执行操作操作: $1"
            exec /usr/bin/kypackage_configure
            exit $?
            ;;
        -i|--install)
            log "通过wrapper执行操作: $1"
            handle_multiple_packages install "$@"
            exit $?
            ;;

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

        --unpack)
            log "通过wrapper执行操作: $1"
            shift #挪走操作符号
            handle_multiple_packages unpack "$@"
            exit $?
            ;;
        
        -l|--list)
            log "通过wrapper执行操作: $1"
            shift
            
            full_list=$(/usr/bin/kypackage_list)
            
            if [ $# -gt 0 ]; then
                awk_patterns=""
                for pattern in "$@"; do
                    if is_wildcard_pattern "$pattern"; then
                        regex_pattern=$(echo "$pattern" | sed 's/\*/.*/g' | sed 's/?/./g' | sed 's/[][^$.+(){}|]/\\&/g')
                    else
                        regex_pattern="^$pattern$"
                    fi
                    
                    if [ -z "$awk_patterns" ]; then
                        awk_patterns="$regex_pattern"
                    else
                        awk_patterns="$awk_patterns|$regex_pattern"
                    fi
                done
                
                echo "$full_list" | awk -v patterns="$awk_patterns" '
                BEGIN {
                    split(patterns, pattern_array, "|")
                }
                /^ii|^hi/ {
                    pkg_name = $2
                    for (i in pattern_array) {
                        if (pkg_name ~ pattern_array[i]) {
                            print $0
                            break
                        }
                    }
                }'
            else
                # 如果没有额外参数，则显示所有包
                if [ -n "$full_list" ]; then
                    printf '%s\n' "$full_list" 2>/dev/null || true
                fi
            fi
            exit 0
            ;;
        *)
            log "通过原生dpkg执行操作: $1"
            exec /usr/bin/dpkg.orig "$@" 2>&1
            ;;
    esac
else
    log "不满足拦截条件，通过原生dpkg执行操作: $1"
    case "$1" in
        -i|--install)
            handle_install_in_maintain_mode "$@" 2>&1
            ;;
        *)
            exec /usr/bin/dpkg.orig "$@" 2>&1
            ;;
    esac
    
fi