#!/usr/bin/env bash
# ============================================================
#  XHCOS Lite (Mint) 2.0.0 — 基于 Linux Mint 22.3 XFCE 64-bit 改造构建
#  目标设备：Dell Wyse 3040（2GB RAM / 8GB eMMC 焊接，Atom x5-Z8350）
#  路线：XHCOS Lite —— 桌面已是 XFCE，只做品牌换皮 + 适度精简 + 注入
#        Calamares(XHCOS) 安装器界面（对齐 XHCOSEmulator 安装界面）。
#
#  ★ 关键约束（与 Ubuntu 版不同）：
#   1) C 盘已满/损坏 → 所有重活放在 D 盘；
#   2) Mint 22.3 的 filesystem.squashfs 约 4.x GB，藏在 ISO 的 UDF 层，
#      WSL2 的 drvfs 读不到 UDF 里的 >4GB 文件，loop 挂载也因缺 UDF 模块失败。
#  ★ 解法：
#   - 用 7-Zip（原生读 UDF + 写 NTFS >4GB 文件）解包 ISO 到 D:\xhcos-lite-mint\iso
#     · 优先用 WSL 内原生 7z（apt install p7zip-full），它自带 ISO/UDF 解析，
#       不经过系统挂载，能直接抽出 >4GB squashfs；
#     · 没有原生 7z 时回退到 Windows 7-Zip（7z.exe）。
#   - 在 D 盘建 16GB ext4 镜像（loop 挂载为 /xhcos-work），chroot/unsquashfs/
#     mksquashfs 全在这上面跑（绕开 NTFS 不支持的设备节点/符号链接，且不占 C 盘）
#
#  在 WSL2 以 root 运行：
#     sudo bash build-xhcos-mint.sh
#  或指定源 ISO：
#     SRC_ISO=/mnt/d/linuxmint-22.3-xfce-64bit.iso sudo bash build-xhcos-mint.sh
#  产物：D:\xhcos-lite-mint\XHCOS-Lite-Mint-2.0.0-amd64.iso
# ============================================================

# ---------- 启动横幅 + 日志（最先执行，确保一定有可见输出 + 持久日志） ----------
echo "══════════════════════════════════════════════════════"
echo " XHCOS Lite (Mint) 2.0.0 构建脚本"
echo " 启动时间: $(date '+%F %T')"
echo "══════════════════════════════════════════════════════"
DROOT_GUESS="/mnt/d/xhcos-lite-mint"
BUILD_LOG="$DROOT_GUESS/build.$(date +%Y%m%d-%H%M%S).log"
mkdir -p "$DROOT_GUESS" 2>/dev/null || true
echo "（全过程日志写入 $BUILD_LOG，即使窗口关闭也能查）"
exec > >(tee -a "$BUILD_LOG") 2>&1

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
# 说明：脚本本身可以放在 D 盘（/mnt/d）直接跑——只读脚本/资产、最终 ISO 也写 D 盘。
# 唯一必须是 ext4 的是下面的工作镜像 work.img（已用 loop 挂载为 /xhcos-work），
# 切勿把 WORK 指向 /mnt/*（NTFS 不支持 chroot 需要的设备节点/符号链接）。

[[ $EUID -eq 0 ]] || { echo "!! 必须用 root 运行：sudo bash $0"; exit 1; }

# ---------- 0. 定位源 ISO ----------
# 优先用环境变量；否则按位置搜索（带 || true 防止 pipefail 在损坏挂载点上静默自杀）。
if [ -z "${SRC_ISO:-}" ]; then
  echo "==> 自动搜索源 ISO …"
  SRC_ISO=""
  CANDIDATE_DIRS="/mnt/d /mnt/d/xhcos-lite-mint /mnt/e /mnt/c/Users/xihaochen/Downloads /mnt/c/Users/xihaochen"
  for d in $CANDIDATE_DIRS; do
    [ -d "$d" ] || continue
    echo "    在 $d 查找 linuxmint*.iso …"
    found=$(timeout 25 find "$d" -maxdepth 5 -iname "linuxmint*.iso" 2>/dev/null | head -1) || true
    if [ -n "$found" ]; then SRC_ISO="$found"; echo "    找到：$SRC_ISO"; break; fi
  done
  # 也接受 D 盘根目录的任意 .iso（兜底）
  if [ -z "$SRC_ISO" ]; then
    found=$(timeout 25 find /mnt/d -maxdepth 2 -iname "*.iso" 2>/dev/null | head -1) || true
    [ -n "$found" ] && SRC_ISO="$found" && echo "    兜底找到 .iso：$SRC_ISO"
  fi
fi
if [ -z "$SRC_ISO" ] || [ ! -f "$SRC_ISO" ]; then
  echo "!! 找不到 linuxmint-22.3-xfce-64bit.iso。"
  echo "   请把 ISO 放到 D 盘，或显式指定："
  echo "   SRC_ISO=/mnt/d/linuxmint-22.3-xfce-64bit.iso sudo bash $0"
  exit 1
fi
echo "源 ISO：$SRC_ISO ($(du -h "$SRC_ISO" 2>/dev/null | cut -f1))"

# ---------- 7-Zip 路径检测 ----------
# 优先 WSL 原生 7z（自带 UDF 解析，无需 Windows 路径转换）；否则回退 Windows 7z.exe。
SEVENZ=""
SEVENZ_WIN=0
if command -v 7z >/dev/null 2>&1; then
  SEVENZ="7z"; echo "使用原生 7z: $(command -v 7z)"
elif command -v 7za >/dev/null 2>&1; then
  SEVENZ="7za"; echo "使用原生 7za: $(command -v 7za)"
else
  for p in "/mnt/c/Program Files/7-Zip/7z.exe" \
           "/mnt/c/Program Files (x86)/7-Zip/7z.exe" \
           "/mnt/c/ProgramData/chocolatey/bin/7z.exe" \
           "/mnt/c/Program Files/NanaZip/7z.exe"; do
    [ -x "$p" ] && SEVENZ="$p" && SEVENZ_WIN=1 && break
  done
  if [ -n "$SEVENZ" ]; then echo "使用 Windows 7z: $SEVENZ"; fi
fi
if [ -z "$SEVENZ" ]; then
  echo "!! 需要 7-Zip。二选一："
  echo "   (A) WSL 内安装原生 7z：  sudo apt-get install -y p7zip-full"
  echo "   (B) Windows 装 7-Zip：    https://7-zip.org  然后重跑本脚本"
  exit 1
fi

# ---------- 工作位置（全部在 D 盘） ----------
DROOT="/mnt/d/xhcos-lite-mint"
WORK_IMG="$DROOT/work.img"          # 36GB ext4 镜像
WORK_IMG_MIN=36                     # 最小容量(GB)，小于则自动重建（避免 mksquashfs 写满）
WORK="/xhcos-work"                  # loop 挂载点
ISO_OUT="${ISO_OUT:-$DROOT/XHCOS-Lite-Mint-2.0.0-amd64.iso}"
ASSETS="$SCRIPT_DIR/assets"
EXTRACT="$DROOT/iso"                # 7z 解包到 NTFS 的 ISO 树（含 >4GB squashfs）
mkdir -p "$DROOT"

# ---------- 清理旧挂载/绑定（防上次崩溃残留导致 rm 卡死） ----------
cleanup_mount(){
  for m in "$WORK/edit/proc" "$WORK/edit/sys" "$WORK/edit/dev/pts" "$WORK/edit/dev" "$WORK/edit/run"; do
    mountpoint -q "$m" 2>/dev/null && umount -l "$m" 2>/dev/null || true
  done
  mountpoint -q "$WORK" 2>/dev/null && umount -l "$WORK" 2>/dev/null || true
}
trap cleanup_mount EXIT

# ---------- 1. 安装宿主工具 ----------
echo "==> [0/7] 安装宿主工具 (xorriso unsquashfs rsync e2fsprogs)"
for pkg in xorriso squashfs-tools rsync e2fsprogs p7zip-full; do
  if ! dpkg -s "$pkg" >/dev/null 2>&1; then
    echo "    安装 $pkg …"
    apt-get install -y "$pkg" || echo "    !! $pkg 安装失败（可能无网络），后续若用到会报错"
  fi
done

# ---------- 2. 建 16GB ext4 工作镜像（D 盘，不占 C） ----------
echo "==> [1/7] 准备 D 盘 ext4 工作镜像 ($WORK_IMG)"
# 旧镜像太小会在 mksquashfs 阶段写满（edit/ + iso/ + 新 squashfs 峰值 ~21GB），
# 故小于 WORK_IMG_MIN 时强制重建，避免重跑仍复用 16GB 旧镜像而再次失败。
NEED_BYTES=$(( WORK_IMG_MIN * 1024 * 1024 * 1024 ))
REBUILD=0
if [ ! -f "$WORK_IMG" ]; then
  REBUILD=1
elif [ "$(stat -c %s "$WORK_IMG" 2>/dev/null || echo 0)" -lt "$NEED_BYTES" ]; then
  REBUILD=1
fi
if [ "$REBUILD" -eq 1 ]; then
  echo "    创建/重建 ${WORK_IMG_MIN}GB ext4 镜像（首次较慢）…"
  rm -f "$WORK_IMG"
  truncate -s ${WORK_IMG_MIN}G "$WORK_IMG"
  mkfs.ext4 -F -q "$WORK_IMG"
fi
mkdir -p "$WORK"
if ! mountpoint -q "$WORK"; then
  if ! mount -o loop "$WORK_IMG" "$WORK" 2>"$DROOT/mount.err"; then
    echo "!! loop 挂载工作镜像失败（可能 WSL 不支持在 /mnt/d 上 loop 普通文件）。"
    echo "   错误："; tail -5 "$DROOT/mount.err"
    echo "   备选：把工作镜像放到 WSL 原生 ext4（如 ~/xhcos-lite-mint/work.img）再跑；"
    echo "   或先在 PowerShell 建 VHDX 并挂载到某盘符，再把 WORK_IMG 指向它。"
    exit 1
  fi
fi
df -h "$WORK" | tail -1

# ---------- 3. 用 7-Zip 解包 ISO（绕开 UDF/>4GB 限制） ----------
echo "==> [2/7] 7-Zip 解包 ISO -> $EXTRACT"
if [ ! -f "$EXTRACT/casper/filesystem.squashfs" ] && [ ! -f "$EXTRACT/live/filesystem.squashfs" ]; then
  rm -rf "$EXTRACT"
  mkdir -p "$EXTRACT"
  if [ "$SEVENZ_WIN" -eq 1 ]; then
    # Windows 7z 吃 Windows 路径
    winiso=$(echo "$SRC_ISO" | sed -E 's#^/mnt/([a-z])/#\U\1:/#; s#/#\\#g')
    windst="D:\\xhcos-lite-mint\\iso"
    "$SEVENZ" x -y "-o$windst" "$winiso" > "$DROOT/7z.log" 2>&1 \
      || { echo "!! 7z 解包失败，详见 $DROOT/7z.log"; tail -15 "$DROOT/7z.log"; exit 1; }
  else
    # 原生 7z：直接吃 Linux 路径
    "$SEVENZ" x -y "-o$EXTRACT" "$SRC_ISO" > "$DROOT/7z.log" 2>&1 \
      || { echo "!! 7z 解包失败，详见 $DROOT/7z.log"; tail -15 "$DROOT/7z.log"; exit 1; }
  fi
fi
# Mint 用 casper，部分衍生用 live；都认
SQ=""
[ -f "$EXTRACT/casper/filesystem.squashfs" ] && SQ="$EXTRACT/casper/filesystem.squashfs"
[ -f "$EXTRACT/live/filesystem.squashfs" ]   && SQ="$EXTRACT/live/filesystem.squashfs"
if [ -z "$SQ" ]; then
  echo "!! 解包后找不到 filesystem.squashfs（casper/ 或 live/）。"
  echo "   解包目录内容："; ls -la "$EXTRACT" 2>/dev/null | head -30
  exit 1
fi
echo "    squashfs: $SQ ($(du -h "$SQ" 2>/dev/null | cut -f1))"

# 把解包树拷进 ext4 工作镜像（chroot/unsquashfs 需要 POSIX 文件系统）
echo "==> [3/7] 复制 ISO 树到 ext4 工作镜像"
rm -rf "$WORK/iso"; mkdir -p "$WORK/iso"
rsync -a --info=progress2 "$EXTRACT/" "$WORK/iso/" 2>/dev/null \
  || cp -a "$EXTRACT/." "$WORK/iso/"

# ---------- 4. unsquashfs ----------
echo "==> [4/7] 解包 filesystem.squashfs"
rm -rf "$WORK/edit"; mkdir -p "$WORK/edit"
unsquashfs -f -d "$WORK/edit" "$SQ"
echo "    解包完成"

# ---------- 5. chroot 品牌化 ----------
echo "==> [5/7] chroot 品牌化（XHCOS Lite + Calamares XHCOS 界面）"
mount --bind /proc    "$WORK/edit/proc"
mount --bind /sys     "$WORK/edit/sys"
mount --bind /dev     "$WORK/edit/dev"
mount --bind /dev/pts "$WORK/edit/dev/pts"
mount --bind /run     "$WORK/edit/run" 2>/dev/null || true
cp --remove-destination /etc/resolv.conf "$WORK/edit/etc/resolv.conf" 2>/dev/null || true
mkdir -p "$WORK/edit/root/xhcos-assets"
cp -r "$ASSETS"/* "$WORK/edit/root/xhcos-assets/"
cp "$SCRIPT_DIR/chroot-customize-mint.sh" "$WORK/edit/root/chroot-customize.sh"
chmod +x "$WORK/edit/root/chroot-customize.sh"
if chroot "$WORK/edit" /root/chroot-customize.sh; then
  echo "    chroot 品牌化成功"
else
  echo "!! chroot 品牌化脚本返回非 0，详见上方输出；继续打包（可能部分品牌未生效）"
fi
rm -f  "$WORK/edit/root/chroot-customize.sh"
rm -rf "$WORK/edit/root/xhcos-assets"
umount -l "$WORK/edit/run" 2>/dev/null || true
umount -l "$WORK/edit/dev/pts" "$WORK/edit/dev" "$WORK/edit/sys" "$WORK/edit/proc" 2>/dev/null || true
rm -f "$WORK/edit/etc/resolv.conf"

# ---------- 6. resquashfs ----------
echo "==> [6/7] 重新打包 squashfs (zstd)"
# 防盘满预检：编辑树 + ISO 树 + 新 squashfs 峰值约需 21GB，剩余须 > 8GB 才安全
FREE_GB=$(df -BG "$WORK" 2>/dev/null | awk 'NR==2{gsub("G","",$4); print $4+0}')
if [ "${FREE_GB:-0}" -lt 8 ]; then
  echo "!! 工作镜像剩余空间不足 ($FREE_GB GB)，mksquashfs 会写满失败。"
  echo "   请把 build-xhcos-mint.sh 顶部的 WORK_IMG_MIN 调大（如 48），并删除旧镜像："
  echo "   sudo rm -f $WORK_IMG && sudo bash $0"
  exit 1
fi
# 新 squashfs 写到「loop 副本」对应路径（xorriso 从该处读取），先删旧文件避免 mksquashfs 追加(append)
SQ_REL="${SQ#$EXTRACT/}"            # 例：casper/filesystem.squashfs
SQ_OUT="$WORK/iso/$SQ_REL"          # 例：/xhcos-work/iso/casper/filesystem.squashfs
rm -f "$SQ_OUT"
mksquashfs "$WORK/edit" "$SQ_OUT" \
  -comp zstd -Xcompression-level 19 -b 1048576 -no-progress -noappend -processors "$(nproc)"
du -sx --block-size=1 "$WORK/edit" 2>/dev/null | cut -f1 > "$(dirname "$SQ_OUT")/filesystem.size" || true

# ---------- 7. ISO 启动菜单品牌化（GRUB + isolinux） ----------
echo "==> [7/7] 改写 GRUB / isolinux（XHCOS 深蓝 + 橙）"
cp "$ASSETS/wallpaper/default.jpg" "$WORK/iso/boot/grub/xhcos-bg.jpg" 2>/dev/null || true
# 纯 sed 改写 grub.cfg（不依赖 python3；主机 WSL 可能没装 python3）
GRUB_CFG="$WORK/iso/boot/grub/grub.cfg"
if [ -f "$GRUB_CFG" ]; then
  sed -i 's/Linux Mint/XHCOS/g; s/Ubuntu/XHCOS/g' "$GRUB_CFG"
  if ! grep -qi "background_image" "$GRUB_CFG"; then
    sed -i '/loadfont/Ia insmod png' "$GRUB_CFG"
    sed -i '/insmod png/a background_image /boot/grub/xhcos-bg.jpg' "$GRUB_CFG"
  else
    sed -i -E 's#background_image[[:space:]]+[^[:space:]]+#background_image /boot/grub/xhcos-bg.jpg#' "$GRUB_CFG"
  fi
  sed -i -E 's/(\bboot=casper\b)/\1 noprompt fsck.mode=skip/g' "$GRUB_CFG"
  sed -i -E 's/\bmaybe-ubiquity\b//g' "$GRUB_CFG"
  sed -i -E 's/[[:space:]]{2,}/ /g' "$GRUB_CFG"
fi
# isolinux：文本替换 + 内核行补 noprompt
for cfg in "$WORK/iso/isolinux/isolinux.cfg" "$WORK/iso/isolinux/menu.cfg" \
           "$WORK/iso/isolinux/txt.cfg" "$WORK/iso/isolinux/stdmenu.cfg"; do
  [ -f "$cfg" ] || continue
  sed -i 's/Linux Mint/XHCOS/g; s/Ubuntu/XHCOS/g' "$cfg" 2>/dev/null || true
  sed -i -E 's/(\bboot=casper\b)/\1 noprompt fsck.mode=skip/g' "$cfg" 2>/dev/null || true
done

# ---------- 8. xorriso 重建 iso-hybrid ----------
echo "==> 重建 iso-hybrid -> $ISO_OUT"
MBR="$WORK/isohdpfx.bin"
dd if="$SRC_ISO" of="$MBR" bs=1 count=432 2>/dev/null || true
# 补全可能 7z 漏抽的 BIOS 引导段
if [ ! -f "$WORK/iso/isolinux/isolinux.bin" ]; then
  xorriso -indev "$SRC_ISO" -osirrox on -extract isolinux/isolinux.bin \
    "$WORK/iso/isolinux/isolinux.bin" 2>/dev/null || true
fi
xorriso -as mkisofs \
  -iso-level 3 -full-iso9660-filenames \
  -volid "XHCOS_LITE_MINT_2_0_0" \
  -eltorito-boot isolinux/isolinux.bin \
  -eltorito-catalog isolinux/boot.cat \
  -no-emul-boot -boot-load-size 4 -boot-info-table \
  -eltorito-alt-boot -e boot/grub/efi.img \
  -no-emul-boot -isohybrid-gpt-basdat -isohybrid-mbr "$MBR" \
  -c isolinux/boot.cat -o "$ISO_OUT" "$WORK/iso"

echo "=================================================="
echo "构建完成 -> $ISO_OUT"
ls -lh "$ISO_OUT"
echo "（工作镜像 $WORK_IMG 可保留复用；要释放 D 盘空间执行："
echo "   sudo umount /xhcos-work && rm -f $WORK_IMG ）"
echo "日志：$BUILD_LOG"
echo "=================================================="
