name: '📏 PR Size Labeler'

on:
  pull_request_target:
    types: ['opened', 'reopened', 'synchronize']

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

concurrency:
  group: '${{ github.workflow }}-${{ github.event.pull_request.number }}'
  cancel-in-progress: true

jobs:
  label-pr:
    timeout-minutes: 5
    runs-on: 'ubuntu-latest'
    steps:
      - name: 'Get PR diff stats'
        id: 'diff_stats'
        uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9.0.0
        with:
          github-token: '${{ secrets.GITHUB_TOKEN }}'
          script: |
            const { data: pr } = await github.rest.pulls.get({
              owner: context.repo.owner,
              repo: context.repo.repo,
              pull_number: context.payload.pull_request.number
            });

            const additions = pr.additions || 0;
            const deletions = pr.deletions || 0;
            const totalChanges = additions + deletions;
            const filesChanged = pr.changed_files || 0;

            core.setOutput('total_changes', totalChanges);
            core.setOutput('files_changed', filesChanged);
            core.setOutput('additions', additions);
            core.setOutput('deletions', deletions);

            core.info(`PR #${pr.number}: +${additions} -${deletions} (${totalChanges} total) in ${filesChanged} files`);

      - name: 'Determine size label'
        id: 'size_label'
        env:
          TOTAL_CHANGES: ${{ steps.diff_stats.outputs.total_changes }}
        run: |
          TOTAL=$TOTAL_CHANGES

          if [ $TOTAL -lt 10 ]; then
            echo "size_label=size/xs" >> $GITHUB_OUTPUT
          elif [ $TOTAL -lt 50 ]; then
            echo "size_label=size/s" >> $GITHUB_OUTPUT
          elif [ $TOTAL -lt 200 ]; then
            echo "size_label=size/m" >> $GITHUB_OUTPUT
          elif [ $TOTAL -lt 1000 ]; then
            echo "size_label=size/l" >> $GITHUB_OUTPUT
          else
            echo "size_label=size/xl" >> $GITHUB_OUTPUT
          fi

      - name: 'Apply size label'
        uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9.0.0
        env:
          SIZE_LABEL: '${{ steps.size_label.outputs.size_label }}'
        with:
          github-token: '${{ secrets.GITHUB_TOKEN }}'
          script: |
            const prNumber = context.payload.pull_request.number;
            const newLabel = process.env.SIZE_LABEL;

            // Get current labels
            const { data: currentLabels } = await github.rest.issues.listLabelsOnIssue({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: prNumber
            });

            // Remove old size labels
            const sizeLabels = ['size/xs', 'size/s', 'size/m', 'size/l', 'size/xl'];
            for (const label of currentLabels) {
              if (sizeLabels.includes(label.name) && label.name !== newLabel) {
                await github.rest.issues.removeLabel({
                  owner: context.repo.owner,
                  repo: context.repo.repo,
                  issue_number: prNumber,
                  name: label.name
                });
                core.info(`Removed old label: ${label.name}`);
              }
            }

            // Add new size label
            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: prNumber,
              labels: [newLabel]
            });
            core.info(`Applied label: ${newLabel}`);

      - name: 'Comment on large PRs'
        if: steps.size_label.outputs.size_label == 'size/xl'
        uses: 'actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3' # v9.0.0
        with:
          github-token: '${{ secrets.GITHUB_TOKEN }}'
          script: |
            const prNumber = context.payload.pull_request.number;

            // Check if we already commented
            const { data: comments } = await github.rest.issues.listComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: prNumber
            });

            const botComment = comments.find(c =>
              c.user && c.user.login && c.user.login.includes('[bot]') &&
              c.body.includes('This pull request is quite large')
            );

            if (!botComment) {
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: prNumber,
                body: `## 📏 Large PR Detected

            This pull request is quite large (1000+ lines changed), which can make reviewing challenging.

            **Suggestions:**
            - Consider breaking this into smaller, focused PRs
            - Separate refactoring from new features
            - Split bug fixes from feature additions

            This helps reviewers provide better feedback and speeds up the merge process. Thank you! 🙏`
              });
            }
