on:
  issues:
    types: [opened]

name: Close issues when the "ticked without reading" checkbox is checked

permissions:
  issues: write

jobs:
  detect-and-close:
    runs-on: ubuntu-latest
    steps:
      - name: Detect checked "ticked without reading" checkbox, comment, close and lock
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          OWNER: ${{ github.repository_owner }}
          REPO: ${{ github.event.repository.name }}
          ISSUE_NUMBER: ${{ github.event.issue.number }}
          ISSUE_BODY: ${{ toJson(github.event.issue.body) }}
          ISSUE_USER: ${{ github.event.issue.user.login }}
        run: |
          set -euo pipefail

          # Normalize the JSON-encoded body into plain text
          BODY=$(printf '%s' "$ISSUE_BODY" | sed -E 's/^"(.*)"$/\1/' | sed 's/\\"/"/g' | sed 's/\\n/\n/g')

          echo "Checking issue #${ISSUE_NUMBER} for the target checked checkbox..."
          # Use -- to stop option parsing so the leading - in the pattern isn't treated as an option
          if printf '%s' "$BODY" | grep -Fiq -- "- [x] I've ticked the checkboxes without reading their contents"; then
            echo "Target checkbox is checked. Proceeding to comment, close and lock the issue."

            # --- Get issue node id via GraphQL ---
            QUERY='query($owner: String!, $name: String!, $number: Int!) { repository(owner: $owner, name: $name) { issue(number: $number) { id } } }'
            GET_ID_PAYLOAD=$(jq -n --arg q "$QUERY" --arg owner "$OWNER" --arg name "$REPO" --argjson number "$ISSUE_NUMBER" '{query:$q, variables:{owner:$owner, name:$name, number:$number}}')

            echo "GraphQL: fetching issue node id..."
            RES=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" -H "Content-Type: application/json" -d "$GET_ID_PAYLOAD" https://api.github.com/graphql)
            echo "GraphQL response (get id):"
            printf '%s\n' "$RES"

            ISSUE_ID=$(printf '%s' "$RES" | jq -r '.data.repository.issue.id // empty')

            if [ -z "$ISSUE_ID" ]; then
              echo "Failed to get issue id from GraphQL response. Aborting."
              exit 1
            fi
            echo "Issue node id: $ISSUE_ID"

            # --- Post a comment to the issue ---
            COMMENT_BODY="Hi @${ISSUE_USER} — I noticed you checked \"I've ticked the checkboxes without reading their contents\" in the issue template. To help others assist you effectively, please read the template and provide the requested diagnostic information (Step 2 & Step 3). I will close this issue now. If you create a new issue with the required information, we can re-evaluate. Thank you!"
            MUT_ADD_COMMENT='mutation($id: ID!, $body: String!) { addComment(input: {subjectId: $id, body: $body}) { clientMutationId } }'
            ADD_COMMENT_PAYLOAD=$(jq -n --arg q "$MUT_ADD_COMMENT" --arg id "$ISSUE_ID" --arg body "$COMMENT_BODY" '{query:$q, variables:{id:$id, body:$body}}')

            echo "GraphQL: adding comment..."
            RES_COMMENT=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" -H "Content-Type: application/json" -d "$ADD_COMMENT_PAYLOAD" https://api.github.com/graphql)
            echo "GraphQL response (add comment):"
            printf '%s\n' "$RES_COMMENT"

            ERR_COMMENT=$(printf '%s' "$RES_COMMENT" | jq -r '.errors[]?.message // empty')
            if [ -n "$ERR_COMMENT" ]; then
              echo "addComment error: $ERR_COMMENT"
              exit 1
            fi
            echo "Comment posted."

            # --- Attempt to close via GraphQL updateIssue ---
            MUT_UPDATE_ISSUE='mutation($id: ID!) { updateIssue(input: {id: $id, state: CLOSED, stateReason: NOT_PLANNED}) { issue { number, state, stateReason } } }'
            UPDATE_PAYLOAD=$(jq -n --arg q "$MUT_UPDATE_ISSUE" --arg id "$ISSUE_ID" '{query:$q, variables:{id:$id}}')

            echo "GraphQL: updating issue (close with NOT_PLANNED)..."
            RES_UPDATE=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" -H "Content-Type: application/json" -d "$UPDATE_PAYLOAD" https://api.github.com/graphql)
            echo "GraphQL response (update issue):"
            printf '%s\n' "$RES_UPDATE"

            ERR_UPDATE=$(printf '%s' "$RES_UPDATE" | jq -r '.errors[]?.message // empty')
            UPDATED_STATE=$(printf '%s' "$RES_UPDATE" | jq -r '.data.updateIssue.issue.state // empty')
            UPDATED_REASON=$(printf '%s' "$RES_UPDATE" | jq -r '.data.updateIssue.issue.stateReason // empty')

            CLOSED_OK=false

            if [ -n "$ERR_UPDATE" ]; then
              echo "GraphQL updateIssue returned errors: $ERR_UPDATE"
            fi

            if [ "$UPDATED_STATE" = "CLOSED" ]; then
              echo "Issue closed via GraphQL: state=$UPDATED_STATE, stateReason=$UPDATED_REASON"
              CLOSED_OK=true
            else
              echo "GraphQL update did not confirm the issue is closed. Falling back to REST API PATCH to ensure the issue is closed."

              # REST fallback to close the issue with state_reason "not_planned"
              REST_PAYLOAD=$(jq -n --arg state "closed" --arg sr "not_planned" '{state:$state, state_reason:$sr}')
              echo "REST: PATCH /repos/$OWNER/$REPO/issues/$ISSUE_NUMBER payload: $REST_PAYLOAD"
              RES_REST=$(curl -s -w "\n%{http_code}" -X PATCH \
                -H "Authorization: Bearer $GITHUB_TOKEN" \
                -H "Accept: application/vnd.github+json" \
                -H "Content-Type: application/json" \
                -d "$REST_PAYLOAD" \
                "https://api.github.com/repos/$OWNER/$REPO/issues/$ISSUE_NUMBER")

              HTTP_STATUS=$(printf '%s' "$RES_REST" | tail -n1)
              RESP_BODY=$(printf '%s' "$RES_REST" | sed '$d')

              echo "REST response body:"
              printf '%s\n' "$RESP_BODY"
              echo "REST HTTP status: $HTTP_STATUS"

              if [ "$HTTP_STATUS" -ge 200 ] && [ "$HTTP_STATUS" -lt 300 ]; then
                CLOSED_STATE=$(printf '%s' "$RESP_BODY" | jq -r '.state // empty')
                CLOSED_REASON=$(printf '%s' "$RESP_BODY" | jq -r '.state_reason // empty')
                echo "Issue closed via REST: state=$CLOSED_STATE, state_reason=$CLOSED_REASON"
                if [ "$CLOSED_STATE" = "closed" ]; then
                  CLOSED_OK=true
                fi
              else
                echo "REST fallback failed to close the issue. See REST response above."
                exit 1
              fi
            fi

            # --- Attempt to lock the conversation (GraphQL first, then REST fallback) ---
            if [ "$CLOSED_OK" = "true" ]; then
              echo "Attempting to lock the conversation via GraphQL with reason NO_REASON..."

              MUT_LOCK='mutation($id: ID!, $reason: LockReason) { lockLockable(input:{lockableId:$id, lockReason:$reason}) { clientMutationId } }'
              LOCK_PAYLOAD=$(jq -n --arg q "$MUT_LOCK" --arg id "$ISSUE_ID" --arg reason "NO_REASON" '{query:$q, variables:{id:$id, reason:$reason}}')

              RES_LOCK=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" -H "Content-Type: application/json" -d "$LOCK_PAYLOAD" https://api.github.com/graphql)
              echo "GraphQL response (lock):"
              printf '%s\n' "$RES_LOCK"

              LOCK_ERR=$(printf '%s' "$RES_LOCK" | jq -r '.errors[]?.message // empty')

              if [ -n "$LOCK_ERR" ]; then
                echo "GraphQL lockLockable returned errors: $LOCK_ERR"
                echo "Falling back to REST API to lock the conversation (no explicit reason)."

                # REST fallback to lock the issue (no lock_reason to indicate "no reason")
                RES_REST_LOCK=$(curl -s -w "\n%{http_code}" -X PUT \
                  -H "Authorization: Bearer $GITHUB_TOKEN" \
                  -H "Accept: application/vnd.github+json" \
                  "https://api.github.com/repos/$OWNER/$REPO/issues/$ISSUE_NUMBER/lock" -d '{}')

                HTTP_STATUS_LOCK=$(printf '%s' "$RES_REST_LOCK" | tail -n1)
                RESP_BODY_LOCK=$(printf '%s' "$RES_REST_LOCK" | sed '$d')

                echo "REST lock response body:"
                printf '%s\n' "$RESP_BODY_LOCK"
                echo "REST lock HTTP status: $HTTP_STATUS_LOCK"

                if [ "$HTTP_STATUS_LOCK" -ge 200 ] && [ "$HTTP_STATUS_LOCK" -lt 300 ]; then
                  echo "Issue conversation locked via REST (no explicit reason)."
                else
                  echo "REST fallback failed to lock the conversation. See REST response above."
                  exit 1
                fi
              else
                echo "Lock via GraphQL succeeded (or returned no errors)."
              fi
            else
              echo "Issue was not successfully closed; skipping lock."
            fi

          else
            echo "Checkbox not present/checked. Nothing to do."
          fi
