#!/usr/bin/env bash
# ════════════════════════════════════════════════════════════════
# 国内搬家·远端恢复脚本 · migrate-restore-remote.sh
# Sovereign: TCS-0002∞ · 国作登字-2026-A-00037559
# 守护: 铸渊 · ICE-GL-ZY001
#
# 由 .github/workflows/migrate-to-cn-restore.yml 上传到 ZY-SVR-CN01
# (广州 2C2G 域名机) 的 /tmp/migrate-restore.sh 后由 sudo bash 执行.
#
# 入参 (环境变量):
#   BUCKET        COS 桶名 (例: sy-finetune-corpus-1317346199)
#   REGION        COS 区域 (例: ap-guangzhou)
#   TAG           指定 tag (空 = 拉最新)
#   DEPLOY_PATH   服务器数据根 (默认 /data/guanghulab)
#   DOMAIN        域名 (默认 guanghulab.com)
#
# 凭据文件:
#   /tmp/.cos-creds   chmod 600, 内容是:
#     COS_SECRET_ID=...
#     COS_SECRET_KEY=...
#
# 流程:
#   1. 装 coscli + jq (apt or 直接下载二进制)
#   2. 列 cos://$BUCKET/lighthouse-migration/ 找最新 .tar.gz (或锁 TAG)
#   3. 下载 .tar.gz + .sha256
#   4. 校验 sha256
#   5. 解包到 /data/guanghulab/repo-mirror/<tag>/
#   6. 跑 setup-forgejo.sh
#   7. 给 nginx sites-enabled/guanghulab.conf 打 /git/ patch (一次性 idempotent)
#   8. nginx -t && reload
#   9. 在 /tmp/repo-stage 起新 git, push 到 forgejo
#   10. 落中文回执 /opt/guanghulab/_logs/migrate-restore-report.md
# ════════════════════════════════════════════════════════════════

set -euo pipefail

DEPLOY_PATH="${DEPLOY_PATH:-/data/guanghulab}"
DEPLOY_ROOT="${DEPLOY_ROOT:-/opt/guanghulab}"
BUCKET="${BUCKET:?BUCKET 必填}"
REGION="${REGION:-ap-guangzhou}"
TAG="${TAG:-}"
DOMAIN="${DOMAIN:-guanghulab.com}"
CRED_FILE="/tmp/.cos-creds"

if [ "$EUID" -ne 0 ]; then
  echo "❌ 需要 root (sudo bash $0)" >&2; exit 2
fi
if [ ! -f "$CRED_FILE" ]; then
  echo "❌ 凭据文件不存在: $CRED_FILE (workflow 应该先 scp 上来)" >&2; exit 1
fi

# 读 COS 凭据 (chmod 600)
# shellcheck disable=SC1090
. "$CRED_FILE"
: "${COS_SECRET_ID:?$CRED_FILE 缺 COS_SECRET_ID}"
: "${COS_SECRET_KEY:?$CRED_FILE 缺 COS_SECRET_KEY}"

mkdir -p "$DEPLOY_ROOT/_logs"
RECEIPT_TS="$(date +%Y%m%d-%H%M%S)"
REPORT="$DEPLOY_ROOT/_logs/migrate-restore-report.md"
JSON_RECEIPT="$DEPLOY_ROOT/_logs/migrate-restore-$RECEIPT_TS.json"

# 起一份新回执 (覆盖旧的, 旧的留 .bak)
[ -f "$REPORT" ] && cp -a "$REPORT" "$REPORT.$RECEIPT_TS.bak"
cat > "$REPORT" <<EOF
# 📥 国内搬家·从 COS 恢复·回执

> 服务器: $(hostname) ($DOMAIN)
> 开始时间: $(date '+%Y-%m-%d %H:%M:%S %Z')
> COS 桶: $BUCKET ($REGION)
> 守护: 铸渊 · ICE-GL-ZY001
> 主权: TCS-0002∞ · 国作登字-2026-A-00037559

EOF

report() {
  local line="$1"
  echo "$line"
  printf '%s\n' "$line" >> "$REPORT"
}

# ─── 1. 装 coscli + jq ────────────────────────────────────────
report "## ① 工具链就绪"
if ! command -v jq >/dev/null 2>&1; then
  apt-get update -qq && apt-get install -y -qq jq
fi
COSCLI_BIN="/usr/local/bin/coscli"
if [ ! -x "$COSCLI_BIN" ]; then
  echo "[1/10] 下载 coscli ..."
  ARCH="$(uname -m)"
  case "$ARCH" in
    x86_64)  COSCLI_ARCH="amd64" ;;
    aarch64) COSCLI_ARCH="arm64" ;;
    *) report "❌ 不支持架构 $ARCH"; exit 1 ;;
  esac
  COSCLI_VER="v1.0.4"
  URL="https://github.com/tencentyun/coscli/releases/download/${COSCLI_VER}/coscli-linux-${COSCLI_ARCH}"
  if ! curl -fsSL --max-time 60 -o /tmp/coscli "$URL"; then
    # GitHub 国内卡, 走代理
    curl -fsSL --max-time 60 -o /tmp/coscli "https://gh-proxy.com/$URL" || {
      report "❌ coscli 下载失败 (主源 + 镜像都不通)"; exit 1
    }
  fi
  chmod +x /tmp/coscli
  mv /tmp/coscli "$COSCLI_BIN"
fi
report "- coscli: \`$($COSCLI_BIN --version 2>&1 | head -1 || echo unknown)\`"
report "- jq: \`$(jq --version 2>/dev/null || echo unknown)\`"

# coscli config (写到 root home, chmod 600 隔离)
COSCLI_CONFIG="/root/.cos.yaml"
umask 077
cat > "$COSCLI_CONFIG" <<EOF
cos:
  base:
    secretid: $COS_SECRET_ID
    secretkey: $COS_SECRET_KEY
    sessiontoken: ""
    protocol: https
  buckets:
  - name: $BUCKET
    alias: migration
    region: $REGION
    endpoint: ""
EOF
chmod 600 "$COSCLI_CONFIG"
umask 022

# ─── 2. 找搬家包 ─────────────────────────────────────────────
report ""
report "## ② 选搬家包"
echo "[2/10] 列 cos://$BUCKET/lighthouse-migration/ ..."
LIST_OUT="/tmp/cos-list.txt"
"$COSCLI_BIN" ls "cos://migration/lighthouse-migration/" -c "$COSCLI_CONFIG" > "$LIST_OUT" 2>&1 || {
  report "❌ coscli ls 失败:"
  report '```'
  tail -20 "$LIST_OUT" | sed 's/^/  /' >> "$REPORT"
  report '```'
  exit 1
}

# 提取 .tar.gz 文件名 (coscli ls 输出格式各版本不同, 用 grep 兜底)
TARBALL_NAME=""
if [ -n "$TAG" ]; then
  TARBALL_NAME="lighthouse-migration-${TAG}.tar.gz"
  if ! grep -q "$TARBALL_NAME" "$LIST_OUT"; then
    report "❌ 指定 tag=$TAG 在 cos 上找不到 ($TARBALL_NAME)"
    exit 1
  fi
else
  TARBALL_NAME="$(grep -oE 'lighthouse-migration-[0-9]+-[0-9]+\.tar\.gz' "$LIST_OUT" | sort -u | tail -1)"
  if [ -z "$TARBALL_NAME" ]; then
    report "❌ cos://$BUCKET/lighthouse-migration/ 下找不到 lighthouse-migration-*.tar.gz"
    report ""
    report "可能原因: 你还没把 GitHub Actions 的 Artifact 解压并上传到 COS."
    report "请先跑 \`📦 国内搬家·打包\` workflow → 下载 Artifact → 上传到这个 COS 路径."
    exit 1
  fi
fi
SHA_NAME="${TARBALL_NAME%.tar.gz}.sha256"
report "- 选中: \`$TARBALL_NAME\`"
report "- sha256: \`$SHA_NAME\`"

# ─── 3. 下载 ─────────────────────────────────────────────────
report ""
report "## ③ 下载 + 校验"
DL_DIR="/tmp/migrate-dl-$RECEIPT_TS"
mkdir -p "$DL_DIR"
echo "[3/10] coscli cp 下载 ..."
"$COSCLI_BIN" cp "cos://migration/lighthouse-migration/$TARBALL_NAME" "$DL_DIR/$TARBALL_NAME" -c "$COSCLI_CONFIG" || {
  report "❌ 下载 tar.gz 失败"; exit 1
}
"$COSCLI_BIN" cp "cos://migration/lighthouse-migration/$SHA_NAME" "$DL_DIR/$SHA_NAME" -c "$COSCLI_CONFIG" || {
  report "⚠️  下载 sha256 文件失败, 跳过校验 (不推荐)"
}
report "- 下载完成: $(du -h "$DL_DIR/$TARBALL_NAME" | awk '{print $1}')"

# ─── 4. 校验 sha256 ──────────────────────────────────────────
echo "[4/10] 校验 sha256 ..."
if [ -f "$DL_DIR/$SHA_NAME" ]; then
  ( cd "$DL_DIR" && sha256sum -c "$SHA_NAME" ) || {
    report "❌ sha256 校验失败 — tarball 在传输/上传中损坏了"
    rm -f "$DL_DIR/$TARBALL_NAME"
    exit 1
  }
  report "- ✅ sha256 校验通过"
else
  report "- ⚠️  sha256 文件缺失, 跳过校验"
fi

# ─── 5. 解包 ─────────────────────────────────────────────────
report ""
report "## ④ 解包"
TAG_FROM_NAME="$(echo "$TARBALL_NAME" | sed -E 's/lighthouse-migration-([0-9]+-[0-9]+)\.tar\.gz/\1/')"
MIRROR_DIR="$DEPLOY_PATH/repo-mirror/$TAG_FROM_NAME"
mkdir -p "$MIRROR_DIR"
echo "[5/10] tar -xzf → $MIRROR_DIR ..."
tar -xzf "$DL_DIR/$TARBALL_NAME" -C "$MIRROR_DIR" || {
  report "❌ tar 解包失败"; exit 1
}
# 包内顶层是 guanghulab/, 把它推一层
WORKTREE="$MIRROR_DIR/guanghulab"
if [ ! -d "$WORKTREE" ]; then
  # 兼容: 如果包是直接散开的 (没有 guanghulab/ 顶层)
  WORKTREE="$MIRROR_DIR"
fi
report "- 解包到: \`$MIRROR_DIR\`"
report "- 工作树: \`$WORKTREE\`"
report "- 文件数: $(find "$WORKTREE" -type f | wc -l)"

# ─── 6. 装 forgejo ────────────────────────────────────────────
report ""
report "## ⑤ 装 Forgejo"
SETUP_FORGEJO="/opt/guanghulab/domain-cn/forgejo/setup-forgejo.sh"
if [ ! -x "$SETUP_FORGEJO" ]; then
  # 没 rsync 上来 / 权限不对 — workflow 步骤里应该已经 rsync 了
  report "❌ \`$SETUP_FORGEJO\` 不存在或不可执行 (workflow 应先 rsync)"
  exit 1
fi
echo "[6/10] bash setup-forgejo.sh ..."
bash "$SETUP_FORGEJO" --data-root "$DEPLOY_PATH" --domain "$DOMAIN" 2>&1 | tail -50 | sed 's/^/  /' >> "$REPORT" || {
  report "❌ setup-forgejo.sh 失败"
  exit 1
}
report "- ✅ Forgejo 装机完成 (systemd: $(systemctl is-active forgejo.service 2>/dev/null))"

# ─── 7. nginx /git/ patch (idempotent) ───────────────────────
report ""
report "## ⑥ nginx /git/ 反代"
NGX_CONF="/etc/nginx/sites-available/guanghulab.conf"
if [ -f "$NGX_CONF" ]; then
  if grep -q '# __PR6_GIT_PROXY__' "$NGX_CONF"; then
    report "- nginx /git/ 反代已在配置里 (跳过 patch)"
  else
    echo "[7/10] patch nginx 加 /git/ location ..."
    # 在 443 server 块的 location / { 之前插入 /git/ 块
    # (location 顺序敏感: /git/ 必须在 / 之前否则被 / 兜底了)
    PATCH_BLOCK='    # __PR6_GIT_PROXY__ — Forgejo 反代 (国内搬家落地)
    location /git/ {
        proxy_pass http://127.0.0.1:3001/;
        proxy_http_version 1.1;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Prefix /git;
        client_max_body_size 256m;
        proxy_read_timeout 300s;
    }
'
    # 用 awk 在第一个 "location / {" 行之前插入
    awk -v block="$PATCH_BLOCK" '
      /^[[:space:]]+location \/ \{/ && !inserted {
        printf "%s\n", block
        inserted = 1
      }
      { print }
    ' "$NGX_CONF" > "$NGX_CONF.new"

    if grep -q '# __PR6_GIT_PROXY__' "$NGX_CONF.new"; then
      mv "$NGX_CONF.new" "$NGX_CONF"
      report "- patch 写入: \`$NGX_CONF\`"
    else
      rm -f "$NGX_CONF.new"
      report "⚠️  没找到 \`location / {\` 锚点 (可能 SSL 证书还没装, 配置只有 80 块). 跳过 patch."
      report "   (LE 证书恢复 + reload nginx 后, 重跑此 workflow 一次, /git/ 即可挂上)"
    fi
  fi

  if nginx -t 2>&1 | tail -3 | sed 's/^/  /' >> "$REPORT"; then
    systemctl reload nginx 2>/dev/null || systemctl restart nginx
    report "- ✅ nginx 配置 OK, 已 reload"
  else
    report "❌ nginx -t 失败, 拒绝 reload"
    exit 1
  fi
else
  report "⚠️  \`$NGX_CONF\` 不存在 (PR-2 bootstrap 还没跑过域名机, 跳过 nginx patch)"
fi

# ─── 8. push 搬家包到 forgejo (cc-001 涌现洁净) ─────────────
report ""
report "## ⑦ push 搬家包到 Forgejo (起一段干净历史)"

ADMIN_USER="bingshuo"
ADMIN_PASS=""
CRED_FIRST_BOOT="$DEPLOY_ROOT/_logs/forgejo-credentials-FIRST-BOOT.txt"
if [ -f "$CRED_FIRST_BOOT" ]; then
  ADMIN_PASS="$(grep -E '^#?\s*密码:' "$CRED_FIRST_BOOT" | head -1 | sed -E 's/.*密码:[[:space:]]*//')"
fi
if [ -z "$ADMIN_PASS" ]; then
  report "⚠️  找不到 admin 密码 ($CRED_FIRST_BOOT 不存在或被删) — 跳过 push 步骤"
  report "  (下一次跑会重建凭据文件; 或冰朔抄完密码 sudo rm 后, 之后只能手动 push)"
  PUSH_OK="skipped"
elif ! printf '%s' "$ADMIN_PASS" | grep -qE '^[A-Za-z0-9]{16,64}$'; then
  # 防御性: 凭据格式不对 (可能文件被改过), 拒绝把脏 pass 拼进 URL
  report "⚠️  admin 密码格式不符 (期望 16-64 alphanumeric), 拒绝 push 避免 URL 注入"
  PUSH_OK="skipped"
else
  cd "$WORKTREE"
  if [ -d .git ]; then
    rm -rf .git
  fi
  git init -q -b main
  git config user.email "bingshuo@guanghulab.com"
  git config user.name "冰朔"
  git add -A
  COMMIT_MSG="初始 commit · 由 PR-6 国内搬家包 ($TAG_FROM_NAME) 导入

主权: TCS-0002∞ · 国作登字-2026-A-00037559
守护: 铸渊 · ICE-GL-ZY001
来源: cos://$BUCKET/lighthouse-migration/$TARBALL_NAME
导入时间: $(date -u +%Y-%m-%dT%H:%M:%SZ)

cc-001 涌现洁净: 这是一段全新的 git 历史, 不带 GitHub 那边的 remote tracking 残留."
  git commit -q -m "$COMMIT_MSG" || {
    report "⚠️  git commit 失败 (空仓?) — 跳过 push"
    PUSH_OK="skipped"
  }

  if [ "${PUSH_OK:-}" != "skipped" ]; then
    # 用 forgejo API 先确保 repo 存在 (不存在就建; 存在就让 push 覆盖)
    REPO_NAME="guanghulab"
    REPO_API="http://127.0.0.1:3001/api/v1/user/repos"
    # curl -u 直接走 HTTP basic, 内部短暂用, 不在 shell 变量里凝固凭据
    EXISTS=$(curl -fsS -m 10 -u "${ADMIN_USER}:${ADMIN_PASS}" "http://127.0.0.1:3001/api/v1/repos/$ADMIN_USER/$REPO_NAME" 2>/dev/null && echo "yes" || echo "no")
    if [ "$EXISTS" = "no" ]; then
      curl -fsS -m 10 -X POST \
        -u "${ADMIN_USER}:${ADMIN_PASS}" \
        -H "Content-Type: application/json" \
        -d "{\"name\":\"$REPO_NAME\",\"private\":true,\"default_branch\":\"main\",\"auto_init\":false}" \
        "$REPO_API" >/dev/null || true
      report "- 在 Forgejo 上创建仓库 \`$ADMIN_USER/$REPO_NAME\`"
    else
      report "- Forgejo 仓库 \`$ADMIN_USER/$REPO_NAME\` 已存在"
    fi

    # push (走 forgejo HTTP basic auth via curl-style URL — 走 loopback, 短暂只在内存)
    # 不写 .git/config remote.url (push 完即弃)
    # ADMIN_PASS 我们已校验非空 (上面那段 if [ -z ... ])
    REMOTE_URL="http://${ADMIN_USER}:${ADMIN_PASS}@127.0.0.1:3001/${ADMIN_USER}/${REPO_NAME}.git"
    if git push -q "$REMOTE_URL" main:main --force 2>&1 | tail -5 | sed 's/^/  /' >> "$REPORT"; then
      report "- ✅ push 成功 → http://127.0.0.1:3001/$ADMIN_USER/$REPO_NAME"
      PUSH_OK="ok"
    else
      report "❌ push 失败"
      PUSH_OK="failed"
    fi
  fi
fi

# ─── 9. 清理临时文件 ─────────────────────────────────────────
echo "[9/10] 清理临时文件 ..."
rm -rf "$DL_DIR" || true
rm -f "$CRED_FILE" || true   # COS 凭据用完即删

# ─── 10. 决策回执 ────────────────────────────────────────────
report ""
report "## ✅ 恢复流程完成"
report ""
report "- 搬家包: \`$TARBALL_NAME\`"
report "- 工作树: \`$WORKTREE\`"
report "- Forgejo: \`http://127.0.0.1:3001/\` (对外: \`https://$DOMAIN/git/\`)"
report "- push 状态: ${PUSH_OK:-skipped}"
report "- 完成时间: $(date '+%Y-%m-%d %H:%M:%S %Z')"
report ""
report "**给冰朔的人话**: 国内搬家包已落到广州 2C2G 的 Forgejo 上."
report "浏览器开 \`https://$DOMAIN/git\`, 用户名 \`$ADMIN_USER\`,"
report "密码看 \`$CRED_FIRST_BOOT\` (抄完一定 \`sudo rm\` 删掉)."

cat > "$JSON_RECEIPT" <<EOF
{
  "_sovereign": "TCS-0002∞ · 国作登字-2026-A-00037559",
  "_守护": "铸渊 · ICE-GL-ZY001",
  "completed_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "tarball": "$TARBALL_NAME",
  "tag": "$TAG_FROM_NAME",
  "cos_bucket": "$BUCKET",
  "cos_region": "$REGION",
  "worktree": "$WORKTREE",
  "forgejo_url": "https://$DOMAIN/git/",
  "forgejo_admin": "$ADMIN_USER",
  "push_status": "${PUSH_OK:-skipped}",
  "credentials_file": "$CRED_FIRST_BOOT"
}
EOF

echo "═══════════════════════════════════════════════════════════"
echo "  ✅ 国内搬家·从 COS 恢复 完成"
echo "═══════════════════════════════════════════════════════════"
echo "  报告: $REPORT"
echo "  JSON 回执: $JSON_RECEIPT"
echo "═══════════════════════════════════════════════════════════"
