name: Cancel Unfinished PR Runs

on:
  workflow_dispatch:
    inputs:
      workflows:
        description: 'Space-separated list of workflow filenames to cancel'
        required: true
        type: string
        default: 'pr-test.yml'
      include_high_priority:
        description: 'Also cancel runs from high-priority PRs'
        required: false
        type: boolean
        default: false

permissions:
  actions: write   # Needed to cancel runs
  contents: read   # Needed to read repo info
  pull-requests: read  # needed for gh pr view (labels)

jobs:
  cancel-unfinished-pr-runs:
    runs-on: ubuntu-latest
    steps:
      - name: Install GitHub CLI
        run: sudo apt-get install -y gh jq

      - name: Cancel unfinished PR-associated runs (skip high-priority PRs)
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          REPO: ${{ github.repository }}
          WORKFLOWS: ${{ github.event.inputs.workflows || 'pr-test.yml' }}
          INCLUDE_HIGH_PRIORITY: ${{ github.event.inputs.include_high_priority || 'false' }}
        shell: bash
        run: |
          set -euo pipefail

          # Read the space-separated string from the input into a bash array
          read -r -a WORKFLOW_FILES <<< "${WORKFLOWS}"

          echo "Targeting ${#WORKFLOW_FILES[@]} workflow(s): ${WORKFLOWS}"
          echo ""

          for workflow_file in "${WORKFLOW_FILES[@]}"; do
            echo "========================================="
            echo "Workflow: $workflow_file"
            echo "========================================="

            # Get all unfinished runs
            all_runs=$(gh run list \
              --repo "$REPO" \
              --workflow "$workflow_file" \
              --json databaseId,status,event,url,createdAt \
              --limit 1000 \
            | jq -c '.[] | select(.status=="queued" or .status=="waiting" or .status=="in_progress")')

            if [ -z "$all_runs" ]; then
              echo "✅ No unfinished runs found"
              echo ""
              continue
            fi

            # Count runs by event type
            total_runs=$(echo "$all_runs" | wc -l)
            pr_runs=$(echo "$all_runs" | jq -s '[.[] | select(.event=="pull_request")] | length')
            other_runs=$(echo "$all_runs" | jq -s '[.[] | select(.event!="pull_request")] | length')

            echo "📊 Summary: $total_runs unfinished runs ($pr_runs PR-related, $other_runs other)"
            echo ""

            # Process non-PR runs first
            if [ "$other_runs" -gt 0 ]; then
              echo "--- Non-PR Runs ---"
              echo "$all_runs" | jq -c 'select(.event!="pull_request")' | while read -r run; do
                run_url=$(echo "$run" | jq -r '.url')
                run_event=$(echo "$run" | jq -r '.event')
                run_status=$(echo "$run" | jq -r '.status')
                echo "  • $run_event ($run_status): $run_url"
              done
              echo ""
            fi

            # Process PR runs
            if [ "$pr_runs" -gt 0 ]; then
              echo "--- PR Runs (checking for cancellation) ---"
              echo "$all_runs" | jq -c 'select(.event=="pull_request")' | while read -r run; do
                run_id=$(echo "$run" | jq -r '.databaseId')
                run_url=$(echo "$run" | jq -r '.url')
                run_status=$(echo "$run" | jq -r '.status')

                echo ""
                echo "Run ($run_status): $run_url"

                # Fetch full run details to get head repository and branch info
                run_details=$(gh api -H "Accept: application/vnd.github+json" \
                  "repos/$REPO/actions/runs/$run_id" 2>/dev/null || true)

                if [ -z "$run_details" ]; then
                  echo "  ⚠️  Could not fetch run details, skipping"
                  continue
                fi

                # Get head owner and branch (works for both fork and non-fork PRs)
                head_owner=$(echo "$run_details" | jq -r '.head_repository.owner.login // empty')
                head_branch=$(echo "$run_details" | jq -r '.head_branch // empty')

                if [ -z "$head_owner" ] || [ -z "$head_branch" ]; then
                  echo "  ⚠️  Missing head info, skipping"
                  continue
                fi

                echo "  Branch: ${head_owner}:${head_branch}"

                # Find PR by searching with head=owner:branch
                pr_number=$(gh api -H "Accept: application/vnd.github+json" \
                  "repos/$REPO/pulls?state=open&head=${head_owner}:${head_branch}" \
                  --jq '.[0].number // empty' 2>/dev/null || true)

                if [ -z "$pr_number" ]; then
                  echo "  ⚠️  No open PR found, skipping"
                  continue
                fi

                pr_url="https://github.com/$REPO/pull/$pr_number"
                echo "  PR: $pr_url"

                # Check for high priority label
                labels=$(gh pr view "$pr_number" --repo "$REPO" --json labels \
                  | jq -r '.labels[].name' 2>/dev/null || true)

                if echo "$labels" | grep -Fxq "bypass-maintenance"; then
                  echo "  🛑 Skipping (bypass-maintenance label, never cancelled)"
                  continue
                fi

                if echo "$labels" | grep -Fxq "high priority"; then
                  if [ "$INCLUDE_HIGH_PRIORITY" != "true" ]; then
                    echo "  🛑 Skipping (high priority label)"
                    continue
                  fi
                  echo "  ⚠️  High priority PR, but include_high_priority is enabled"
                fi

                echo "  🚫 Cancelling..."
                gh run cancel "$run_id" --repo "$REPO" || echo "  ⚠️  Cancellation failed"
              done
            fi

            echo ""
          done

          echo "========================================="
          echo "✅ Processing complete"
          echo "========================================="
