name: PR Preview Deploy

on:
  workflow_run:
    workflows: ['PR Preview Build']
    types: [completed]

permissions:
  actions: read
  contents: read
  pull-requests: write
  issues: write
  deployments: write

jobs:
  deploy-preview:
    if: >
      github.event.workflow_run.event == 'pull_request' &&
      github.event.workflow_run.conclusion == 'success'
    continue-on-error: true
    runs-on: ubuntu-latest
    environment: preview-deployments

    steps:
      - name: Download build artifact
        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v4
        with:
          name: pr-preview-build
          path: dist/browser
          run-id: ${{ github.event.workflow_run.id }}
          github-token: ${{ github.token }}

      - name: Get PR info
        id: pr
        env:
          GH_TOKEN: ${{ github.token }}
          HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }}
          HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
          HEAD_OWNER: ${{ github.event.workflow_run.head_repository.owner.login }}
          REPO_OWNER: ${{ github.event.workflow_run.repository.owner.login }}
          REPO: ${{ github.repository }}
        run: |
          # Handle fork PRs vs same-repo PRs
          if [ "$HEAD_OWNER" != "$REPO_OWNER" ]; then
            BRANCH="${HEAD_OWNER}:${HEAD_BRANCH}"
          else
            BRANCH="${HEAD_BRANCH}"
          fi

          PR_NUMBER=$(gh pr view --repo "$REPO" "$BRANCH" --json number --jq '.number')

          if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then
            echo "::error::Could not determine PR number"
            exit 1
          fi

          # Sanitize branch name for safe use in downstream commands
          SAFE_BRANCH=$(echo "$HEAD_BRANCH" | sed 's/[^a-zA-Z0-9._\/-]//g')

          echo "number=$PR_NUMBER" >> "$GITHUB_OUTPUT"
          echo "head_branch=$SAFE_BRANCH" >> "$GITHUB_OUTPUT"
          echo "head_sha=$HEAD_SHA" >> "$GITHUB_OUTPUT"

      - name: Deploy to Cloudflare Pages
        id: cloudflare-deploy
        uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          command: pages deploy dist/browser --project-name=super-productivity-preview --branch=${{ steps.pr.outputs.head_branch }}

      - name: Find existing comment
        uses: peter-evans/find-comment@b30e6a3c0ed37e7c023ccd3f1db5c6c0b0c23aad # v4.0.0
        id: find-comment
        with:
          issue-number: ${{ steps.pr.outputs.number }}
          comment-author: 'github-actions[bot]'
          body-includes: '<!-- pr-preview-comment -->'

      - name: Create or update PR comment
        uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
        with:
          comment-id: ${{ steps.find-comment.outputs.comment-id }}
          issue-number: ${{ steps.pr.outputs.number }}
          edit-mode: replace
          body: |
            <!-- pr-preview-comment -->
            ## Preview Deployment

            | Status | URL |
            |--------|-----|
            | Deployed | ${{ steps.cloudflare-deploy.outputs.deployment-url }} |

            **Branch:** `${{ steps.pr.outputs.head_branch }}`
            **Commit:** ${{ steps.pr.outputs.head_sha }}

            ---
            <sub>Deployed with Cloudflare Pages</sub>

      - name: Find linked issues
        id: linked
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          PR_NUMBER: ${{ steps.pr.outputs.number }}
        run: |
          set -euo pipefail
          # Only issues linked via a closing keyword (Closes/Fixes #N); most PRs link none.
          # pipefail surfaces a gh failure instead of silently reporting zero issues.
          NUMBERS=$(gh pr view "$PR_NUMBER" --repo "$REPO" \
            --json closingIssuesReferences \
            --jq '[.closingIssuesReferences[].number | tostring] | join(" ")')
          echo "numbers=$NUMBERS" >> "$GITHUB_OUTPUT"

      - name: Post preview link to linked issues
        if: steps.linked.outputs.numbers != '' && steps.cloudflare-deploy.outputs.deployment-url != ''
        env:
          GH_TOKEN: ${{ github.token }}
          REPO: ${{ github.repository }}
          URL: ${{ steps.cloudflare-deploy.outputs.deployment-url }}
          PR_NUMBER: ${{ steps.pr.outputs.number }}
          ISSUE_NUMBERS: ${{ steps.linked.outputs.numbers }}
        run: |
          set -euo pipefail
          MARKER="<!-- pr-preview-issue-comment -->"
          BODY=$(cat <<EOF
          $MARKER
          🔍 A live preview of the proposed fix in #${PR_NUMBER} is available (not yet released):

          ${URL}

          Help testing this would be appreciated 🙏
          EOF
          )
          for ISSUE in $ISSUE_NUMBERS; do
            # Find-or-update a single bot-authored marker comment per issue: in-place
            # edits are silent, so subscribers are notified at most once. Restrict to
            # the Actions bot's own comments so we never overwrite a user's comment.
            IDS_RAW=$(gh api "repos/$REPO/issues/$ISSUE/comments" --paginate \
              --jq ".[] | select(.user.login == \"github-actions[bot]\" and (.body | contains(\"$MARKER\"))) | .id")
            mapfile -t IDS < <(printf '%s\n' "$IDS_RAW" | grep -E '^[0-9]+$' || true)
            if [ "${#IDS[@]}" -gt 0 ]; then
              gh api -X PATCH "repos/$REPO/issues/comments/${IDS[0]}" -f body="$BODY"
              # Reconcile duplicates from an earlier concurrent run so only one remains.
              for EXTRA in "${IDS[@]:1}"; do
                gh api -X DELETE "repos/$REPO/issues/comments/$EXTRA" || true
              done
            else
              gh api -X POST "repos/$REPO/issues/$ISSUE/comments" -f body="$BODY"
            fi
          done
