import { readFileSync } from "fs"
import path from "path"
import { describe, expect, test } from "bun:test"

/**
 * The two GraphQL fetch scripts in ce-resolve-pr-feedback must paginate.
 *
 * Issue #798: previous versions used fixed `first: N` page sizes with no
 * cursor loop, so PRs with more than one page of review threads / comments /
 * reviews silently dropped everything past page 1. The skill then reported
 * "0 of 0 resolved" while real findings sat unanswered.
 *
 * `gh api graphql --paginate` follows only one `pageInfo` per response, so
 * `get-pr-comments` must issue a separate paginated query for each top-level
 * connection. `get-thread-for-comment` paginates the single `reviewThreads`
 * connection it queries.
 */

const SCRIPTS_DIR = path.join(
  process.cwd(),
  "skills/ce-resolve-pr-feedback/scripts",
)

const PAGE_INFO_SELECTION = /pageInfo\s*\{\s*hasNextPage\s+endCursor\s*\}/

function read(name: string): string {
  return readFileSync(path.join(SCRIPTS_DIR, name), "utf8")
}

describe("ce-resolve-pr-feedback scripts paginate GraphQL connections (issue #798)", () => {
  test("get-pr-comments uses --paginate for every top-level connection", () => {
    const body = read("get-pr-comments")
    const paginateCount = (body.match(/gh api graphql --paginate\b/g) ?? []).length
    expect(
      paginateCount,
      "get-pr-comments must issue three paginated queries (reviewThreads, comments, reviews); `gh api graphql --paginate` only follows the outermost pageInfo per response, so combining them in one query silently drops everything past page 1.",
    ).toBeGreaterThanOrEqual(3)
  })

  test("get-pr-comments paginates every connection it queries", () => {
    const body = read("get-pr-comments")
    for (const conn of ["reviewThreads", "comments", "reviews"]) {
      const re = new RegExp(`${conn}\\(first:\\s*\\d+,\\s*after:\\s*\\$endCursor\\)`)
      expect(
        re.test(body),
        `get-pr-comments must call ${conn}(first: N, after: $endCursor); fixed page sizes truncate on long-lived PRs.`,
      ).toBe(true)
    }
  })

  test("get-pr-comments selects pageInfo { hasNextPage endCursor } in each query", () => {
    const body = read("get-pr-comments")
    const matches = body.match(new RegExp(PAGE_INFO_SELECTION.source, "g")) ?? []
    expect(
      matches.length,
      "Each paginated GraphQL query must select pageInfo { hasNextPage endCursor } so `gh api graphql --paginate` can drive the cursor loop.",
    ).toBeGreaterThanOrEqual(3)
  })

  test("get-thread-for-comment paginates the reviewThreads connection", () => {
    const body = read("get-thread-for-comment")
    expect(
      body,
      "get-thread-for-comment must paginate reviewThreads, otherwise comment lookups fail on PRs with >100 threads.",
    ).toMatch(/gh api graphql --paginate\b/)
    expect(body).toMatch(/reviewThreads\(first:\s*\d+,\s*after:\s*\$endCursor\)/)
    expect(body).toMatch(PAGE_INFO_SELECTION)
  })
})
