/**
 * WP-13 — observation snapshot / host event mapper / evidence fields.
 */

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

import { SwitchboardPaths } from "../../paths/SwitchboardPaths.js";
import { DoorbellMailbox } from "../../store/DoorbellMailbox.js";
import { WorkerBindingStore } from "../../store/WorkerBindingStore.js";
import { RunStore } from "../../store/RunStore.js";
import type { DoorbellMessage } from "../../contracts/DoorbellMessage.js";
import type { WorkerBindingRevision } from "../../contracts/WorkerBinding.js";
import type { RunRecord } from "../../contracts/RunRecord.js";
import {
  ObservationSnapshotBuilder,
  OBSERVATION_FIELD_TABLE,
  mapHostEventToRuntimeEvent,
  toPanelDisplayRow,
  pickEvidenceObservationFields,
  SWITCHBOARD_OBSERVATION_EVENTS,
} from "../index.js";

describe("WP-13 observation", () => {
  let persistDir = "";
  let paths!: SwitchboardPaths;

  before(async () => {
    persistDir = join(
      tmpdir(),
      `wp13-obs-${Date.now()}-${Math.random().toString(16).slice(2)}`,
    );
    await mkdir(persistDir, { recursive: true });
    paths = new SwitchboardPaths({ persistDir });
  });

  after(async () => {
    await rm(persistDir, { recursive: true, force: true });
  });

  it("maps known switchboard events and tolerates unknown HostEvents", () => {
    const known = mapHostEventToRuntimeEvent({
      event_type: "host.run.started",
      payload: { runId: "r1" },
    });
    assert.equal(known.switchboard, true);
    assert.equal(known.known, true);
    assert.equal(toPanelDisplayRow(known).unknown, false);

    const unknown = mapHostEventToRuntimeEvent({
      event_type: "host.future.weird_event",
      payload: { x: 1 },
    });
    assert.equal(unknown.known, false);
    const row = toPanelDisplayRow(unknown);
    assert.equal(row.unknown, true);
    assert.match(row.label, /^unknown:/);
  });

  it("picks optional evidence observation fields without inventing", () => {
    const picked = pickEvidenceObservationFields({
      host_id: "host-local",
      adapter_kind: "cursor",
      noise: 1,
    });
    assert.deepEqual(picked, {
      host_id: "host-local",
      adapter_kind: "cursor",
    });
  });

  it("builds observation snapshot with Host/Binding/Run/Delivery counts", async () => {
    const box = new DoorbellMailbox(paths);
    const msg: DoorbellMessage = {
      schema: "codeflowmu.doorbell/v1",
      doorbellId: "db-obs-1",
      recipientWorkerId: "DEV-01",
      topic: "task.ready",
      sourceFactRefs: ["TASK-1"],
      summary: "obs",
      priority: "P1",
      dedupeKey: "dk-obs-1",
      createdAt: "2026-08-05T12:00:00.000Z",
    };
    await box.enqueue(msg);
    await box.enqueue({
      ...msg,
      doorbellId: "db-obs-fail",
      dedupeKey: "dk-obs-fail",
    });
    await box.fail("DEV-01", "db-obs-fail");

    const bindings = new WorkerBindingStore(paths);
    const rev: WorkerBindingRevision = {
      schema: "codeflowmu.worker-binding/v1",
      bindingId: "bind-obs",
      revision: 1,
      workerId: "DEV-01",
      host: { hostId: "host-local", externalSessionId: "sess-1" },
      state: "ready",
      createdAt: "2026-08-05T12:00:00.000Z",
      createdBy: "test",
    };
    await bindings.append(rev);

    const runs = new RunStore(paths);
    const run: RunRecord = {
      schema: "codeflowmu.run/v1",
      runId: "run-obs-1",
      workerId: "DEV-01",
      doorbellId: "db-obs-1",
      bindingId: "bind-obs",
      hostId: "host-local",
      deliveryAttemptId: "att-1",
      state: "delivery_unknown",
      sourceFactRefs: ["TASK-1"],
      continuationMode: "new_session_from_files",
      settledAt: "2026-08-05T12:01:00.000Z",
    };
    await runs.put(run);

    const snap = await new ObservationSnapshotBuilder().build({
      paths,
      workerIds: ["DEV-01"],
      instanceId: "inst-test",
      runtimeRole: "Runtime",
      registryRoot: ".codeflowmu/registry",
      dataRoot: ".codeflowmu/state",
      fcopRoot: "fcop",
      writerLock: { held: false },
      gateway: { status: "up" },
      isolationAlerts: [],
    });

    assert.equal(snap.schema, "codeflowmu.observation-snapshot/v1");
    assert.equal(snap.productionActiveEnabled, false);
    assert.equal(snap.instanceId, "inst-test");
    const w = snap.workers[0]!;
    assert.equal(w.hostId, "host-local");
    assert.equal(w.bindingId, "bind-obs");
    assert.equal(w.hostSessionOk, true);
    assert.equal(w.pendingDoorbells, 1);
    assert.equal(w.failedDoorbells, 1);
    assert.equal(w.deliveryUnknownRuns, 1);
    assert.equal(w.continuityMode, "new_session_from_files");
    assert.ok(OBSERVATION_FIELD_TABLE.length >= 10);
    assert.ok(SWITCHBOARD_OBSERVATION_EVENTS.includes("host.run.started"));
  });
});
