name: Auto Format

on:
  pull_request_target:
    branches: [main]
    types: [opened, synchronize]

permissions:
  contents: read

jobs:
  format:
    name: Format
    # Skip bot-authored commits to avoid infinite loops
    if: github.actor != 'emdashbot[bot]'
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - name: Generate token
        id: app-token
        uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
        with:
          app-id: ${{ secrets.APP_ID }}
          private-key: ${{ secrets.APP_PRIVATE_KEY }}

      - name: Get PR details
        id: pr
        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
        with:
          github-token: ${{ steps.app-token.outputs.token }}
          script: |
            const pr = context.payload.pull_request;
            const isFork = pr.head.repo.fork || pr.head.repo.full_name !== `${context.repo.owner}/${context.repo.repo}`;
            core.setOutput('ref', pr.head.ref);
            core.setOutput('sha', pr.head.sha);
            core.setOutput('number', pr.number.toString());
            core.setOutput('is_fork', isFork.toString());
            core.setOutput('full_name', pr.head.repo.full_name);

      # --- Same-repo PRs: checkout and push directly ---

      - name: Checkout (same-repo)
        if: steps.pr.outputs.is_fork == 'false'
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          ref: ${{ steps.pr.outputs.ref }}
          token: ${{ steps.app-token.outputs.token }}

      # --- Fork PRs: checkout the fork at the pinned SHA ---

      - name: Checkout (fork)
        if: steps.pr.outputs.is_fork == 'true'
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
        with:
          repository: ${{ steps.pr.outputs.full_name }}
          ref: ${{ steps.pr.outputs.sha }}
          persist-credentials: false

      - name: Setup Node
        uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
        with:
          node-version: 22

      - name: Run formatter
        run: npx oxfmt --ignore-path .gitignore

      - name: Check for changes
        id: diff
        run: |
          git add -A
          if git diff --staged --quiet; then
            echo "changed=false" >> "$GITHUB_OUTPUT"
          else
            echo "changed=true" >> "$GITHUB_OUTPUT"
          fi

      # --- Same-repo: push directly ---

      - name: Commit and push (same-repo)
        if: steps.pr.outputs.is_fork == 'false' && steps.diff.outputs.changed == 'true'
        run: |
          git config user.name "emdashbot[bot]"
          git config user.email "emdashbot[bot]@users.noreply.github.com"
          git commit -m "style: format"
          git push

      # --- Fork: push via git with GIT_ASKPASS ---

      - name: Commit and push (fork)
        if: steps.pr.outputs.is_fork == 'true' && steps.diff.outputs.changed == 'true'
        id: push-fork
        run: |
          git config user.name "emdashbot[bot]"
          git config user.email "emdashbot[bot]@users.noreply.github.com"
          git commit -m "style: format"
          # Push to the fork using the app token via GIT_ASKPASS to avoid
          # leaking the token in process args or git config
          export GIT_ASKPASS="$RUNNER_TEMP/git-askpass.sh"
          printf '#!/bin/sh\necho "%s"\n' "$APP_TOKEN" > "$GIT_ASKPASS"
          chmod +x "$GIT_ASKPASS"
          git remote add fork "https://x-access-token@github.com/${{ steps.pr.outputs.full_name }}.git"
          if git push fork "HEAD:${{ steps.pr.outputs.ref }}"; then
            echo "push_failed=false" >> "$GITHUB_OUTPUT"
          else
            echo "push_failed=true" >> "$GITHUB_OUTPUT"
          fi
          rm -f "$GIT_ASKPASS"
        env:
          APP_TOKEN: ${{ steps.app-token.outputs.token }}

      - name: Comment on push failure
        if: steps.push-fork.outputs.push_failed == 'true'
        uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
        with:
          github-token: ${{ steps.app-token.outputs.token }}
          script: |
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: ${{ steps.pr.outputs.number }},
              body: `Could not push formatting changes to this fork. The contributor may have "Allow edits by maintainers" disabled.\n\nPlease run the formatter locally:\n\n\`\`\`\npnpm format\n\`\`\``,
            });
