#!/usr/bin/env bash
# 好用斋 Docker 懒人包 —— 单应用安装 / 更新
# 把某个应用追加到该系统的 docker-compose.yml（重复执行安全：装新应用追加，重装同一个应用先替换旧块）。
#
# 用法：bash hyz-append.sh <系统id> <应用id> [--arm|--x86] [--no-up] [--user <拾光坞用户名>] [--base <基本路径>] [--tools <工具路径>]
#  系统id：feiniu istoreos ugreen dsm tos sgw wsl
#  例：bash hyz-append.sh feiniu jellyfin
#  拾光坞：bash hyz-append.sh sgw jellyfin --user <拾光坞用户名>
#
# 拾光坞(sgw) 必须提供 --user 或 --base（用户名不同，存储路径就不同）：
#  --user   拾光坞用户名，基本路径 = /mnt/usb1/<用户名>
#  --base   直接指定基本路径（目录必须已存在，脚本不会自动创建）
#  --tools  自定义工具路径，默认 <基本路径>/tools
#
# 可选环境变量：
#  HYZ_BASE        站点地址，默认 https://haoyongzhai.com
#  HYZ_COMPOSE_DIR 覆盖 compose 目录（自定义过目录时用）
#  HYZ_FILE        覆盖 compose 文件名，默认 docker-compose.yml
set -euo pipefail
# 固定 cwd 到 /tmp，避免 TOS 等系统上子 shell getcwd 失败刷 shell-init 报错
cd /tmp

BASE="${HYZ_BASE:-https://haoyongzhai.com}"
sys="${1:-}"
app="${2:-}"
arch=""
archset=""
do_up=1
sgw_user="${HYZ_USER:-}"
sgw_base="${HYZ_BASE_PATH:-}"
sgw_tools="${HYZ_TOOLS_PATH:-}"
for ((i=3; i<=$#; i++)); do
  a="${!i}"
  case "$a" in
    --arm) arch=arm; archset=1 ;;
    --x86) arch=x86; archset=1 ;;
    --no-up) do_up=0 ;;
    --user=*) sgw_user="${a#*=}" ;;
    --base=*) sgw_base="${a#*=}" ;;
    --tools=*) sgw_tools="${a#*=}" ;;
    --user|--base|--tools)
      j=$((i+1))
      [ "$j" -le "$#" ] || { echo "参数 $a 缺少值" >&2; exit 1; }
      v="${!j}"
      case "$a" in
        --user) sgw_user="$v" ;;
        --base) sgw_base="$v" ;;
        --tools) sgw_tools="$v" ;;
      esac
      i=$((i+1))
      ;;
    *) echo "未知参数：$a" >&2; exit 1 ;;
  esac
done

case "$sys" in
  feiniu)   DIR=/vol1/1000/compose/all ;;
  istoreos)   DIR=/mnt/mydisk/compose/all ;;
  ugreen)   DIR=/volume1/docker/compose/all ;;
  dsm)   DIR=/volume1/docker/compose/all ;;
  tos)   DIR=/Volume1/DockerAppData/compose/all ;;
  sgw)   DIR=/mnt/usb1/haoyong/compose/all ;;
  wsl)   DIR=/mnt/mydisk/compose/all ;;
  *) echo "未知系统 id：${sys}（可用：feiniu istoreos ugreen dsm tos sgw wsl）" >&2; exit 1 ;;
esac
[ -n "$app" ] || { echo "用法：bash hyz-append.sh <系统id> <应用id> [--arm|--x86] [--no-up] [--user <拾光坞用户名>] [--base <基本路径>] [--tools <工具路径>]" >&2; exit 1; }

# 拾光坞：存储根目录随用户名变化，必须由用户提供（不写死）
if [ "$sys" = sgw ]; then
  sgw_base="${sgw_base:-${sgw_user:+/mnt/usb1/$sgw_user}}"
  if [ -z "$sgw_base" ]; then
    echo "❌ 拾光坞(SGW OS)需要先提供用户名才能继续安装" >&2
    echo "   请加参数：--user <拾光坞用户名>（基本路径默认为 /mnt/usb1/<用户名>）" >&2
    echo "   若存储路径不是这个规则，改用：--base <基本路径>" >&2
    exit 1
  fi
  sgw_base="${sgw_base%/}"
  if [ ! -d "$sgw_base" ]; then
    echo "❌ 基本路径不存在：$sgw_base" >&2
    echo "   请检查拾光坞用户名或 --base 是否正确（脚本不会自动创建基本路径）" >&2
    exit 1
  fi
  DIR="$sgw_base/compose/all"
  sgw_tools="${sgw_tools:-$sgw_base/tools}"
fi
DIR="${HYZ_COMPOSE_DIR:-$DIR}"
F="${HYZ_FILE:-$DIR/docker-compose.yml}"

# 未指定 --arm / --x86 时按机器架构自动判断
if [ -z "${archset:-}" ]; then
  case "$(uname -m)" in aarch64|arm64) arch=arm ;; esac
fi
blk="$app"
[ "$arch" = arm ] && blk="$app-arm"
url="$BASE/lazybag/install/$sys/$blk.yml"
urlx="$BASE/lazybag/install/$sys/$app.yml"
# ARM 机器上，没有独立 ARM 模板的应用用 x86 块（与官网规则一致）
if [ "$arch" = arm ] && ! curl -fsSL -o /dev/null "$url" 2>/dev/null; then
  url="$urlx"
fi

mkdir -p "$DIR"
[ -f "$F" ] || printf 'services:\n' > "$F"

tmp="$(mktemp)"
tmp2="$(mktemp)"
trap 'rm -f "$tmp" "$tmp2" "$tmp.p"' EXIT
curl -fsSL -o "$tmp" "$url" || { echo "下载失败：$url" >&2; exit 1; }

# 拾光坞：模板里是默认用户名 haoyong 的路径，按用户实际路径替换
# 顺序：先替换更具体的 TOOLS（/mnt/usb1/haoyong/tools），再替换 BASE（/mnt/usb1/haoyong）
if [ "$sys" = sgw ]; then
  def_base="/mnt/usb1/haoyong"
  def_tools="$def_base/tools"
  esc() { printf '%s' "$1" | sed 's/[\\&|]/\\&/g'; }
  if [ "$sgw_tools" != "$def_tools" ]; then
    sed "s|$(esc "$def_tools")|$(esc "$sgw_tools")|g" "$tmp" > "$tmp.p" && mv "$tmp.p" "$tmp"
  fi
  if [ "$sgw_base" != "$def_base" ]; then
    sed "s|$(esc "$def_base")|$(esc "$sgw_base")|g" "$tmp" > "$tmp.p" && mv "$tmp.p" "$tmp"
  fi
fi

# 【可选】替换默认 NAS IP（HYZ_IP 为空时跳过，行为与旧版完全一致）
if [ -n "${HYZ_IP:-}" ]; then
  sed "s/192.168.31.245/${HYZ_IP}/g" "$tmp" > "$tmp.ip" && mv "$tmp.ip" "$tmp"
fi

# 【可选】预创建该应用的宿主数据目录（HYZ_MKDIRS=1 时启用；默认关闭，目录交给 docker 自建）
if [ "${HYZ_MKDIRS:-0}" = 1 ]; then
  awk '
/^    volumes:/ { inv=1; next }
inv && /^    [a-zA-Z]/ { inv=0 }
inv && /^      - / {
  s = substr($0, index($0,"- ")+2)
  i = index(s, ":")
  if (i > 0) s = substr(s, 1, i-1)
  if (substr(s,1,1) == "/" && index(s,"/dev/") != 1 && index(s,"docker.sock") == 0) print s
}
' "$tmp" | while read -r p; do mkdir -p "$p"; done || true
fi

svc="$(awk '/^  [A-Za-z0-9][A-Za-z0-9_.-]*:$/{gsub(/[:]/,"",$1); print $1; exit}' "$tmp")"
[ -n "$svc" ] || { echo "块文件里没找到服务名：$url" >&2; exit 1; }

# 删掉该应用在文件里的旧块（新版带标记的块，和交互页导出的无标记块都能识别），再追加新块
awk -v id="$app" -v svc="$svc" '
function all(   i) { for (i = 1; i <= n; i++) print b[i]; n = 0 }
function keep(   i, k) {
  k = 0
  for (i = 1; i <= n; i++) if (b[i] ~ /^# >>> APP /) k = i
  if (!k) for (i = 1; i <= n; i++) if (b[i] ~ /^#{4,}/) k = i
  for (i = 1; i < k; i++) print b[i]
  n = 0
}
$0 == "# >>> APP " id " >>>" { n = 0; inm = 1; next }
$0 == "# <<< APP " id " <<<" { n = 0; inm = 0; next }
/^  [A-Za-z0-9][A-Za-z0-9_.-]*:$/ {
  name = $1; sub(/:$/, "", name)
  if (name == svc) { keep(); insvc = 1; next }
  all(); insvc = 0; print; next
}
inm { next }
insvc && /^[ \t]/ { next }
insvc && (/^#{4,}/ || /^# >>> APP /) { insvc = 0 }
insvc && /^[ \t]*$/ { next }
insvc && /^#/ { next }
insvc { insvc = 0 }
{ if ($0 ~ /^[ \t]*$/ || $0 ~ /^#/) { b[++n] = $0; next } all(); print }
END { all() }
' "$F" > "$tmp2"
# 先在临时文件上合成并校验，通过后才替换真实文件，避免失败时把原文件写坏
cat "$tmp" >> "$tmp2"
cd "$DIR"
if ! docker compose -f "$tmp2" config -q; then
  echo "❌ compose 校验失败，已保留原文件不动：$F（本次 ${app} 未写入）" >&2
  exit 1
fi
mv "$tmp2" "$F"
echo "✅ 已写入：${app}（服务名 ${svc}）→ $F"
if [ "$do_up" = 1 ]; then
  docker compose -f "$F" up -d
  echo "✅ 已启动 / 更新。以后升级：cd $DIR && docker compose pull && docker compose up -d"
else
  echo "（--no-up）未启动；手动启动：cd $DIR && docker compose up -d"
fi
