name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]
  # 允许手动触发
  workflow_dispatch:

# 并行运行同分支的多个 push 时,取消前面那个
concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  docs-check:
    name: Docs & Links
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Run link check
        run: node tools/cross-platform/scripts/check-links.js

      - name: Run markdown lint (nit 警告不阻塞)
        run: node tools/cross-platform/scripts/markdown-lint.js --fail-on=hard

  commit-lint:
    name: Commit Message Lint
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0  # 需要完整历史来对比

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Check commit messages
        run: |
          # 获取本 PR 所有 commit 的标题行
          COMMITS=$(git log --format=%s origin/${{ github.base_ref }}..HEAD)
          if [ -z "$COMMITS" ]; then
            echo "⚠️ 没有发现新 commit"
            exit 0
          fi
          FAIL=0
          echo "$COMMITS" | while IFS= read -r msg; do
            echo "检查: $msg"
            node tools/cross-platform/scripts/check-commit.js "$msg" || FAIL=1
          done
          exit $FAIL

  shell-syntax:
    name: Shell Script Syntax
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Check bash scripts
        run: |
          FAIL=0
          find platforms/linux platforms/macos -name "*.sh" -type f | while read -r f; do
            echo "检查: $f"
            bash -n "$f" || FAIL=1
          done
          # shellcheck 可选,若未装则跳过
          if command -v shellcheck >/dev/null 2>&1; then
            find platforms/linux platforms/macos -name "*.sh" -type f -exec shellcheck -x -e SC1091,SC2086 {} +
          fi
          exit $FAIL

  powershell-syntax:
    name: PowerShell Syntax
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup PowerShell
        shell: bash
        run: |
          # Ubuntu 上装 pwsh（比跑 windows-latest 省 2x 额度）
          sudo apt-get update -qq
          sudo apt-get install -y -qq wget apt-transport-https software-properties-common
          source /etc/os-release
          wget -q "https://packages.microsoft.com/config/ubuntu/$VERSION_ID/packages-microsoft-prod.deb"
          sudo dpkg -i packages-microsoft-prod.deb
          sudo apt-get update -qq
          sudo apt-get install -y -qq powershell

      - name: Parse PowerShell scripts
        shell: pwsh
        run: |
          $ErrorActionPreference = 'Stop'
          $files = Get-ChildItem -Path platforms/windows -Recurse -Include *.ps1
          $failed = 0
          foreach ($f in $files) {
            $errors = $null
            $tokens = $null
            [System.Management.Automation.Language.Parser]::ParseFile(
              $f.FullName, [ref]$tokens, [ref]$errors
            ) | Out-Null
            if ($errors.Count -gt 0) {
              Write-Host "❌ $($f.FullName)"
              $errors | ForEach-Object { Write-Host "   L$($_.Extent.StartLineNumber): $($_.Message)" }
              $failed++
            } else {
              Write-Host "✅ $($f.FullName)"
            }
          }
          if ($failed -gt 0) { exit 1 }

  submission-check:
    name: Submission Format Check
    runs-on: ubuntu-latest
    # 只在有 submission 相关文件变化时跑
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Check changed submission files
        run: |
          # 找本 PR 变化的 "实际提测申请单",排除方法论文章/模板文件/示例
          # - 排除 docs/chapters/ (讲解提测规范的文章,不是申请单本身)
          # - 排除 templates/ (模板)
          # - 排除 examples/ 只 submission-* 前缀命名的(真实示例)仍然校验
          FILES=$(git diff --name-only origin/${{ github.base_ref }}..HEAD \
            | grep -E '(submission|提测).*\.md$' \
            | grep -v -E '^(docs/chapters/|templates/)' \
            || true)
          if [ -z "$FILES" ]; then
            echo "✅ 本 PR 无提测申请单变化,跳过"
            exit 0
          fi
          FAIL=0
          for f in $FILES; do
            if [ -f "$f" ]; then
              echo "检查: $f"
              node tools/cross-platform/scripts/check-submission.js "$f" || FAIL=1
            fi
          done
          exit $FAIL

  prd-check:
    name: PRD Structure & Testability
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Check changed PRD files
        run: |
          FILES=$(git diff --name-only origin/${{ github.base_ref }}..HEAD \
            | grep -E '(prd|PRD).*\.md$' || true)
          if [ -z "$FILES" ]; then
            echo "✅ 本 PR 无 PRD 变化,跳过"
            exit 0
          fi
          FAIL=0
          for f in $FILES; do
            [ -f "$f" ] || continue
            echo "=== 结构校验: $f ==="
            node tools/cross-platform/scripts/check-prd.js "$f" || {
              code=$?
              # 只有硬错误（退出码 2）阻塞
              if [ "$code" = "2" ]; then FAIL=1; fi
            }
            echo "=== 可测性评分: $f ==="
            node tools/cross-platform/scripts/score-testability.js "$f" || {
              code=$?
              # < 60 分硬阻塞
              if [ "$code" = "2" ]; then FAIL=1; fi
            }
          done
          exit $FAIL

  adr-index-sync:
    name: ADR Index Up-to-date
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Detect ADR directories
        id: scan
        run: |
          # 任何 docs/adr 或 **/adr/ 目录下 0001-xxx.md 变动
          DIRS=$(git diff --name-only origin/${{ github.base_ref }}..HEAD \
            | grep -E '(^|/)adr/[0-9]{4}-.+\.md$' \
            | sed -E 's#/[^/]+$##' | sort -u || true)
          echo "dirs<<EOF" >> $GITHUB_OUTPUT
          echo "$DIRS" >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Verify ADR index is latest
        if: steps.scan.outputs.dirs != ''
        run: |
          FAIL=0
          while IFS= read -r dir; do
            [ -z "$dir" ] && continue
            echo "→ 校验索引: $dir"
            node tools/cross-platform/scripts/generate-adr-index.js \
              --target "$dir" --check || FAIL=1
          done <<< "${{ steps.scan.outputs.dirs }}"
          exit $FAIL

  coverage-check:
    name: Requirement Coverage
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Run coverage-analysis on examples
        run: |
          # 对 examples/leave-management-system 做需求覆盖快照（参考值）
          # 不阻塞：仅打印,PR 改了相关目录时才报硬错
          CHANGED=$(git diff --name-only origin/${{ github.base_ref }}..HEAD \
            | grep -E '(01-business|03-testing)/' || true)
          if [ -z "$CHANGED" ]; then
            echo "✅ 本 PR 未动业务/测试目录,跳过"
            exit 0
          fi
          node tools/cross-platform/scripts/coverage-analysis.js \
            --req examples/leave-management-system/01-business/prd-v1.0.md \
            --cases examples/leave-management-system/03-testing/ \
            --output /tmp/COVERAGE.md || echo "⚠️  有未覆盖需求（软警告,不阻塞）"
          echo "::group::COVERAGE.md"
          cat /tmp/COVERAGE.md
          echo "::endgroup::"

  config-audit:
    name: Config Audit (opt-in)
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Detect changed config dirs and audit
        run: |
          # 找同目录下多份 *.env / *.yml / *.json 的改动
          CHANGED=$(git diff --name-only origin/${{ github.base_ref }}..HEAD \
            | grep -E '\.(env|ya?ml|json)$' | grep -E '(config|configs|env)/' | head -10 || true)
          if [ -z "$CHANGED" ]; then
            echo "✅ 本 PR 未触发配置审计"
            exit 0
          fi
          # 按目录分组
          DIRS=$(echo "$CHANGED" | xargs -I{} dirname {} | sort -u)
          FAIL=0
          for d in $DIRS; do
            echo "=== 审计 $d ==="
            node tools/cross-platform/scripts/config-audit.js --dir "$d" --output /tmp/audit-$(basename $d).md || {
              code=$?
              # 退出码 2 (prod 明文敏感值) 阻塞合入
              if [ "$code" = "2" ]; then FAIL=1; fi
            }
          done
          exit $FAIL

  summary:
    name: CI Summary
    needs: [docs-check, commit-lint, shell-syntax, powershell-syntax, submission-check, prd-check, adr-index-sync, coverage-check, config-audit]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Summary
        run: |
          echo "### CI 汇总" >> $GITHUB_STEP_SUMMARY
          echo "" >> $GITHUB_STEP_SUMMARY
          echo "| 检查项 | 结果 |" >> $GITHUB_STEP_SUMMARY
          echo "|-------|------|" >> $GITHUB_STEP_SUMMARY
          echo "| Docs & Links | ${{ needs.docs-check.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Commit Lint  | ${{ needs.commit-lint.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Shell Syntax | ${{ needs.shell-syntax.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| PS Syntax    | ${{ needs.powershell-syntax.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Submission   | ${{ needs.submission-check.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| PRD Check    | ${{ needs.prd-check.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| ADR Index    | ${{ needs.adr-index-sync.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Req Coverage | ${{ needs.coverage-check.result }} |" >> $GITHUB_STEP_SUMMARY
          echo "| Config Audit | ${{ needs.config-audit.result }} |" >> $GITHUB_STEP_SUMMARY
