#!/bin/bash

# APM软件包转换器 - 将DEB包转换为APM格式
log.warn() { echo -e "[\e[33mWARN\e[0m]:  \e[1m$*\e[0m"; }
log.error()  { echo -e "[\e[31mERROR\e[0m]: \e[1m$*\e[0m"; }
log.info() { echo -e "[\e[96mINFO\e[0m]:  \e[1m$*\e[0m"; }
log.debug()  { echo -e "[\e[32mDEBUG\e[0m]: \e[1m$*\e[0m"; }
SCRIPT_NAME=$(basename "$0")

if ! command -v dpkg > /dev/null ;then
log.error "若想使用APM软件包转换器，您需先安装dpkg"
exit 1
fi
# 显示用法信息
usage() {
    echo "用法: $SCRIPT_NAME --base <basename> [--base <basename> ...] <deb文件路径> [--pkgname <包名>] [--version <版本号>]"
    echo ""
    echo "参数说明:"
    echo "  --basename   必填参数，指定基础环境名称，可多次使用指定多个基础环境"
    echo "  deb文件路径  必填参数，要转换的DEB文件路径"
    echo "  --pkgname    可选参数，指定新包的包名（默认使用原DEB包名）"
    echo "  --version    可选参数，指定新包的版本号（默认在原版本后追加'-apm'）"
    echo ""
    echo "示例:"
    echo "  $SCRIPT_NAME --base amber-pm-trixie /path/to/package.deb"
    echo "  $SCRIPT_NAME --base amber-pm-bookworm-spark-wine /path/to/package.deb --pkgname new-pkg --version 1.0.0"
    echo "最下层的base在最后面，从上到下写base"
}

# 检查参数数量
if [ $# -lt 3 ]; then
    log.error "错误：参数不足"
    usage
    exit 1
fi

# 解析参数
BASENAMES=()  # 改为数组存储多个base
DEB_PATH=""
PKGNAME=""
VERSION=""

# 参数解析
while [ $# -gt 0 ]; do
    case $1 in
        --base)
            BASENAMES+=("$2")
            BASENAMES_ORIG+=("$2")
            shift 2
            ;;
        --pkgname)
            PKGNAME="$2"
            shift 2
            ;;
        --version)
            VERSION="$2"
            shift 2
            ;;
        *)
            if [ -z "$DEB_PATH" ] && [ -f "$1" ]; then
                DEB_PATH="$1"
                shift
            else
                log.error "错误：未知参数或无效的DEB文件路径: $1"
                usage
                exit 1
            fi
            ;;
    esac
done

# 检查必填参数
if [ ${#BASENAMES[@]} -eq 0 ] || [ -z "$DEB_PATH" ]; then
    log.error "错误：至少需要一个--basename参数，且DEB文件路径为必填"
    usage
    exit 1
fi

# 检查DEB文件是否存在
if [ ! -f "$DEB_PATH" ]; then
    log.error "错误：DEB文件不存在: $DEB_PATH"
    exit 1
fi

log.info "开始转换DEB包: $DEB_PATH"
log.info "基础环境数量: ${#BASENAMES[@]}"
for i in "${!BASENAMES[@]}"; do
    log.info "  基础环境 $((i+1)): ${BASENAMES[$i]}"
done

# 1. 创建临时工作目录
CRAFT_DIR="$HOME/apm-craft-$$"
log.info "创建临时工作目录: $CRAFT_DIR"
mkdir -p "$CRAFT_DIR"/{core,work,mergedir,modified_deb}

# 设置环境变量
export CRAFT_DIR

# 检查是否已挂载，避免重复挂载
cleanup_mount() {
    if mountpoint -q "$CRAFT_DIR/mergedir"; then
        log.info "解除挂载: $CRAFT_DIR/mergedir"
        sudo umount "$CRAFT_DIR/mergedir" || true
    fi
}

# 清理函数
cleanup() {
    log.info "开始清理..."
    cleanup_mount
    if [ -d "$CRAFT_DIR" ]; then
        log.info "删除临时目录: $CRAFT_DIR"
        sudo rm -rf "$CRAFT_DIR"
    fi
}

# 设置退出时清理
trap cleanup EXIT

# 递归获取info文件中的依赖
get_recursive_basenames() {
    local basename="$1"
    local base_dir="/var/lib/apm/apm/files/ace-env/var/lib/apm/$basename"
    local info_file="$base_dir/info"
    
    if [ -f "$info_file" ]; then
        log.info "读取info文件: $info_file"
        while IFS= read -r base; do
            # 跳过空行
            [[ -z "$base" ]] && continue
            # 如果依赖的base没有被记录过，则递归添加
            if [[ ! " ${BASENAMES[*]} " =~ " $base " ]]; then
                BASENAMES+=("$base")
                # 递归获取依赖
                get_recursive_basenames "$base"
            fi
        done < "$info_file"
    else
        log.info "未找到info文件，跳过: $info_file"
    fi
}

# 递归获取所有基础环境
for BASE in "${BASENAMES[@]}"; do
    get_recursive_basenames "$BASE"
done

# 检查DEB文件
log.info "检查原DEB包信息..."
ORIG_PKGNAME=$(dpkg -f "$DEB_PATH" Package)
ORIG_VERSION=$(dpkg -f "$DEB_PATH" Version)
ORIG_ARCH=$(dpkg -f "$DEB_PATH" Architecture)

log.info "原包名: $ORIG_PKGNAME"
log.info "原版本: $ORIG_VERSION"
log.info "原架构: $ORIG_ARCH"

# 设置新包名和版本
NEW_PKGNAME="${PKGNAME:-$ORIG_PKGNAME}"
NEW_VERSION="${VERSION:-${ORIG_VERSION}-apm}"

log.info "新包名: $NEW_PKGNAME"
log.info "新版本: $NEW_VERSION"
log.info "新架构: $ORIG_ARCH"

# 2. 构建lowerdir路径（多个base按顺序叠放）
log.info "构建overlay lowerdir路径..."
LOWERDIRS=()

# 按顺序处理每个base（从第一个到最后一个，最后一个在最底层）
for BASENAME in "${BASENAMES[@]}"; do
    ACE_ENV_PATH="/var/lib/apm/apm/files/ace-env/var/lib/apm/${BASENAME}/files/ace-env"
    CORE_PATH="/var/lib/apm/apm/files/ace-env/var/lib/apm/${BASENAME}/files/core"
    
    if [ -d "$ACE_ENV_PATH" ]; then
        log.info "使用ace-env路径: $ACE_ENV_PATH"
        LOWERDIRS+=("$ACE_ENV_PATH")
    elif [ -d "$CORE_PATH" ]; then
        log.info "使用core路径: $CORE_PATH"
        LOWERDIRS+=("$CORE_PATH")
    else
        log.error "错误：基础环境路径不存在: $BASENAME"
        log.error "  检查的路径: $ACE_ENV_PATH"
        log.error "  检查的路径: $CORE_PATH"
        exit 1
    fi
done

# 将lowerdirs数组用冒号连接
LOWERDIR=$(IFS=:; echo "${LOWERDIRS[*]}")
log.debug "最终lowerdir: $LOWERDIR"

# 4. 进行融合挂载
log.info "正在进行融合挂载..."

sudo mount -t overlay overlay \
    -o "lowerdir=$LOWERDIR,upperdir=$CRAFT_DIR/core/,workdir=$CRAFT_DIR/work/" \
    "$CRAFT_DIR/mergedir"

log.info "挂载完成"

# 5. 在融合环境中安装修改后的DEB包
log.info "在融合环境中测试安装DEB包..."

# 更新包列表
export chrootEnvPath="$CRAFT_DIR/mergedir"
sudo -E /var/lib/apm/apm/files/ace-run-pkg aptss update

# 首先进行dry-run检查
log.info "进行安装前检查..."
if ! sudo -E /var/lib/apm/apm/files/ace-run-pkg aptss install "$DEB_PATH" --dry-run; then
    log.error "错误：安装前检查失败，DEB包可能无法在基础环境中安装"
    log.error "请检查依赖关系或基础环境是否兼容"
    exit 1
fi

log.info "安装前检查通过，准备实际安装..."

# 6. 提取并修改DEB包
log.info "提取并修改原DEB包..."
EXTRACT_DIR="$CRAFT_DIR/extract"
MODIFIED_DEB_DIR="$CRAFT_DIR/modified_deb"
mkdir -p "$EXTRACT_DIR"
mkdir -p "$MODIFIED_DEB_DIR/DEBIAN"

# 解压DEB包
dpkg -x "$DEB_PATH" "$EXTRACT_DIR"
dpkg -e "$DEB_PATH" "$MODIFIED_DEB_DIR/DEBIAN"

# 处理.desktop文件
DESKTOP_MODIFIED=false
find "$EXTRACT_DIR" -name "*.desktop" | while read -r desktop_file; do
    log.info "处理桌面文件: $desktop_file"
    busybox dos2unix $desktop_file
    DESKTOP_MODIFIED=true

    # 在Exec和TryExec行前追加 "apm run $NEW_PKGNAME"
    # 处理Exec行
    if grep -q '^Exec=' "$desktop_file"; then
        sed -i 's/^Exec=\(.*\)$/Exec=apm run '"$NEW_PKGNAME"' \1/' "$desktop_file"
    fi
    
# 处理TryExec行 - 直接删除
if grep -q '^TryExec=' "$desktop_file"; then
    sed -i '/^TryExec=/d' "$desktop_file"
    log.info "已删除TryExec行"
fi

    # 处理Icon路径
    icon_line=$(grep "^Icon=" "$desktop_file")
    if [[ "$icon_line" == "Icon=/"* ]]; then
        sed -i 's|^Icon=/|Icon=/var/lib/apm/apm/files/ace-env/var/lib/apm/'"$NEW_PKGNAME"'/files/core/|' "$desktop_file"
    fi

    # 添加X-APM-APPID
    if ! grep -q "X-APM-APPID" "$desktop_file"; then
        echo "X-APM-APPID=$NEW_PKGNAME" >> "$desktop_file"
    fi

    # 检查修改结果
    if grep -q "apm run $NEW_PKGNAME" "$desktop_file"; then
        log.info "桌面文件修改成功"
        log.debug "修改后的Exec行: $(grep '^Exec=' "$desktop_file" || echo "未找到")"
        log.debug "修改后的TryExec行: $(grep '^TryExec=' "$desktop_file" || echo "未找到")"
    else
        log.warn "桌面文件可能未正确修改: $desktop_file"
    fi
done

if [ "$DESKTOP_MODIFIED" = false ]; then
    log.info "未找到需要修改的.desktop文件"
fi

# 重新打包修改后的DEB
MODIFIED_DEB_PATH="$CRAFT_DIR/modified_${ORIG_PKGNAME}.deb"
log.info "重新打包修改后的DEB: $MODIFIED_DEB_PATH"

# 复制修改后的文件结构到打包目录
mkdir -p "$MODIFIED_DEB_DIR/data"
cp -r "$EXTRACT_DIR"/* "$MODIFIED_DEB_DIR/" 2>/dev/null || true

# 使用fakeroot重新打包
cd "$MODIFIED_DEB_DIR" && fakeroot  dpkg-deb --build -Z none . "$MODIFIED_DEB_PATH"
cd - > /dev/null

if [ ! -f "$MODIFIED_DEB_PATH" ]; then
    log.error "错误：重新打包DEB失败"
    exit 1
fi

log.info "DEB包修改完成，新包路径: $MODIFIED_DEB_PATH"

# 实际安装修改后的DEB包
if ! sudo -E /var/lib/apm/apm/files/ace-run-pkg ssaudit "$MODIFIED_DEB_PATH" --native --no-create-desktop-entry; then
    log.error "错误：修改后的DEB包安装失败"
    exit 1
fi

log.info "修改后的DEB包安装完成"

# 清理一些垃圾
sudo -E /var/lib/apm/apm/files/ace-run-pkg aptss clean
sudo -E /var/lib/apm/apm/files/ace-run-pkg rm -vfr /var/lib/apt/lists
sudo -E /var/lib/apm/apm/files/ace-run-pkg rm -vfr /var/lib/aptss/lists

# 7. 创建新的APM包结构
log.info "创建新的APM包结构..."
PKG_BUILD_DIR="$CRAFT_DIR/new-pkg"
mkdir -p "$PKG_BUILD_DIR/DEBIAN"
mkdir -p "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME"/{entries,files}

# 创建info文件 - 写入所有base，每行一个
log.info "创建info文件，包含输入的基础环境:"
for BASENAME in "${BASENAMES_ORIG[@]}"; do
    echo "$BASENAME" >> "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/info"
    log.info "  写入: $BASENAME"
done
log.info "创建info_debug文件，包含所有基础环境:"
for BASENAME in "${BASENAMES[@]}"; do
    echo "$BASENAME" >> "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/info_debug"
    log.info "  写入: $BASENAME"
done

# 创建postrm脚本
cat > "$PKG_BUILD_DIR/DEBIAN/postrm" << 'EOF'
#!/bin/bash
PACKAGE_NAME="$DPKG_MAINTSCRIPT_PACKAGE"

if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then
    echo "清理卸载残留"
    rm -rf "/var/lib/apm/$PACKAGE_NAME"
for username in $(ls /home)
    do
        echo /home/$username
        if [ -d "/home/$username/.apm/$PACKAGE_NAME" ]
        then
            rm -fr "/home/$username/.apm/$PACKAGE_NAME"
        fi
done
else
    echo "非卸载，跳过清理"
fi
EOF

chmod +x "$PKG_BUILD_DIR/DEBIAN/postrm"

# 8. 复制文件到新的APM包
log.info "复制文件到新的APM包..."

# 复制/usr/share/内容到entries
if [ -d "$EXTRACT_DIR/usr/share" ]; then
    log.info "复制/usr/share/内容..."
    cp -r "$EXTRACT_DIR/usr/share/"* "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/entries/"
fi

# 复制/opt/apps/内容（如果存在）
if [ -d "$EXTRACT_DIR/opt/apps/$ORIG_PKGNAME/entries" ]; then
    log.info  "复制/opt/apps/$ORIG_PKGNAME/entries内容..."
    cp -r "$EXTRACT_DIR/opt/apps/$ORIG_PKGNAME/entries/"* "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/entries/"
fi

# 复制融合环境文件
log.info  "复制融合环境文件..."
sudo cp -r "$CRAFT_DIR"/{core,work} "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/files/"

# 设置文件权限
sudo chmod -R 755 "$PKG_BUILD_DIR/var/lib/apm/$NEW_PKGNAME/files/"

# 9. 解除挂载
log.info  "解除挂载..."
cleanup_mount

# 10. 打包新的APM包
log.info  "打包新的APM包..."
calculate_directory_size() {
    local dir="$1"
    if [ -d "$dir" ]; then
        du -sk "$dir" | cut -f1
    else
        echo "0"
    fi
}

# 构建依赖字符串 - 包含所有base
DEPENDS_STR=$(IFS=,; echo "${BASENAMES_ORIG[*]}")

# 创建control文件
cat > "${PKG_BUILD_DIR}/DEBIAN/control" << EOF
Package: $NEW_PKGNAME
Version: $NEW_VERSION
Architecture: $ORIG_ARCH
Maintainer: APM Converter <apm-convert@spark-app.store>
Depends: $DEPENDS_STR
Installed-Size: $(calculate_directory_size $PKG_BUILD_DIR)
Description: APM converted package from $ORIG_PKGNAME
  This package was automatically converted from the original deb package.
  Based on: ${BASENAMES_ORIG[*]}
EOF

# 生成输出文件名
OUTPUT_DEB="${NEW_PKGNAME}_${NEW_VERSION}_${ORIG_ARCH}.deb"

# 打包
fakeroot  dpkg-deb -Z xz --build "$PKG_BUILD_DIR" "$OUTPUT_DEB"

log.info  "转换完成！"
log.info "生成的APM包: $OUTPUT_DEB"
log.info "包名: $NEW_PKGNAME"
log.info "版本: $NEW_VERSION"
log.info "架构: $ORIG_ARCH"
log.info "依赖: $DEPENDS_STR"
log.info "基础环境: ${BASENAMES[*]}"
log.info "注意：桌面文件已修改，添加了APM运行前缀和APPID"