name: Issue Labeler

on:
  issues:
    types: [opened, edited]

permissions:
  issues: write

jobs:
  label-bug-reports:
    runs-on: ubuntu-latest
    steps:
      - name: Add "bug" label to unlabeled bug reports
        uses: actions/github-script@v7
        with:
          script: |
            const issue = context.payload.issue;

            // Web-form submissions already carry the label from the issue template
            if (issue.labels.some((label) => label.name === 'bug')) {
              return;
            }

            const isEdit = context.payload.action === 'edited';
            const titleWasEdited = Boolean(context.payload.changes?.title);

            if (isEdit && !titleWasEdited) {
              return;
            }

            const title = issue.title ?? '';
            const body = issue.body ?? '';

            // Freeform bug reports: "issue: ...", "bug: ...", "fix: ...", "[Bug] ...", "issue/UX: ..."
            const bugLikeTitle = /^\s*(\[\s*(bug|issue|fix)\b[^\]]*\]|(bug|issue|fix)\s*[:/\-])/i.test(title);

            // API/CLI-created issues that reproduce the bug report form structure.
            // Only headings distinctive to the bug form (both are required fields there) —
            // generic headings like "Expected Behavior" also appear in freeform feature requests.
            const bugFormBody = /###\s*(Installation Method|Open WebUI Version)/i.test(body);

            if (!bugLikeTitle && !bugFormBody) {
              return;
            }

            if (isEdit) {
              const events = await github.paginate(github.rest.issues.listEvents, {
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                per_page: 100
              });

              const bugLabelWasRemoved = events.some(
                (event) => event.event === 'unlabeled' && event.label?.name === 'bug'
              );

              if (bugLabelWasRemoved) {
                return;
              }
            }

            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issue.number,
              labels: ['bug']
            });

  label-feature-requests:
    runs-on: ubuntu-latest
    steps:
      - name: Add "enhancement" label to unlabeled feature requests
        uses: actions/github-script@v7
        with:
          script: |
            const issue = context.payload.issue;

            if (issue.labels.some((label) => label.name === 'enhancement')) {
              return;
            }

            // A human (or the bug form) already classified this as a bug;
            // do not stack a second, contradictory classification on it.
            if (issue.labels.some((label) => label.name === 'bug')) {
              return;
            }

            const isEdit = context.payload.action === 'edited';
            const titleWasEdited = Boolean(context.payload.changes?.title);

            if (isEdit && !titleWasEdited) {
              return;
            }

            const title = issue.title ?? '';
            const body = issue.body ?? '';

            // Feature requests: "feat: ...", "feature: ...", "feature request: ...",
            // "enhancement: ...", "enh: ...", "[Feature Request] ..." — the feature
            // request form titles every submission "feat: ", so form submissions are
            // covered by the same pattern.
            const featureLikeTitle =
              /^\s*(\[\s*(feat|feature|enhancement|enh)\b[^\]]*\]|(feat|feature( request)?|enhancement|enh)\s*[:/\-])/i.test(
                title
              );

            // API/CLI-created issues that reproduce the feature request form structure.
            // Only headings distinctive to that form.
            const featureFormBody = /###\s*(Proposed Solution|Alternatives Considered)/i.test(body);

            if (!featureLikeTitle && !featureFormBody) {
              return;
            }

            if (isEdit) {
              const events = await github.paginate(github.rest.issues.listEvents, {
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: issue.number,
                per_page: 100
              });

              const enhancementLabelWasRemoved = events.some(
                (event) => event.event === 'unlabeled' && event.label?.name === 'enhancement'
              );

              if (enhancementLabelWasRemoved) {
                return;
              }
            }

            await github.rest.issues.addLabels({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: issue.number,
              labels: ['enhancement']
            });
