name: '✦ FTCHAT 部署 · guanghu.online (微调模型内测)'

# ═══════════════════════════════════════════════════════════
# 光湖 · 微调模型团队内测站 部署工作流
# 编号: ZY-WF-FTCHAT
# 守护: 铸渊 · ICE-GL-ZY001
# 版权: 国作登字-2026-A-00037559
#
# 目标服务器: ZY-SVR-006 (43.153.203.105 · 新加坡)
# 域名:       guanghu.online
# 部署路径:   /opt/guanghu/ftchat
# 后端端口:   3010 (内部, Nginx 反代)
# 进程名:     ftchat-api (PM2)
#
# 复用 Secrets (与 novel-mirror-shield 同服务器):
#   ZY_NOVEL_HOST  — 43.153.203.105
#   ZY_NOVEL_USER  — root
#   ZY_NOVEL_KEY   — SSH 私钥
#
# 新增 Secrets:
#   FT_NOTION_API_TOKEN     — Notion Internal Integration token
#   FT_NOTION_PROMPT_PAGE_ID — Notion 系统提示词页面 ID
#   FT_DASHSCOPE_API_KEY    — 阿里云百炼 API Key (区分商业模型)
#   ZY_SMTP_USER / ZY_SMTP_PASS — QQ 邮箱 SMTP (验证码发件)
# ═══════════════════════════════════════════════════════════

on:
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'server/ftchat/**'
      - 'server/nginx/ftchat-guanghu-online.conf'
      - 'frontend/ftchat/**'
      - 'package.json'
      - 'package-lock.json'
      - '.github/workflows/deploy-ftchat-guanghu-online.yml'
  workflow_dispatch:
    inputs:
      action:
        description: '执行动作'
        required: true
        default: 'deploy'
        type: choice
        options:
          - deploy
          - retire-zhiku
          - health
          - rollback

jobs:
  deploy:
    name: '🚀 部署 FTCHAT'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    if: |
      github.event_name == 'push' ||
      (github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'deploy')

    steps:
      - name: '📥 检出代码'
        uses: actions/checkout@v4

      - name: '🔑 配置 SSH'
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ZY_NOVEL_KEY }}" > ~/.ssh/ftchat_key
          chmod 600 ~/.ssh/ftchat_key
          ssh-keyscan -H ${{ secrets.ZY_NOVEL_HOST }} >> ~/.ssh/known_hosts

      - name: '📦 服务器准备目录'
        run: |
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          mkdir -p /opt/guanghu/ftchat/{src,server/ftchat,scripts,data,public}
          mkdir -p /var/log/ftchat
          # 数据目录权限
          chmod 700 /opt/guanghu/ftchat/data
          echo "✓ 目录就绪"
          ENDSSH

      - name: '📤 上传后端代码 (src/ + server/ftchat/)'
        run: |
          # 排除 node_modules / data / public 等
          tar --exclude='node_modules' --exclude='.git' --exclude='data' \
              -czf /tmp/ftchat-backend.tar.gz \
              src/ server/ftchat/services server/ftchat/middleware \
              server/ftchat/ecosystem.config.js \
              package.json package-lock.json \
              scripts/hli-contract-check.js
          scp -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            /tmp/ftchat-backend.tar.gz \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/opt/guanghu/ftchat/_payload.tar.gz
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} \
            'cd /opt/guanghu/ftchat && tar -xzf _payload.tar.gz && rm -f _payload.tar.gz && echo "✓ 后端代码已解压"'

      - name: '🏷️ 注入前端构建版本号 (cache-busting)'
        run: |
          BUILD_ID="${GITHUB_SHA::7}-$(date -u +%Y%m%d%H%M)"
          echo "BUILD_ID=${BUILD_ID}"
          # 替换 index.html 中的 __BUILD_ID__ 占位 → 触发用户端 CSS/JS 强制刷新
          sed -i "s/__BUILD_ID__/${BUILD_ID}/g" frontend/ftchat/index.html
          grep -E 'style\.css|chat\.js|theme-toggle\.js' frontend/ftchat/index.html || true

      - name: '📤 上传前端静态文件'
        run: |
          scp -r -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            frontend/ftchat/* \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/opt/guanghu/ftchat/public/
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} \
            'echo "✓ 前端 $(ls /opt/guanghu/ftchat/public/ | wc -l) 个文件"'

      - name: '⚙️ 生成服务器 .env (在 runner 上拼接, 避免 heredoc 暴露 secrets)'
        env:
          NOTION_TOKEN: ${{ secrets.FT_NOTION_API_TOKEN }}
          NOTION_PAGE: ${{ secrets.FT_NOTION_PROMPT_PAGE_ID }}
          DASHSCOPE_KEY: ${{ secrets.FT_DASHSCOPE_API_KEY }}
          # 微调模型 ID 必须填 DashScope 控制台真实 ID (例: ft:qwen-...:xxxxx).
          # 没配则保持空, ft-dashscope.js 默认值会被命中后由 model_not_found 自动降级到 FT_MODEL_FALLBACK (qwen-turbo).
          MODEL_SYSTEM: ${{ secrets.FT_MODEL_SYSTEM }}
          MODEL_NAIPPING: ${{ secrets.FT_MODEL_NAIPPING }}
          MODEL_FALLBACK: ${{ secrets.FT_MODEL_FALLBACK }}
          SMTP_USER: ${{ secrets.ZY_SMTP_USER }}
          SMTP_PASS: ${{ secrets.ZY_SMTP_PASS }}
        run: |
          cat > /tmp/ftchat.env << EOF
          NODE_ENV=production
          PORT=3010
          FTCHAT_DATA_DIR=/opt/guanghu/ftchat/data
          FT_NOTION_API_TOKEN=${NOTION_TOKEN}
          FT_NOTION_PROMPT_PAGE_ID=${NOTION_PAGE}
          FT_DASHSCOPE_API_KEY=${DASHSCOPE_KEY}
          FT_MODEL_SYSTEM=${MODEL_SYSTEM:-qwen3-8b-ft-202604281809-9f30}
          FT_MODEL_NAIPPING=${MODEL_NAIPPING:-qwen3-8b-ft-202604281809-9f30}
          FT_MODEL_FALLBACK=${MODEL_FALLBACK:-qwen-turbo}
          ZY_SMTP_USER=${SMTP_USER}
          ZY_SMTP_PASS=${SMTP_PASS}
          EOF
          scp -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            /tmp/ftchat.env \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/opt/guanghu/ftchat/.env
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} \
            'chmod 600 /opt/guanghu/ftchat/.env'
          rm -f /tmp/ftchat.env

      - name: '📦 安装依赖'
        run: |
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          cd /opt/guanghu/ftchat
          # Node 与 PM2 假定已在服务器上 (与 novel-api 复用)
          npm ci --production --silent || npm install --production --silent
          # 契约自检 (确保上传的 schema 与代码一致)
          if [ -f scripts/hli-contract-check.js ]; then
            node scripts/hli-contract-check.js || echo "⚠ 契约自检发现问题, 继续部署"
          fi
          echo "✓ 依赖安装完成"
          ENDSSH

      - name: '🚀 启动/重启 PM2'
        run: |
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          cd /opt/guanghu/ftchat
          # 加载 .env 到当前 shell, PM2 reload --update-env 会继承
          set -a
          # shellcheck disable=SC1091
          . ./.env
          set +a
          pm2 describe ftchat-api > /dev/null 2>&1 \
            && pm2 reload server/ftchat/ecosystem.config.js --update-env \
            || pm2 start server/ftchat/ecosystem.config.js
          pm2 save
          pm2 startup systemd -u root --hp /root 2>/dev/null || true
          systemctl enable pm2-root 2>/dev/null || true
          echo "=== PM2 状态 ==="
          pm2 list
          ENDSSH

      - name: '🌐 部署 Nginx 配置'
        run: |
          scp -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            server/nginx/ftchat-guanghu-online.conf \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }}:/etc/nginx/sites-available/ftchat-guanghu-online.conf
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          # 备份并禁用旧的 zhiku 站点 (域名复用)
          if [ -L /etc/nginx/sites-enabled/zhiku ] || [ -L /etc/nginx/sites-enabled/zhiku-guanghu-online.conf ]; then
            rm -f /etc/nginx/sites-enabled/zhiku /etc/nginx/sites-enabled/zhiku-guanghu-online.conf
            echo "✓ 已禁用旧 zhiku 站点"
          fi
          ln -sf /etc/nginx/sites-available/ftchat-guanghu-online.conf \
                 /etc/nginx/sites-enabled/ftchat-guanghu-online.conf
          nginx -t
          systemctl reload nginx
          echo "✓ Nginx 已重载"
          ENDSSH

      - name: '✅ 健康检查'
        run: |
          sleep 3
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set -e
          echo "── /health (本地直连 3010) ──"
          curl -fsS http://127.0.0.1:3010/health || (echo '后端未就绪' && exit 1)
          echo
          echo "── /hli/ftchat/status (本地) ──"
          curl -fsS http://127.0.0.1:3010/hli/ftchat/status
          echo
          echo "── /hli/ftchat/status (公网 HTTPS) ──"
          curl -fsS https://guanghu.online/hli/ftchat/status || echo '⚠ 公网检查失败 (可能 DNS/SSL 还没就绪)'
          echo
          echo "✓ 健康检查通过"
          ENDSSH

  retire-zhiku:
    name: '🗄️ 下架旧 zhiku 站点'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'retire-zhiku'
    steps:
      - name: '📥 检出代码'
        uses: actions/checkout@v4
      - name: '🔑 配置 SSH'
        run: |
          mkdir -p ~/.ssh
          echo "${{ secrets.ZY_NOVEL_KEY }}" > ~/.ssh/ftchat_key
          chmod 600 ~/.ssh/ftchat_key
          ssh-keyscan -H ${{ secrets.ZY_NOVEL_HOST }} >> ~/.ssh/known_hosts
      - name: '🛑 停止 zhiku-api + 禁用 nginx 站点'
        run: |
          ssh -i ~/.ssh/ftchat_key -o StrictHostKeyChecking=no \
            ${{ secrets.ZY_NOVEL_USER }}@${{ secrets.ZY_NOVEL_HOST }} << 'ENDSSH'
          set +e
          pm2 describe zhiku-api > /dev/null 2>&1 && {
            pm2 stop zhiku-api
            pm2 delete zhiku-api
            pm2 save
            echo "✓ zhiku-api PM2 进程已停止"
          } || echo "ℹ zhiku-api 不在 PM2 中"
          # 禁用 nginx
          rm -f /etc/nginx/sites-enabled/zhiku /etc/nginx/sites-enabled/zhiku-guanghu-online.conf
          nginx -t && systemctl reload nginx && echo "✓ Nginx 已重载"
          ENDSSH

  health:
    name: '🩺 健康检查'
    runs-on: ubuntu-latest
    permissions:
      contents: read
    if: github.event_name == 'workflow_dispatch' && github.event.inputs.action == 'health'
    steps:
      - run: |
          curl -fsS https://guanghu.online/health
          echo
          curl -fsS https://guanghu.online/hli/ftchat/status
