import { existsSync, readFileSync, readdirSync, rmSync } from "node:fs";
import { spawnSync } from "node:child_process";
import { describe, expect, test } from "bun:test";
import { repoRoot } from "./config";

const dumpDir = "/tmp/unidesk-cli-output";

function runOversizedIssueOutput(token: string, explicit = false): { status: number | null; stdout: string; stderr: string } {
  const command = `gh issue view 1890 --repo pikasTech/unidesk --json body ${token}`;
  const script = [
    "import { emitJson } from './scripts/src/output.ts';",
    `emitJson(${JSON.stringify(command)}, {`,
    "  command: 'issue view',",
    "  repo: 'pikasTech/unidesk',",
    "  issue: { number: 1890, title: 'large body', state: 'open', url: 'https://example.invalid/1890', body: 'x'.repeat(30000) },",
    "});",
  ].join("\n");
  const args = ["-e", script, "output-test", ...(explicit ? ["--full"] : [])];
  const result = spawnSync("bun", args, { cwd: repoRoot, encoding: "utf8" });
  return { status: result.status, stdout: result.stdout, stderr: result.stderr };
}

function matchingDumps(token: string): string[] {
  if (!existsSync(dumpDir)) return [];
  return readdirSync(dumpDir).filter((name) => name.includes(token));
}

describe("CLI oversized output disclosure", () => {
  test("default oversized output creates no dump and gives the semantic gh text route", () => {
    const token = `nodump-${process.pid}-${Date.now()}`;
    expect(matchingDumps(token)).toEqual([]);

    const result = runOversizedIssueOutput(token);

    expect(result.status).toBe(0);
    expect(result.stderr).toBe("");
    const payload = JSON.parse(result.stdout) as { data: { outputTruncated: boolean; dump?: unknown; next: string[]; disclosurePolicy: Record<string, unknown> } };
    expect(payload.data.outputTruncated).toBe(true);
    expect(payload.data.dump).toBeUndefined();
    expect(payload.data.disclosurePolicy).toMatchObject({ defaultCreatesDump: false, dumpCreated: false });
    expect(payload.data.next[0]).toBe("trans gh:/pikasTech/unidesk/issue/1890 cat");
    expect(matchingDumps(token)).toEqual([]);
  });

  test("explicit full disclosure keeps a protected complete dump", () => {
    const token = `fulldump-${process.pid}-${Date.now()}`;
    expect(matchingDumps(token)).toEqual([]);

    const result = runOversizedIssueOutput(token, true);

    expect(result.status).toBe(0);
    expect(result.stderr).toBe("");
    const payload = JSON.parse(result.stdout) as { data: { dump: { path: string }; disclosurePolicy: Record<string, unknown> } };
    expect(payload.data.disclosurePolicy).toMatchObject({ defaultCreatesDump: false, dumpCreated: true });
    expect(existsSync(payload.data.dump.path)).toBe(true);
    expect(readFileSync(payload.data.dump.path, "utf8")).toContain(token);
    rmSync(payload.data.dump.path, { force: true });
    expect(matchingDumps(token)).toEqual([]);
  });
});
