name: Auto-merge Copilot PRs

# Copilot Coding Agent が作成した PR が
# 1) CI 通過（Type Check + Build Check）かつ
# 2) AI レビュー (ai-review.yml) で APPROVE された
# 場合に自動マージする。

on:
  pull_request_review:
    types: [submitted]
  pull_request:
    types: [opened, synchronize, ready_for_review]
  check_run:
    types: [completed]

jobs:
  auto-merge:
    name: Auto-merge if CI + AI Review passed
    runs-on: ubuntu-latest
    if: |
      github.actor == 'Copilot' ||
      github.event.pull_request.user.login == 'Copilot' ||
      github.event.review.user.login == 'github-actions[bot]' ||
      github.event_name == 'check_run'
    permissions:
      pull-requests: write
      contents: write
    steps:
      - name: Check CI status and AI review approval
        uses: actions/github-script@v7
        with:
          script: |
            let prNumber;

            // イベント種別に応じて PR 番号を取得
            if (context.eventName === 'check_run') {
              const runName = context.payload.check_run.name;
              if (runName === 'Auto-merge if CI + AI Review passed') {
                console.log('Skipping self-triggered check_run');
                return;
              }
              const prs = context.payload.check_run.pull_requests;
              if (!prs || prs.length === 0) {
                console.log('check_run: no associated PRs, skipping');
                return;
              }
              prNumber = prs[0].number;
              console.log(`check_run "${runName}" completed: checking PR #${prNumber}`);
            } else {
              prNumber = context.payload.pull_request?.number
                || context.payload.review?.pull_request_url?.match(/\/pulls\/(\d+)$/)?.[1];
            }

            if (!prNumber) {
              console.log('No PR number found, skipping');
              return;
            }

            const pr = await github.rest.pulls.get({
              owner: context.repo.owner,
              repo:  context.repo.repo,
              pull_number: Number(prNumber),
            });

            // すでに closed/merged の PR はスキップ
            if (pr.data.state !== 'open') {
              console.log(`PR #${prNumber} is ${pr.data.state}, skipping`);
              return;
            }

            // Draft PR はスキップ
            if (pr.data.draft) {
              console.log(`PR #${prNumber} is still Draft, skipping`);
              return;
            }

            // Copilot 作成でなければスキップ
            if (pr.data.user.login !== 'Copilot') {
              console.log(`PR #${prNumber} is not from Copilot (${pr.data.user.login}), skipping`);
              return;
            }

            // ── CI チェックの状態を確認 ──────────────────────────────
            const checks = await github.rest.checks.listForRef({
              owner: context.repo.owner,
              repo:  context.repo.repo,
              ref:   pr.data.head.sha,
              per_page: 100,
            });

            // 同名の check_run が複数ある場合（re-run）は最新のものだけを使う
            const latestByName = {};
            for (const c of checks.data.check_runs) {
              if (c.name === 'Type Check' || c.name === 'Build Check') {
                const prev = latestByName[c.name];
                if (!prev || new Date(c.started_at) > new Date(prev.started_at)) {
                  latestByName[c.name] = c;
                }
              }
            }
            const ciChecks = Object.values(latestByName);

            const ciPassed = ciChecks.length >= 2 &&
              ciChecks.every(c => c.status === 'completed' && c.conclusion === 'success');

            const ciStatus = ciChecks.map(c => `${c.name}:${c.conclusion ?? c.status}`).join(', ');
            console.log(`PR #${prNumber} CI (latest runs): ${ciStatus || 'no checks found'}`);

            if (!ciPassed) {
              console.log(`PR #${prNumber}: CI not fully passed yet, skipping`);
              return;
            }

            // ── AI レビューの APPROVE を確認 ─────────────────────────
            const reviews = await github.rest.pulls.listReviews({
              owner:       context.repo.owner,
              repo:        context.repo.repo,
              pull_number: Number(prNumber),
              per_page: 100,
            });

            const latestByReviewer = {};
            for (const r of reviews.data) {
              if (r.state !== 'COMMENTED') {
                latestByReviewer[r.user.login] = r.state;
              }
            }

            const hasApproval = Object.values(latestByReviewer).includes('APPROVED');
            const hasChangesRequested = Object.values(latestByReviewer).includes('CHANGES_REQUESTED');

            console.log(`PR #${prNumber} reviews: ${JSON.stringify(latestByReviewer)}`);

            if (hasChangesRequested) {
              console.log(`PR #${prNumber}: AI review requested changes, skipping merge`);
              return;
            }

            if (!hasApproval) {
              console.log(`PR #${prNumber}: No APPROVE review yet, waiting for AI review`);
              return;
            }

            console.log(`PR #${prNumber}: CI passed + AI review approved. Proceeding to merge.`);

            // ── マージ実行（squash） ──────────────────────────────────
            try {
              await github.rest.pulls.merge({
                owner:        context.repo.owner,
                repo:         context.repo.repo,
                pull_number:  Number(prNumber),
                merge_method: 'squash',
              });
              console.log(`✅ Merged PR #${prNumber}`);
            } catch (err) {
              if (err.status === 405) {
                // Branch protection: GitHub native auto-merge を有効化
                try {
                  await github.graphql(`
                    mutation EnableAutoMerge($prId: ID!) {
                      enablePullRequestAutoMerge(input: {
                        pullRequestId: $prId
                        mergeMethod: SQUASH
                      }) {
                        pullRequest { number state }
                      }
                    }
                  `, { prId: pr.data.node_id });
                  console.log(`Enabled GitHub auto-merge for PR #${prNumber}`);
                } catch (graphqlErr) {
                  console.log(`Auto-merge enable failed: ${graphqlErr.message}`);
                }
              } else if (err.status === 404 || err.status === 422) {
                console.log(`PR #${prNumber} not mergeable (${err.status}): ${err.message}`);
              } else {
                throw err;
              }
            }
