import { expect, test } from "bun:test";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import type { GiteaConfig, GiteaMirrorRepository } from "./platform-infra-gitea-config";
import { renderMirrorBootstrap } from "./platform-infra-gitea-render";
import { resolvePacBootstrapMirrorRepository } from "./platform-infra-pipelines-as-code-bootstrap";
import { runPlatformInfraPipelinesAsCodeCommand } from "./platform-infra-pipelines-as-code";

const mirror: GiteaMirrorRepository = {
  key: "widgets-nc01",
  targetId: "NC01",
  upstream: { repository: "acme/widgets", cloneUrl: "https://github.com/acme/widgets.git", branch: "main", visibility: "public" },
  gitea: { owner: "mirrors", name: "acme-widgets", mirrorMode: "controlled-push", publicRead: true, readUrl: "http://gitea-http.devops-infra.svc.cluster.local:3000/mirrors/acme-widgets.git" },
  gitops: { branch: "main", flushDisposition: "not-a-gitops-branch" },
  snapshot: { prefix: "refs/unidesk/snapshots/widgets-main-nc01" },
  legacyGitMirror: null,
};

function fixtureConfig(repositories: GiteaMirrorRepository[]): GiteaConfig {
  return { sourceAuthority: { repositories } } as unknown as GiteaConfig;
}

test("PaC bootstrap uses one exact YAML-owned Gitea repository", () => {
  const selected = resolvePacBootstrapMirrorRepository(fixtureConfig([mirror]), "nc01", {
    id: "widgets-nc01",
    owner: "mirrors",
    repo: "acme-widgets",
    cloneUrl: `${mirror.gitea.readUrl}/`,
  });
  expect(selected.key).toBe("widgets-nc01");
  expect(() => resolvePacBootstrapMirrorRepository(fixtureConfig([]), "NC01", {
    id: "widgets-nc01",
    owner: "mirrors",
    repo: "acme-widgets",
    cloneUrl: mirror.gitea.readUrl,
  })).toThrow("no exact match");
  expect(() => resolvePacBootstrapMirrorRepository(fixtureConfig([mirror, { ...mirror }]), "NC01", {
    id: "widgets-nc01",
    owner: "mirrors",
    repo: "acme-widgets",
    cloneUrl: mirror.gitea.readUrl,
  })).toThrow("2 exact matches");
});

test("Gitea mirror bootstrap defaults to a visible dry-run instead of an empty refusal", () => {
  const rendered = renderMirrorBootstrap({
    ok: true,
    action: "platform-infra-gitea-mirror-bootstrap",
    mode: "dry-run",
    mutation: false,
    target: { id: "NC01" },
    repositories: [{ key: "widgets-nc01", giteaOwner: "mirrors", giteaRepo: "acme-widgets" }],
    blockers: [],
    next: { confirm: "bun scripts/cli.ts platform-infra gitea mirror bootstrap --target NC01 --repo widgets-nc01 --confirm" },
  }).renderedText;
  expect(rendered).toContain("MODE     MUTATION  TARGET");
  expect(rendered).toContain("widgets-nc01");
  expect(rendered).toContain("--repo widgets-nc01 --confirm");
  expect(rendered).not.toContain("missing-confirm");
});

test("PaC apply checks the Gitea repository before dry-run return and cluster mutation", () => {
  const remote = readFileSync(resolve(import.meta.dir, "platform-infra-pipelines-as-code-remote.sh"), "utf8");
  const action = remote.indexOf("apply_action() {");
  const preflight = remote.indexOf("if ! repository_preflight", action);
  const dryRun = remote.indexOf('if [ "$UNIDESK_PAC_DRY_RUN" = "1" ]', action);
  const release = remote.indexOf("  apply_release", action);
  expect(action).toBeGreaterThanOrEqual(0);
  expect(preflight).toBeGreaterThan(action);
  expect(dryRun).toBeGreaterThan(preflight);
  expect(release).toBeGreaterThan(dryRun);
  expect(remote).toContain('"error":"gitea-repository-missing"');
});

test("platform bootstrap help advertises the composite entry before low-level apply", async () => {
  const help = await runPlatformInfraPipelinesAsCodeCommand({} as never, ["help", "platform-bootstrap"]);
  const usage = (help as Record<string, unknown>).usage as string[];
  expect(usage[0]).toContain("pipelines-as-code bootstrap");
  expect(usage).toContain("bun scripts/cli.ts platform-infra pipelines-as-code bootstrap --target <NODE> --consumer <consumer> --confirm");
});
