#!/usr/bin/env bash
# Description: 基于 downgrade 的软件包降级 TUI
# Features:
#   1. 模糊搜索已安装软件包并传递给 downgrade 进行版本回退
#   2. 自动检测系统依赖 (fzf, downgrade, paru/yay)
#   3. 动态追溯并显示包的真实来源 (core/extra/aur 等)
#   4. 严格执行前置高危操作安全警告，防止破坏系统依赖链
#   5. 实时下半屏预览软件包详细信息
# ==============================================================================

# 启用严格的错误处理机制
set -euo pipefail

# --- 1. 环境与基础配置 ---
ORIGINAL_LANG="${LC_ALL:-${LC_MESSAGES:-${LANG:-C}}}"
SHOW_HELP=false
QUERY_ARGS=()

# 强制 C locale 确保 awk 解析的一致性
export LC_ALL=C

# --- 2. 参数解析 ---
while [[ $# -gt 0 ]]; do
    case "$1" in
        --help|-h)
            SHOW_HELP=true
            shift
        ;;
        *)
            QUERY_ARGS+=("$1")
            shift
        ;;
    esac
done

# --- 3. 本地化多语言字典 ---
declare -A MSG
if [[ "$ORIGINAL_LANG" == *"zh_CN"* ]]; then
    MSG[DESC]="模糊搜索已安装的软件包并进行版本降级。"
    MSG[OPTS]="选项："
    MSG[OPT_HELP]="  --help, -h    显示此帮助信息并退出"
    MSG[FEAT]="功能特性："
    MSG[FEAT_1]="- 历史回溯：集成 downgrade，支持从本地缓存或 A.L.A 降级"
    MSG[FEAT_2]="- 精准追溯：动态比对显示包的真实来源 (core/extra/aur 等)"
    MSG[FEAT_3]="- 依赖安全：移交 pacman 进行底层依赖拦截，并提供强警告"
    MSG[EX]="示例："
    
    # 依赖报错字典 (支持 printf 格式化注入变量)
    MSG[ERR_DEPS]="\033[1;31m[错误] 缺少核心依赖程序！\033[0m\n未找到命令: \033[1;33m%s\033[0m\n参考安装: \033[32msudo pacman -S %s\033[0m\n"
    MSG[ERR_HELPER]="\033[1;31m[错误] 未找到 AUR 助手！\033[0m\n请至少安装 \033[32mparu\033[0m 或 \033[32myay\033[0m 以支持包信息预览。\n"
    MSG[ERR_DOWNGRADE]="\033[1;31m[错误] 未找到 downgrade 工具！\033[0m\n此脚本强依赖该工具执行版本回退操作。\n参考安装: \033[32m%s -S downgrade\033[0m\n"
    
    MSG[DOWNGRADING]=">> 准备降级："
    MSG[WARN_DEP]="[依赖危险警告] 降级核心库(如 glibc, mesa, python 等)极易导致系统崩溃！"
    MSG[HEADER]="Tab:多选 | Enter:降级 | Esc:退出"
else
    MSG[DESC]="Fuzzy search and downgrade installed packages."
    MSG[OPTS]="Options:"
    MSG[OPT_HELP]="  --help, -h    Show this help and exit"
    MSG[FEAT]="Features:"
    MSG[FEAT_1]="- History: Integrates with downgrade tool (Local Cache / A.L.A)"
    MSG[FEAT_2]="- Exact Origin: Dynamically maps package to real repo"
    MSG[FEAT_3]="- Dependency Safety: Relies on pacman strictly, with pre-execution warnings"
    MSG[EX]="Example:"
    
    MSG[ERR_DEPS]="\033[1;31m[Error] Missing core dependencies!\033[0m\nCommands not found: \033[1;33m%s\033[0m\nInstall via: \033[32msudo pacman -S %s\033[0m\n"
    MSG[ERR_HELPER]="\033[1;31m[Error] AUR helper not found!\033[0m\nPlease install \033[32mparu\033[0m or \033[32myay\033[0m to support package previews.\n"
    MSG[ERR_DOWNGRADE]="\033[1;31m[Error] downgrade tool not found!\033[0m\nThis script strictly requires 'downgrade' to operate.\nInstall via: \033[32m%s -S downgrade\033[0m\n"
    
    MSG[DOWNGRADING]=">> Preparing to downgrade:"
    MSG[WARN_DEP]="[DANGER] Downgrading core libs can break your system!"
    MSG[HEADER]="Tab:Multi-Select | Enter:Downgrade | Esc:Exit"
fi

# --- 4. 帮助信息拦截 ---
if [ "$SHOW_HELP" = true ]; then
    cat <<EOF
Usage: ${0##*/} [options] [query]

${MSG[OPTS]}
${MSG[OPT_HELP]}

Description:
  ${MSG[DESC]}

${MSG[FEAT]}
  ${MSG[FEAT_1]}
  ${MSG[FEAT_2]}
  ${MSG[FEAT_3]}

${MSG[EX]}
  ${0##*/} linux        # 搜索并降级 'linux' 内核
  ${0##*/}              # 列出所有已安装的包
EOF
    exit 0
fi

# --- 5. 核心依赖检查与动态 Helper 探测 ---
AUR_HELPER=""
if command -v paru >/dev/null 2>&1; then
    AUR_HELPER="paru"
elif command -v yay >/dev/null 2>&1; then
    AUR_HELPER="yay"
fi

check_dependencies() {
    # 1. 检查基础 CLI 工具
    local missing_deps=()
    for cmd in fzf awk pacman; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            missing_deps+=("$cmd")
        fi
    done

    if [[ ${#missing_deps[@]} -gt 0 ]]; then
        printf "${MSG[ERR_DEPS]}" "${missing_deps[*]}" "${missing_deps[*]}" >&2
        exit 1
    fi

    # 2. 检查 AUR 助手 (提供预览功能，也是安装 downgrade 的前提)
    if [[ -z "$AUR_HELPER" ]]; then
        echo -e "${MSG[ERR_HELPER]}" >&2
        exit 1
    fi

    # 3. 检查 downgrade 工具 (强依赖，动态生成安装命令)
    if ! command -v downgrade >/dev/null 2>&1; then
        printf "${MSG[ERR_DOWNGRADE]}" "$AUR_HELPER" >&2
        exit 1
    fi
}

check_dependencies

# --- 6. 异步逻辑与文件安全设置 ---
TMP_DIR=$(mktemp -d -t pacd_fzf.XXXXXX)
TARGET_FILE="${TMP_DIR}/target"
PIPE_FIFO="${TMP_DIR}/fifo"
mkfifo "$PIPE_FIFO"

# 预览时直接查询本地已安装信息即可
PREVIEW_CMD="$AUR_HELPER -Qi {2}"

cleanup() {
    if [[ -n "${PID_GEN:-}" ]]; then kill "$PID_GEN" 2>/dev/null || true; fi
    rm -rf "$TMP_DIR"
}
trap cleanup EXIT INT TERM

# --- 7. 数据生成器 (后台运行：智能源映射) ---
AWK_CMD='
# 阶段 1: 读取 sync_db.txt，将源名称存入内存哈希表
NR==FNR {
    if (!($2 in repo)) {
        repo[$2] = $1
    }
    next
}
# 阶段 2: 读取 pacman -Q 当前已安装的包
{
    pkg_name = $1
    pkg_ver = $2
    if (pkg_name in repo) {
        # 存在于源中 -> 官方源或第三方源 (蓝色)
        printf "%s%-16s%s %-30s %s\n", cb, repo[pkg_name], r, pkg_name, pkg_ver
    } else {
        # 不存在于源中 -> 纯正的外来/AUR包 (紫色)
        printf "%s%-16s%s %-30s %s\n", cp, "aur", r, pkg_name, pkg_ver
    }
}
'

(
    # 导出包含 repo 信息的源数据库清单
    pacman --color=never -Sl > "${TMP_DIR}/sync_db.txt" || true

    # 比对本地已安装包，精确追溯来源
    pacman --color=never -Q | awk -v cb='\033[34m' -v cp='\033[35m' -v r='\033[0m' \
        "$AWK_CMD" "${TMP_DIR}/sync_db.txt" -

) > "$PIPE_FIFO" 2>/dev/null &

PID_GEN=$!

# --- 8. 交互式 FZF 渲染 ---
COLOR_YELLOW=$'\033[33m'
COLOR_RESET=$'\033[0m'
FZF_HEADER="${MSG[HEADER]} | ${COLOR_YELLOW}Using downgrade & ${AUR_HELPER}${COLOR_RESET}"

set +e
fzf --multi --ansi \
    --preview "$PREVIEW_CMD" \
    --preview-window=down:55%:wrap \
    --height=95% --layout=reverse --border \
    --tiebreak=index \
    --nth=2 \
    --header "$FZF_HEADER" \
    --query "${QUERY_ARGS[*]:-}" \
    < "$PIPE_FIFO" \
    > "$TARGET_FILE"
FZF_EXIT=$?
set -e

# --- 9. 执行降级 ---
if [[ $FZF_EXIT -eq 0 ]] && [[ -s "$TARGET_FILE" ]]; then
    mapfile -t SELECTED_LINES < "$TARGET_FILE"
    PACKAGES=()
    for line in "${SELECTED_LINES[@]}"; do
        pkg=$(echo "$line" | awk '{print $2}')
        [[ -n "$pkg" ]] && PACKAGES+=("$pkg")
    done

    if [[ ${#PACKAGES[@]} -gt 0 ]]; then
        echo -e "\n\033[33m${MSG[DOWNGRADING]}\033[0m ${PACKAGES[*]}"
        echo -e "\033[31;1m${MSG[WARN_DEP]}\033[0m"
        echo "----------------------------------------"

        # downgrade 本身会在执行 pacman -U 时自动请求 sudo 权限
        sudo downgrade "${PACKAGES[@]}"
    fi
fi
