import { mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { commanderContract } from "../src/components/microservices/host-codex-commander/src/contract";
import { createCommanderRequestHandler, type RuntimeConfig } from "../src/components/microservices/host-codex-commander/src/index";
import {
  buildCommanderApprovalDraft,
  commanderApprovalPreview,
  commanderHealth,
  commanderSessionPreview,
  commanderStatePaths,
  listCommanderSessions,
  readCommanderApproval,
  readCommanderSession,
  summarizeCommanderTrace,
  writeCommanderApproval,
  writeCommanderSession,
} from "../src/components/microservices/host-codex-commander/src/state";

type JsonRecord = Record<string, unknown>;

function assertCondition(condition: unknown, message: string, detail: unknown = {}): void {
  if (!condition) throw new Error(`${message}: ${JSON.stringify(detail)}`);
}

function asRecord(value: unknown, label: string): JsonRecord {
  assertCondition(typeof value === "object" && value !== null && !Array.isArray(value), `${label} must be an object`, value);
  return value as JsonRecord;
}

function dataOf(response: JsonRecord): JsonRecord {
  return asRecord(response.body, "body");
}

async function readJson(response: Response): Promise<JsonRecord> {
  const body = await response.json();
  return asRecord(body, "response body");
}

const tmp = mkdtempSync(join(tmpdir(), "host-codex-commander-"));
const runtime: RuntimeConfig = {
  rootDir: tmp,
  host: "127.0.0.1",
  port: 4261,
  logFile: join(tmp, "logs", "commander.jsonl"),
  serviceId: "host-codex-commander",
  stateRoot: tmp,
  sessionId: "primary",
};
const handler = createCommanderRequestHandler(runtime);

try {
  const contract = commanderContract();
  assertCondition(contract.ok === true, "contract must be ok", contract);
  assertCondition(contract.serviceId === "host-codex-commander", "contract must expose service id", contract);
  assertCondition(contract.daemonImplemented === false, "contract must remain skeleton only", contract);
  assertCondition(contract.currentImplementation === "host-codex-commander-skeleton", "contract must identify skeleton implementation", contract);

  const session = writeCommanderSession(runtime, {
    sessionId: "primary",
    state: "running",
    promptState: "planned",
    approvalState: "draft",
    pid: 321,
    cwd: "/workspace/unidesk",
    lastSeq: 7,
    heartbeatAt: "2026-05-21T00:00:00.000Z",
    updatedAt: "2026-05-21T00:00:00.000Z",
    notes: ["token=ghp_abcdef1234567890", "trace-summary:running"],
  });
  assertCondition(session.notes[0] === "<redacted>", "session notes must be redacted", session);
  assertCondition(readCommanderSession(runtime, "primary").state === "running", "session read must round-trip", readCommanderSession(runtime, "primary"));
  assertCondition(listCommanderSessions(runtime).length >= 1, "session listing must include stored session", listCommanderSessions(runtime));
  const sessionPreview = asRecord(commanderSessionPreview(session), "session preview");
  const sessionPreviewNotes = Array.isArray(sessionPreview.notes) ? sessionPreview.notes.map((item) => String(item)) : [];
  assertCondition(sessionPreviewNotes.includes("<redacted>"), "session preview must redact notes", sessionPreview);

  const trace = summarizeCommanderTrace({
    taskId: "task-123",
    sessionId: "primary",
    traceJsonl: [
      JSON.stringify({ seq: 1, kind: "message", status: "running", summary: "prompt token=ghp_1234567890abcdef" }),
      JSON.stringify({ seq: 4, kind: "command", status: "attention_required", command: "ask-for-approval", output: "reason=https://user:secret@example.com" }),
      JSON.stringify({ seq: 8, kind: "event", status: "completed", text: "done" }),
    ].join("\n"),
    taskSummary: "task summary token=ghp_aaaaaaaaaaaaaaaa",
  });
  assertCondition(trace.taskId === "task-123", "trace summary must preserve task id", trace);
  assertCondition(trace.lastSeq === 8, "trace summary must preserve last seq", trace);
  assertCondition(trace.status === "terminal", "trace summary should reach terminal status", trace);
  assertCondition(trace.redactionsApplied >= 2, "trace summary must redact secrets", trace);
  assertCondition(trace.taskSummaryPreview?.includes("<redacted>") === true, "task summary preview must redact", trace);
  assertCondition(trace.keyEvents.length > 0, "trace summary must include key events", trace);

  const approval = buildCommanderApprovalDraft({
    approvalId: "draft-1",
    action: "code-queue-task-interrupt",
    taskId: "task-123",
    reason: "token=ghp_1234567890abcdef https://user:secret@example.com",
    sessionId: "primary",
  });
  assertCondition(approval.reason.includes("<redacted>"), "approval reason must redact", approval);
  assertCondition(approval.previewMarkdown.includes("<redacted>"), "approval preview must redact", approval);
  assertCondition(approval.previewJson["sendImplemented"] === false, "approval preview must not imply sending", approval.previewJson);
  writeCommanderApproval(runtime, approval);
  assertCondition(readCommanderApproval(runtime, "draft-1").reason.includes("<redacted>"), "approval round-trip must preserve redaction", readCommanderApproval(runtime, "draft-1"));

  const health = commanderHealth(runtime, "2026-05-21T00:00:00.000Z");
  assertCondition(health.ok === true && health.service === "host-codex-commander", "health must expose service metadata", health);
  assertCondition(health.stateRoot === tmp, "health must point at temp state root", health);

  const healthBody = await readJson(await handler(new Request("http://localhost/health")));
  assertCondition(healthBody.ok === true, "health route must succeed", healthBody);

  const contractBody = await readJson(await handler(new Request("http://localhost/api/commander/contract")));
  assertCondition(contractBody.serviceId === "host-codex-commander", "HTTP contract route must expose service id", contractBody);

  const sessionsBody = await readJson(await handler(new Request("http://localhost/api/commander/sessions")));
  assertCondition(Array.isArray(sessionsBody.sessions) && sessionsBody.sessions.length >= 1, "sessions route must list sessions", sessionsBody);

  const traceBody = await readJson(await handler(new Request(`http://localhost/api/commander/trace-summary?taskId=task-123&traceJsonl=${encodeURIComponent(JSON.stringify({ seq: 1, status: "running", summary: "hello token=ghp_1234567890abcdef" }))}`)));
  assertCondition(traceBody.ok === true && Number(asRecord(traceBody.summary, "summary").redactionsApplied) >= 1, "trace route must redact and summarize", traceBody);

  const approvalBody = await readJson(await handler(new Request("http://localhost/api/commander/approvals", {
    method: "POST",
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ action: "code-queue-task-cancel", reason: "cookie=session=secret", taskId: "task-123" }),
  })));
  assertCondition(approvalBody.ok === true, "approval route must succeed", approvalBody);
  assertCondition(String(JSON.stringify(approvalBody)).includes("<redacted>"), "approval route must redact sensitive text", approvalBody);

  const statePath = commanderStatePaths(runtime);
  assertCondition(readFileSync(statePath.stateFile, "utf8").length > 0, "state file must be written", statePath);
  assertCondition(readFileSync(statePath.approvalFile, "utf8").length > 0, "approval file must be written", statePath);

  process.stdout.write(`${JSON.stringify({
    ok: true,
    checks: [
      "commander contract exposes skeleton contract boundaries",
      "state files round-trip and redact secrets",
      "trace summary aggregates mock jsonl input",
      "approval draft preview stays preview-only and redacted",
      "HTTP handler serves /health, /api/commander/contract, /api/commander/sessions, /api/commander/trace-summary, and /api/commander/approvals",
    ],
  }, null, 2)}\n`);
} finally {
  rmSync(tmp, { recursive: true, force: true });
}
