name: PR checks

on:
  pull_request:
    types: [opened, edited, synchronize, reopened, labeled, unlabeled]
    branches: [main]

permissions:
  pull-requests: read

jobs:
  pr-checks:
    name: PR checks
    runs-on: ubuntu-latest
    steps:
      - name: Validate PR title format
        uses: actions/github-script@v8
        with:
          script: |
            const title = context.payload.pull_request.title;

            if (title.length > 72) {
              core.setFailed(
                `PR title is ${title.length} characters (max 72).\n` +
                `Title: "${title}"`
              );
              return;
            }

            // Format: <component>: <verb> <description>
            const pattern = /^[a-z][a-z0-9_-]*: [a-z]+ .+$/;
            if (!pattern.test(title)) {
              core.setFailed(
                `PR title does not match the required format.\n\n` +
                `Expected: <component>: <verb> <description>\n` +
                `  - component: lowercase, may contain digits, hyphens, underscores\n` +
                `  - verb: lowercase imperative (add, fix, update, remove, ...)\n` +
                `  - description: free text\n\n` +
                `Examples:\n` +
                `  arksim: add retry logic to evaluator\n` +
                `  simulator: fix config loading for empty fields\n` +
                `  ci: update python version in workflow\n\n` +
                `Got: "${title}"`
              );
            }

      - name: Validate PR description has content
        uses: actions/github-script@v8
        with:
          script: |
            const body = context.payload.pull_request.body || '';

            // Strip HTML comments
            let cleaned = body.replace(/<!--[\s\S]*?-->/g, '');

            // Strip markdown headers (lines starting with #)
            cleaned = cleaned.replace(/^#+\s.*$/gm, '');

            // Strip empty checklist items (unchecked boxes with no real text)
            cleaned = cleaned.replace(/^- \[ \]\s*$/gm, '');

            // Strip template checklist items that are just tool commands
            cleaned = cleaned.replace(/^- \[ \] `[^`]+`\s*(passes)?\s*$/gm, '');

            // Strip blank "Closes #" lines
            cleaned = cleaned.replace(/^Closes\s+#\s*$/gm, '');

            // Strip lone list dashes (empty bullet points)
            cleaned = cleaned.replace(/^-\s*$/gm, '');

            // Collapse whitespace
            cleaned = cleaned.replace(/\s+/g, ' ').trim();

            if (cleaned.length < 20) {
              core.setFailed(
                `PR description is too short (${cleaned.length} characters of real content, minimum 20).\n\n` +
                `Please fill out the PR template with a meaningful summary and description.\n` +
                `Template headers, comments, and empty checkboxes do not count.`
              );
            }

      - name: Check CHANGELOG.md was updated
        uses: actions/github-script@v8
        with:
          script: |
            const labels = context.payload.pull_request.labels.map(l => l.name);
            if (labels.includes('skip-changelog')) {
              core.info('skip-changelog label found, skipping check.');
              return;
            }

            const { data: files } = await github.rest.pulls.listFiles({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number,
              per_page: 100,
            });

            const changelogUpdated = files.some(f => f.filename === 'CHANGELOG.md');
            if (!changelogUpdated) {
              core.setFailed(
                `CHANGELOG.md was not updated in this PR.\n\n` +
                `Please add an entry under the [Unreleased] section describing your change.\n` +
                `Use the appropriate heading: Added, Changed, Fixed, Removed, etc.\n\n` +
                `If this change does not need a changelog entry (e.g. internal refactor,\n` +
                `CI-only change), add the "skip-changelog" label to this PR.`
              );
            }
