---
name: Auto-Close Issues on PR Merge

'on':
  pull_request:
    types: [closed]

permissions:
  issues: write
  pull-requests: read
  contents: read

jobs:
  close-linked-issues:
    name: Close Issues Linked in PR
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Check Workflow Kill Switch
        run: |
          if [ -f ".github/WORKFLOW_KILLSWITCH" ]; then
            STATUS=$(grep "STATUS:" .github/WORKFLOW_KILLSWITCH | awk '{print $2}')
            if [ "$STATUS" = "DISABLED" ]; then
              echo "🛑 Workflows disabled by kill switch"
              exit 0
            fi
          fi

      - name: Extract linked issues from PR body
        id: extract_issues
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const prBody = context.payload.pull_request.body || '';
            const prNumber = context.payload.pull_request.number;

            // Patterns to detect linked issues
            // Supports: Fixes #123, Closes #456, Resolves #789, Related to #111, See #222
            const patterns = [
              /(?:fix|fixes|fixed|close|closes|closed|resolve|resolves|resolved)\s+#(\d+)/gi,
              /(?:related\s+to|see|ref|references)\s+#(\d+)/gi
            ];

            const issueNumbers = new Set();

            // Extract issue numbers
            patterns.forEach(pattern => {
              let match;
              while ((match = pattern.exec(prBody)) !== null) {
                issueNumbers.add(match[1]);
              }
            });

            // Also check PR title
            const prTitle = context.payload.pull_request.title || '';
            patterns.forEach(pattern => {
              let match;
              while ((match = pattern.exec(prTitle)) !== null) {
                issueNumbers.add(match[1]);
              }
            });

            // Also check commit messages in PR
            const commits = await github.rest.pulls.listCommits({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: prNumber
            });

            commits.data.forEach(commit => {
              const message = commit.commit.message;
              patterns.forEach(pattern => {
                let match;
                while ((match = pattern.exec(message)) !== null) {
                  issueNumbers.add(match[1]);
                }
              });
            });

            const issues = Array.from(issueNumbers);
            console.log(`Found linked issues: ${issues.join(', ')}`);

            return issues;

      - name: Close linked issues
        if: steps.extract_issues.outputs.result != '[]'
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueNumbers = ${{ steps.extract_issues.outputs.result }};
            const prNumber = context.payload.pull_request.number;
            const prTitle = context.payload.pull_request.title;
            const prUrl = context.payload.pull_request.html_url;
            const merger = context.payload.pull_request.merged_by.login;

            console.log(`Processing ${issueNumbers.length} linked issue(s)`);

            for (const issueNumber of issueNumbers) {
              try {
                // Get issue details first
                const issue = await github.rest.issues.get({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: parseInt(issueNumber)
                });

                // Skip if already closed
                if (issue.data.state === 'closed') {
                  console.log(`Issue #${issueNumber} already closed, skipping`);
                  continue;
                }

                // Add comment explaining closure
                await github.rest.issues.createComment({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: parseInt(issueNumber),
                  body: `Completed via PR #${prNumber}\n\nPR: ${prTitle}\nURL: ${prUrl}\nMerged by: ${merger}\n\nThis issue has been resolved and the changes have been merged into main.\n\nAutomatically closed via PR merge automation`
                });

                // Close the issue
                await github.rest.issues.update({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: parseInt(issueNumber),
                  state: 'closed',
                  state_reason: 'completed'
                });

                console.log(`✅ Closed issue #${issueNumber}`);

              } catch (error) {
                console.error(`❌ Failed to close issue #${issueNumber}: ${error.message}`);
              }
            }

      - name: Update project board status
        if: steps.extract_issues.outputs.result != '[]'
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueNumbers = ${{ steps.extract_issues.outputs.result }};

            for (const issueNumber of issueNumbers) {
              try {
                // Add status: done label
                await github.rest.issues.addLabels({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: parseInt(issueNumber),
                  labels: ['status: done']
                });

                // Remove in-progress and in-review labels
                const labelsToRemove = ['status: in-progress', 'status: in-review'];
                for (const label of labelsToRemove) {
                  try {
                    await github.rest.issues.removeLabel({
                      owner: context.repo.owner,
                      repo: context.repo.repo,
                      issue_number: parseInt(issueNumber),
                      name: label
                    });
                  } catch (e) {
                    // Label might not exist, ignore error
                  }
                }

                console.log(`✅ Updated project status for issue #${issueNumber}`);

              } catch (error) {
                console.error(`❌ Failed to update status for issue #${issueNumber}: ${error.message}`);
              }
            }

      - name: Summary
        if: steps.extract_issues.outputs.result != '[]'
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const issueNumbers = ${{ steps.extract_issues.outputs.result }};
            const prNumber = context.payload.pull_request.number;

            console.log(`
            ✅ PR #${prNumber} Merge Automation Complete

            Closed issues: ${issueNumbers.join(', ')}
            Updated project board: status → done
            Comments added: Linked to PR #${prNumber}

            All linked issues have been automatically closed and marked as done.
            `);
