#!/bin/bash

# set -x
# set -e

WRAPPER_TAG="dpkg_wrapper"

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

# 根据依赖关系对包数组进行排序
resolve_package_dependencies() {
    local -n packages_ref=$1
    local original_packages=("${packages_ref[@]}")
    local deb_count=0
    local pkg_path
    local pkg_name

    declare -A pkg_to_file=()
    declare -A pkg_deps=()
    declare -A visit_state=()
    local pkg_names=()
    local sorted_pkg_names=()
    local sorted_packages=()
    local passthrough_packages=()

    for pkg_path in "${packages_ref[@]}"; do
        if [[ "$pkg_path" == *.deb ]] && [ -f "$pkg_path" ]; then
            pkg_name=$(dpkg-deb -f "$pkg_path" Package 2>/dev/null)
            if [ -n "$pkg_name" ]; then
                if [ -n "${pkg_to_file[$pkg_name]+set}" ]; then
                    log "检测到重复包名 $pkg_name，使用原始安装顺序"
                    return 0
                fi
                pkg_to_file["$pkg_name"]="$pkg_path"
                pkg_names+=("$pkg_name")
                ((deb_count++))
                log "发现包: $pkg_name ($pkg_path)"
            else
                passthrough_packages+=("$pkg_path")
                log "无法解析包名，保持原顺序追加: $pkg_path"
            fi
        else
            passthrough_packages+=("$pkg_path")
        fi
    done

    log "准备分析依赖关系，共发现 $deb_count 个有效 .deb 文件"
    if [ "$deb_count" -le 1 ]; then
        log "有效 .deb 文件数量不足，无需依赖排序"
        return 0
    fi

    local pre_depends
    local depends
    local dependency_fields
    local dependency_group
    local alternative
    local dep_name
    local old_ifs
    for pkg_name in "${pkg_names[@]}"; do
        pkg_path="${pkg_to_file[$pkg_name]}"
        pre_depends="$(dpkg-deb -f "$pkg_path" Pre-Depends 2>/dev/null || true)"
        depends="$(dpkg-deb -f "$pkg_path" Depends 2>/dev/null || true)"
        dependency_fields="$pre_depends"
        if [ -n "$dependency_fields" ] && [ -n "$depends" ]; then
            dependency_fields="$dependency_fields, $depends"
        else
            dependency_fields="$dependency_fields$depends"
        fi
        log "分析包: $pkg_name ($pkg_path)"

        old_ifs="$IFS"
        IFS=','
        for dependency_group in $dependency_fields; do
            IFS='|'
            for alternative in $dependency_group; do
                dep_name="$alternative"
                dep_name="${dep_name%%(*}"
                dep_name="${dep_name%%[*}"
                dep_name="${dep_name%%:*}"
                dep_name="${dep_name#"${dep_name%%[![:space:]]*}"}"
                dep_name="${dep_name%"${dep_name##*[![:space:]]}"}"

                if [ -n "$dep_name" ] && [ -n "${pkg_to_file[$dep_name]+set}" ] && [ "$dep_name" != "$pkg_name" ]; then
                    pkg_deps["$pkg_name"]="${pkg_deps[$pkg_name]} $dep_name"
                    log "添加依赖关系: $dep_name -> $pkg_name"
                    break
                fi
            done
            IFS=','
        done
        IFS="$old_ifs"
    done

    resolve_visit_package() {
        local current_pkg=$1
        local dependency

        case "${visit_state[$current_pkg]}" in
            visiting)
                log "检测到依赖环，使用原始安装顺序"
                return 1
                ;;
            visited)
                return 0
                ;;
        esac

        visit_state["$current_pkg"]="visiting"
        for dependency in ${pkg_deps[$current_pkg]}; do
            resolve_visit_package "$dependency" || return 1
        done
        visit_state["$current_pkg"]="visited"
        sorted_pkg_names+=("$current_pkg")
    }

    for pkg_name in "${pkg_names[@]}"; do
        resolve_visit_package "$pkg_name" || return 0
    done

    for pkg_name in "${sorted_pkg_names[@]}"; do
        sorted_packages+=("${pkg_to_file[$pkg_name]}")
    done
    for pkg_path in "${passthrough_packages[@]}"; do
        sorted_packages+=("$pkg_path")
    done

    if [ "${#sorted_packages[@]}" -eq "${#original_packages[@]}" ]; then
        packages_ref=("${sorted_packages[@]}")
        log "依赖排序完成: ${packages_ref[*]}"
    else
        log "排序结果数量异常，使用原始安装顺序"
    fi
}

# 处理多个包名操作
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
            processing_options=false
        elif [ "$processing_options" = true ] && [[ "$arg" == -* ]]; then
            options+=("$arg")
        else
            processing_options=false
            packages+=("$arg")
        fi
    done
    log "处理带选项的安装: options=[${options[*]}], packages=[${packages[*]}]"

    if [ "$operation" = "install" ] && [ ${#packages[@]} -gt 1 ]; then
        resolve_package_dependencies packages
        log "依赖排序后的安装列表: [${packages[*]}]"
    fi
    
    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" 2> /dev/null)
            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"

                local check_res
                local check_status
                check_res=$(deb_install_check $package_name $absolute_path)
                check_status=$?
                if [ $check_status -ne 0 ];then
                    echo $check_res
                    return 1
                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
    local field_opt=0
    
    for arg in "$@"; do
        case "$arg" in
            --unpack)
                unpack_opt=1
                ;;
            -f|--field)
                field_opt=1
                ;;
            -l|--list)
                list_opt=$((list_opt + 1))
                ;;
            -i|--install|-P|--purge|-r|--remove)
                pkg_opt=$((pkg_opt + 1))
                ;;
            --configure|-a|--pending)
                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 + field_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" == *"?"* ]]
}

# 卸载软件包
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 "env")
        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}\' && pkg_is_in_ostree ${package_name}; then
                printf "当前模式下,软件包 ${package_name} 不允许卸载\n"
            else
                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
            fi
        fi
    done
}

# 卸载软件包
handle_remove_in_maintain_mode() 
{
    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 "env")
        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
            log "软件包 ${package_name}, 使用原生dpkg"
            /usr/bin/kypackage_desktop  "--remove" $package_name
            /usr/bin/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
        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" == "--" ]]; then
            processing_options=false
        elif [ "$processing_options" = true ] && [[ "$arg" == -* ]] && [[ "$arg" != *"upgrade"* ]]; then
            options+=("$arg")
        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
                    /usr/bin/kypackage_desktop "--create" "$absolute_path"
                    local result=$(/usr/bin/kypackage_check "$absolute_path" 2> /dev/null)
                    if [[ "$result" =~ "将要安装的环境为kare" ]]; then
                        log "维护模式下,非特权包,无需加入特权列表"
                    else
                        local package_name=""
                        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 
        return $return_code
    fi
}


# 只有在非live-build且非chroot且是normal模式时才执行操作拦截
if  should_execute_operation; then
    parse_arguments "$@"
    
    # 需要阻止的操作类型
    case "$1" in
        --configure)
            log "通过wrapper执行操作操作: $1"
            run_by_root
            /usr/bin/kypackage_configure
            exit $?
            ;;
        -i|--install)
            log "通过wrapper执行操作: $1"
            run_by_root
            handle_multiple_packages install "$@"
            exit $?
            ;;

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

        --unpack)
            log "通过wrapper执行操作: $1"
            run_by_root
            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)
            run_by_root
            handle_install_in_maintain_mode "$@" 2>&1
            ;;
        -P|--purge|-r|--remove)
            run_by_root
            handle_remove_in_maintain_mode "$@" 2>&1
            ;;
        *)
            exec /usr/bin/dpkg.orig "$@" 2>&1
            ;;
    esac
fi
