name: PR Triage (Models)

on:
  pull_request_target:
    types: [opened]

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

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

jobs:
  triage:
    if: ${{ github.repository == 'meshtastic/firmware' && github.event.pull_request.user.type != 'Bot' }}
    runs-on: ubuntu-latest
    steps:
      # ─────────────────────────────────────────────────────────────────────────
      # Step 1: Check if PR already has automation/type labels (skip if so)
      # ─────────────────────────────────────────────────────────────────────────
      - name: Check existing labels
        uses: actions/github-script@v9
        id: check-labels
        with:
          script: |
            const skipLabels = new Set(['automation']);
            const typeLabels = new Set(['bugfix', 'hardware-support', 'enhancement', 'dependencies', 'submodules', 'github_actions', 'trunk', 'cleanup']);
            const prLabels = context.payload.pull_request.labels.map(l => l.name);

            const shouldSkipAll = prLabels.some(l => skipLabels.has(l));
            const hasTypeLabel = prLabels.some(l => typeLabels.has(l));

            core.setOutput('skip_all', shouldSkipAll ? 'true' : 'false');
            core.setOutput('has_type_label', hasTypeLabel ? 'true' : 'false');

      # ─────────────────────────────────────────────────────────────────────────
      # Step 2: Quality check (spam/AI-slop detection)
      # ─────────────────────────────────────────────────────────────────────────
      - name: Detect spam or low-quality content
        if: steps.check-labels.outputs.skip_all != 'true'
        uses: actions/ai-inference@v2
        id: quality
        continue-on-error: true
        with:
          max-tokens: 20
          prompt: |
            Is this GitHub pull request spam, AI-generated slop, or low quality?

            Title: ${{ github.event.pull_request.title }}
            Body: ${{ github.event.pull_request.body }}

            Respond with exactly one of: spam, ai-generated, needs-review, ok
          system-prompt: You detect spam and low-quality contributions. Be conservative - only flag obvious spam or AI slop.
          model: openai/gpt-4o-mini

      - name: Apply quality label if needed
        if: steps.check-labels.outputs.skip_all != 'true' && steps.quality.outputs.response != '' && steps.quality.outputs.response != 'ok'
        uses: actions/github-script@v9
        id: quality-label
        env:
          QUALITY_LABEL: ${{ steps.quality.outputs.response }}
        with:
          script: |
            const label = (process.env.QUALITY_LABEL || '').trim().toLowerCase();
            const labelMeta = {
              'spam': { color: 'd73a4a', description: 'Possible spam' },
              'ai-generated': { color: 'fbca04', description: 'Possible AI-generated low-quality content' },
              'needs-review': { color: 'f9d0c4', description: 'Needs human review' },
            };
            const meta = labelMeta[label];
            if (!meta) return;

            // Ensure label exists
            try {
              await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
            } catch (e) {
              if (e.status !== 404) throw e;
              await github.rest.issues.createLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label, color: meta.color, description: meta.description });
            }

            // Apply label
            await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, labels: [label] });

            core.setOutput('is_spam', 'true');

      # ─────────────────────────────────────────────────────────────────────────
      # Step 3: Auto-label PR type (bugfix/hardware-support/enhancement)
      # Only skip for spam/ai-generated; still classify needs-review PRs
      # ─────────────────────────────────────────────────────────────────────────
      - name: Classify PR for labeling
        if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.quality.outputs.response != 'spam' && steps.quality.outputs.response != 'ai-generated'
        uses: actions/ai-inference@v2
        id: classify
        continue-on-error: true
        with:
          max-tokens: 30
          prompt: |
            Classify this pull request into exactly one category.

            Return exactly one of: bugfix, hardware-support, enhancement

            Use bugfix if it fixes a bug, crash, or incorrect behavior.
            Use hardware-support if it adds or improves support for a specific hardware device/variant.
            Use enhancement if it adds a new feature, improves performance, or refactors code.

            Title: ${{ github.event.pull_request.title }}
            Body: ${{ github.event.pull_request.body }}
          system-prompt: You classify pull requests into categories. Be conservative and pick the most appropriate single label.
          model: openai/gpt-4o-mini

      - name: Apply type label
        if: steps.check-labels.outputs.skip_all != 'true' && steps.check-labels.outputs.has_type_label != 'true' && steps.classify.outputs.response != ''
        uses: actions/github-script@v9
        env:
          TYPE_LABEL: ${{ steps.classify.outputs.response }}
        with:
          script: |
            const label = (process.env.TYPE_LABEL || '').trim().toLowerCase();
            const labelMeta = {
              'bugfix': { color: 'd73a4a', description: 'Bug fix' },
              'hardware-support': { color: '0e8a16', description: 'Hardware support addition or improvement' },
              'enhancement': { color: 'a2eeef', description: 'New feature or enhancement' },
            };
            const meta = labelMeta[label];
            if (!meta) return;

            // Ensure label exists
            try {
              await github.rest.issues.getLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label });
            } catch (e) {
              if (e.status !== 404) throw e;
              await github.rest.issues.createLabel({ owner: context.repo.owner, repo: context.repo.repo, name: label, color: meta.color, description: meta.description });
            }

            // Apply label
            await github.rest.issues.addLabels({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.payload.pull_request.number, labels: [label] });
