name: CI

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
  schedule:
    - cron: "0 2 * * *"  # 每天凌晨 2 点触发定时备份


jobs:
  build-deploy:
    runs-on: CDCD
    # 合并 Job：统一使用带 Docker 的 Node 镜像
    container: dockerreg.eazygame.cn/node-with-docker:22
    env:
      SKIP_ENV_VALIDATION: "1"
      NEXT_TELEMETRY_DISABLED: "1"
    steps:

      - name: Checkout
        uses: actions/checkout@v3

      # 1. 增加 Cache 策略，显著加快 npm ci 速度
      - name: Cache npm dependencies
        uses: actions/cache@v3
        id: npm-cache
        with:
          path: ~/.npm
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.os }}-node-

      # 【保留增强】配置代理，确保 npm install 能通
      - name: Configure npm proxy
        run: |
          GATEWAY_IP=$(ip route show | grep default | awk '{print $3}')
          echo "Detected Docker Gateway: $GATEWAY_IP"
          
          if [ -z "$GATEWAY_IP" ]; then
            echo "Warning: Could not detect gateway IP, falling back to 172.17.0.1"
            GATEWAY_IP="172.17.0.1"
          fi

          PROXY_URL="http://$GATEWAY_IP:7890"
          echo "Using Proxy: $PROXY_URL"
          
          # 设置 npm 代理
          npm config set proxy "$PROXY_URL"
          npm config set https-proxy "$PROXY_URL"
          
          # 设置环境变量供后续步骤使用
          echo "http_proxy=$PROXY_URL" >> $GITHUB_ENV
          echo "https_proxy=$PROXY_URL" >> $GITHUB_ENV
          echo "HTTP_PROXY=$PROXY_URL" >> $GITHUB_ENV
          echo "HTTPS_PROXY=$PROXY_URL" >> $GITHUB_ENV

      - name: Install dependencies
        run: npm ci

      - name: Lint
        run: npm run lint

      - name: Typecheck
        run: npm run typecheck

      - name: Install Playwright Chromium
        run: npx playwright install chromium

      - name: Integration tests
        run: npm run test:integration

      - name: E2E full regression tests
        run: npm run test:e2e

      # 2. 增加 Next.js 构建缓存
      - name: Cache Next.js build
        uses: actions/cache@v3
        with:
          path: |
            ~/.npm
            ${{ github.workspace }}/.next/cache
          # Generate a new cache whenever packages or source files change.
          key: ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
          restore-keys: |
            ${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-

      - name: Build
        run: npm run build

      - name: Prepare standalone build
        run: |
          mkdir -p .next/standalone/public
          mkdir -p .next/standalone/.next/static

          cp -r public/* .next/standalone/public/
          cp -r .next/static/* .next/standalone/.next/static/
          cp Dockerfile .next/standalone/Dockerfile

      # 【核心变更】合并 Deploy 步骤，直接构建镜像，无需 artifact
      - name: Deploy to Docker
        run: |
          # 1. 进入 standalone 目录
          cd .next/standalone
          
          # 2. 构建镜像 (使用 standalone 目录下的 Dockerfile)
          echo "Building Docker image from standalone..."
          docker build --no-cache --pull -t nextjs-app .

          # 3. 优雅停止
          docker stop nextjs-app || true
          docker rm nextjs-app || true

          # 4. 运行容器
          # 使用你后来补充的完整配置 (包含 network 和 NEXTAUTH)
          docker run -d \
            --init \
            -p 8015:3000 \
            --restart unless-stopped \
            --name nextjs-app \
            --network 1panel-network \
            -e NODE_ENV=production \
            -e DATABASE_URL=${{ secrets.DATABASE_URL }} \
            -e NEXTAUTH_SECRET=${{ secrets.NEXTAUTH_SECRET }} \
            -e NEXTAUTH_URL=${{ secrets.NEXTAUTH_URL }} \
            -e NEXT_TELEMETRY_DISABLED=1 \
            nextjs-app
          
          echo "Deploy complete!"

  security-scan:
    runs-on: ubuntu-latest
    needs: build-deploy
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci

      # 1. npm audit(保留)
      - name: npm audit
        run: |
          npm audit --audit-level=moderate || true
          npm audit --json > audit-report.json || true
        continue-on-error: true

      # 2. Snyk 扫描(深度依赖分析)
      - name: Run Snyk to check for vulnerabilities
        uses: snyk/actions/node@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: --severity-threshold=high --sarif-file-output=snyk.sarif
        continue-on-error: true

      # 3. Trivy 文件系统扫描(扫描项目代码和依赖)
      - name: Trivy FS Scan
        run: |
          trivy fs --format json --output trivy-fs-report.json --exit-code 0 .
          trivy fs --format table --exit-code 0 .
        continue-on-error: true

      # 4. OWASP ZAP 基线扫描(扫描部署后的应用)
      - name: OWASP ZAP Baseline Scan
        uses: zaproxy/action-baseline@v0.10.0
        with:
          target: ${{ secrets.NEXTAUTH_URL || 'http://localhost:8015' }}
          cmd_options: '-a -j'
        continue-on-error: true

      # 5. 上传所有报告(失败不阻塞,但生成报告)
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: security-reports
          path: |
            audit-report.json
            trivy-fs-report.json
            snyk.sarif

  scheduled-backup:
    if: github.event_name == 'schedule'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run database backup
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          BACKUP_DIR: ./backups
        run: |
          chmod +x scripts/backup-db.sh
          ./scripts/backup-db.sh
      - name: Verify backup integrity
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          BACKUP_DIR: ./backups
        run: |
          chmod +x scripts/backup-verify.sh
          ./scripts/backup-verify.sh
      - name: Sync backup to offsite storage
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          BACKUP_DIR: ./backups
          BACKUP_OFFSITE_BACKEND: ${{ secrets.BACKUP_OFFSITE_BACKEND }}
          BACKUP_OFFSITE_REMOTE: ${{ secrets.BACKUP_OFFSITE_REMOTE }}
          BACKUP_OFFSITE_BUCKET: ${{ secrets.BACKUP_OFFSITE_BUCKET }}
          BACKUP_OFFSITE_ACCESS_KEY: ${{ secrets.BACKUP_OFFSITE_ACCESS_KEY }}
          BACKUP_OFFSITE_SECRET_KEY: ${{ secrets.BACKUP_OFFSITE_SECRET_KEY }}
          BACKUP_OFFSITE_REGION: ${{ secrets.BACKUP_OFFSITE_REGION }}
        run: |
          chmod +x scripts/backup-offsite-sync.sh
          ./scripts/backup-offsite-sync.sh || echo "WARN: Offsite sync failed, continuing"
      - uses: actions/upload-artifact@v3
        with:
          name: db-backup
          path: backups/
          retention-days: 30

  backup-verify:
    if: github.event_name == 'schedule'
    needs: scheduled-backup
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/download-artifact@v3
        with:
          name: db-backup
          path: backups/
      - name: Verify backup integrity
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          BACKUP_DIR: ./backups
        run: |
          chmod +x scripts/backup-verify.sh
          ./scripts/backup-verify.sh
      - name: Run health check
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          BACKUP_DIR: ./backups
          HEALTH_CHECK_URL: ${{ secrets.HEALTH_CHECK_URL }}
        run: |
          chmod +x scripts/health-check.sh
          ./scripts/health-check.sh > health-report.json || true
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: backup-verify-report
          path: |
            backups/
            health-report.json
          retention-days: 7

  weekly-dr-drill:
    if: github.event_name == 'schedule' && github.run_attempt % 7 == 0
    needs: backup-verify
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run disaster recovery drill
        env:
          DATABASE_URL: ${{ secrets.DATABASE_URL }}
          BACKUP_DIR: ./backups
          DR_DRILL_TEST_DB: next_edu_dr_drill
        run: |
          chmod +x scripts/dr-drill.sh
          ./scripts/dr-drill.sh || echo "WARN: DR drill failed, see report"
      - uses: actions/upload-artifact@v3
        if: always()
        with:
          name: dr-drill-report
          path: docs/dr/reports/
          retention-days: 90
