/**
 * WP-08 HostSwitchboard + FactToDoorbellBridge + DualDeliveryGuard.
 */

import { describe, it } from "node:test";
import assert from "node:assert/strict";
import { mkdtemp, mkdir } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";

import {
  AgentHostRegistry,
  DualDeliveryGuard,
  FactToDoorbellBridge,
  HostSwitchboard,
  SwitchboardModeError,
  SwitchboardPaths,
  HostSwitchboard as FromPublic,
  type ActiveAuthorization,
} from "../index.ts";

async function tempPaths(): Promise<SwitchboardPaths> {
  const root = await mkdtemp(join(tmpdir(), "sb-wp08-"));
  const persistDir = join(root, ".codeflowmu", "state");
  await mkdir(persistDir, { recursive: true });
  return new SwitchboardPaths({ persistDir });
}

function auth(ref = "GATE-B-TEST-APPROVE"): ActiveAuthorization {
  return {
    approved: true,
    decisionRef: ref,
    approvedAt: new Date().toISOString(),
    approvedBy: "ADMIN",
  };
}

const allow = {
  decision: "allow" as const,
  reason: "allowed",
};

describe("WP-08 DualDeliveryGuard", () => {
  it("blocks legacy send when mode=active", () => {
    const guard = new DualDeliveryGuard({
      mode: "active",
      activeAuthorization: auth(),
    });
    assert.throws(
      () => guard.assertLegacySendAllowed("work-1"),
      (e: unknown) =>
        e instanceof SwitchboardModeError &&
        /legacy send blocked.*active/.test(e.message),
    );
    guard.assertSwitchboardSendAllowed("work-1");
    assert.equal(guard.isDualDelivery("work-1"), false);
  });

  it("detects dual delivery when both paths fire", () => {
    const guard = new DualDeliveryGuard({ mode: "shadow" });
    guard.recordAttempt("w", "legacy");
    guard.recordAttempt("w", "switchboard");
    assert.equal(guard.isDualDelivery("w"), true);
  });

  it("refuses entering active without Gate B token", () => {
    const guard = new DualDeliveryGuard({ mode: "off" });
    assert.throws(
      () => guard.setMode("active"),
      (e: unknown) => e instanceof SwitchboardModeError,
    );
  });

  it("emergencyStop rolls back to off and blocks both paths", () => {
    const guard = new DualDeliveryGuard({
      mode: "active",
      activeAuthorization: auth(),
    });
    guard.emergencyStop("dual_detected");
    assert.equal(guard.mode, "off");
    assert.throws(() => guard.assertLegacySendAllowed());
    assert.throws(() => guard.assertSwitchboardSendAllowed());
  });
});

describe("WP-08 FactToDoorbellBridge", () => {
  it("refuses formal doorbell in mode=off", async () => {
    const paths = await tempPaths();
    const bridge = new FactToDoorbellBridge({ paths, mode: "off" });
    const result = await bridge.enqueueFromAdmittedWork({
      workerId: "DEV-01",
      summary: "x",
      dedupeKey: "dk-1",
      sourceFactRefs: ["TASK-1"],
      admission: allow,
    });
    assert.equal(result.status, "refused");
  });

  it("enqueues once; same dedupeKey is duplicate", async () => {
    const paths = await tempPaths();
    const bridge = new FactToDoorbellBridge({ paths, mode: "shadow" });
    const fact = {
      workerId: "DEV-01",
      summary: "do work",
      dedupeKey: "dk-unique-1",
      sourceFactRefs: ["TASK-1"],
      admission: allow,
      priority: "P0" as const,
    };
    const a = await bridge.enqueueFromAdmittedWork(fact);
    const b = await bridge.enqueueFromAdmittedWork(fact);
    assert.equal(a.status, "enqueued");
    assert.equal(b.status, "duplicate");
    const pending = await bridge.mailbox.list("DEV-01", "pending");
    assert.equal(pending.length, 1);
  });

  it("refuses when admission is not allow", async () => {
    const paths = await tempPaths();
    const bridge = new FactToDoorbellBridge({ paths, mode: "shadow" });
    const result = await bridge.enqueueFromAdmittedWork({
      workerId: "DEV-01",
      summary: "x",
      dedupeKey: "dk-hold",
      sourceFactRefs: ["TASK-1"],
      admission: { decision: "hold", reason: "waiting_dependency" },
    });
    assert.equal(result.status, "refused");
  });
});

describe("WP-08 HostSwitchboard", () => {
  it("exports from switchboard barrel", () => {
    assert.equal(FromPublic, HostSwitchboard);
  });

  it("blocks wake in mode=off", async () => {
    const paths = await tempPaths();
    const registry = new AgentHostRegistry();
    const board = new HostSwitchboard({
      paths,
      registry,
      mode: "off",
    });
    const result = await board.wakeWorker({
      workerId: "DEV-01",
      doorbellId: "missing",
    });
    assert.equal(result.status, "blocked");
  });

  it("refuses active construction without authorize", async () => {
    const paths = await tempPaths();
    const registry = new AgentHostRegistry();
    assert.throws(
      () =>
        new HostSwitchboard({
          paths,
          registry,
          mode: "active",
        }),
      SwitchboardModeError,
    );
  });
});
