import { afterEach, beforeEach, describe, expect, test } from "bun:test";
import type { Server } from "bun";
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { Journal } from "../src/journal";
import { CollectorState } from "../src/state";
import { startServer } from "../src/server";
import type { LoadedIncidentOptions } from "../src/incidents/dispatch-options";
import type { IncidentsProvider } from "../src/incidents/provider";
import type { Incident } from "../src/incidents/incident-service";

const TOKEN = "production-incidents-wiring-token";

function optionsFixture(): LoadedIncidentOptions {
  const internal = new Map<string, { wrapperModel: string; permissionMode: "safe" | "unsafe"; fixed: boolean }>();
  internal.set(["claude", "fable", "high", "main", "safe"].join("\0"), { wrapperModel: "fable-high", permissionMode: "safe", fixed: false });
  return {
    types: [{ id: "resource-overload", title: "Resource overload", keywords: ["cpu"] }],
    clis: [{ id: "claude", label: "Claude", models: [{ id: "fable", efforts: ["high"] }], accounts: [{ slug: "main", label: "Main", ready: true, fixed: false }], permissionModes: ["safe"] }],
    sourcePaths: [],
    internal,
  };
}

function incidentFixture(): Incident {
  return {
    id: "6ba7b810-9dad-41d1-80b4-00c04fd430c8",
    kanboardTaskId: 42,
    title: "Collector wedged",
    description: "No deltas",
    priority: "P1",
    incidentType: null,
    dispatchBrief: null,
    dispatchBriefProvenance: null,
    state: "filed",
    active: true,
    createdAt: null,
    updatedAt: null,
    resolvedAt: null,
    dispatch: {
      state: "filed",
      dispatchId: null,
      cli: "claude",
      model: "fable",
      wrapperModel: null,
      reasoningEffort: "high",
      account: "main",
      requestSha256: null,
      statusRevision: null,
      startedAt: null,
      heartbeatAt: null,
      completedAt: null,
      exitCode: null,
      failureClass: null,
      resultSummary: null,
    },
    activity: [],
    coverage: { stale: false },
  };
}

describe("production incidents startup wiring", () => {
  let server: Server<undefined> | undefined;
  let dir: string;

  beforeEach(() => {
    dir = mkdtempSync(join(tmpdir(), "collector-production-incidents-"));
  });

  afterEach(() => {
    server?.stop(true);
    server = undefined;
    rmSync(dir, { recursive: true, force: true });
  });

  test("mirrors index.ts by passing loadIncidentOptions to startServer for mutation routes", async () => {
    const incidents: IncidentsProvider = {
      async listIncidents() { return { incidents: [], coverage: { stale: false }, page: { highWater: 0, nextCursor: null, exhausted: true, order: "id_desc" } }; },
      async getIncident() { return null; },
      async fileIncident() { return incidentFixture(); },
      async dispatchIncident() { return { ...incidentFixture(), state: "dispatching" }; },
      async resolveIncident() { return { ...incidentFixture(), state: "resolved" }; },
      async getOptions() { return { types: optionsFixture().types, clis: optionsFixture().clis }; },
    };

    server = startServer({
      host: "127.0.0.1",
      port: 0,
      token: TOKEN,
      state: new CollectorState(new Journal(join(dir, "items.jsonl"))),
      incidents,
      loadIncidentOptions: async () => optionsFixture(),
    });

    const origin = `http://127.0.0.1:${server.port}`;
    const headers = { authorization: `Bearer ${TOKEN}`, "content-type": "application/json" };

    const filed = await fetch(`${origin}/incidents`, {
      method: "POST",
      headers,
      body: JSON.stringify({
        requestId: "6ba7b810-9dad-41d1-80b4-00c04fd430c8",
        title: "Collector wedged",
        description: "No deltas",
        cli: "claude",
        model: "fable",
        reasoningEffort: "high",
        account: "main",
        unsafe: false,
        priority: "P1",
      }),
    });
    expect(filed.status).not.toBe(503);

    const dispatched = await fetch(`${origin}/incidents/6ba7b810-9dad-41d1-80b4-00c04fd430c8/dispatch`, {
      method: "POST",
      headers,
      body: "{}",
    });
    expect(dispatched.status).not.toBe(503);
    expect(await dispatched.json()).toEqual({ incident: { ...incidentFixture(), state: "dispatching" } });
  });
});
