import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import { after, before, test } from "node:test";

import { createServer } from "vite";

let server;
let guard;

before(async () => {
  server = await createServer({
    appType: "custom",
    logLevel: "silent",
    server: { middlewareMode: true },
  });
  guard = await server.ssrLoadModule("/src/core/runtime/acquisitionGuard.ts");
});

after(async () => {
  await server?.close();
});

function runtimeState(acquisitionState, cleanupPending = false) {
  return {
    phase: "idle",
    sourceMode: "idle",
    acquisition: acquisitionState === null
      ? null
      : {
          acquisitionId: "acq-1",
          deviceId: "device-1",
          deviceSessionId: "device-session-1",
          compatibilityProfileId: "profile-1",
          controlMode: "operator-manual",
          state: acquisitionState,
          stateRevision: 1,
          operatorInstructions: [],
          cleanupPending,
        },
  };
}

test("every nonterminal acquisition phase blocks saved and manual source replacement", () => {
  for (const state of [
    "preparing",
    "prepared",
    "awaiting_external_start",
    "starting",
    "acquiring",
    "awaiting_external_stop",
    "stopping",
    "finalizing",
  ]) {
    assert.equal(guard.isSpatialSourceSwitchBlocked(runtimeState(state)), true, state);
  }
});

test("terminal or absent acquisitions allow an explicit source selection", () => {
  for (const state of ["completed", "failed", "aborted", "interrupted"]) {
    assert.equal(guard.isSpatialSourceSwitchBlocked(runtimeState(state)), false, state);
  }
  assert.equal(guard.isSpatialSourceSwitchBlocked(runtimeState(null)), false);
  assert.equal(guard.isSpatialSourceSwitchBlocked(null), false);
});

test("an unknown acquisition state fails closed", () => {
  assert.equal(
    guard.isSpatialSourceSwitchBlocked(runtimeState("future_vendor_phase")),
    true,
  );
  assert.match(guard.SPATIAL_SOURCE_SWITCH_BLOCKED_REASON, /Завершите текущий приём/);
});

test("terminal acquisition with retained cleanup remains source-switch blocked", () => {
  assert.equal(guard.isSpatialSourceSwitchBlocked(runtimeState("failed", true)), true);
  assert.equal(guard.isSpatialSourceSwitchBlocked(runtimeState("failed", false)), false);
});

test("saved-session and manual source controls share the acquisition guard", async () => {
  const appSource = await readFile(new URL("../src/App.tsx", import.meta.url), "utf8");
  const sessionSelectSource = await readFile(
    new URL("../src/components/ObservationSessionSelect.tsx", import.meta.url),
    "utf8",
  );
  const observationHookSource = await readFile(
    new URL("../src/core/observation/useObservationSessions.ts", import.meta.url),
    "utf8",
  );

  assert.match(appSource, /blockedReason=\{sourceSwitchBlockedReason\}/);
  assert.match(appSource, /disabled=\{sourceSwitchBlocked \|\| !sourceDraft\.trim\(\)\}/);
  assert.match(appSource, /if \(sourceSwitchBlockedRef\.current\) return;/);
  assert.match(sessionSelectSource, /replayEnabled: blockedReason === null/);
  assert.match(observationHookSource, /!replayEnabledRef\.current/);
});
