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

import { createServer } from "vite";

let server;
let selectMonotonicXgridsState;

before(async () => {
  server = await createServer({
    appType: "custom",
    logLevel: "silent",
    server: { middlewareMode: true },
  });
  ({ selectMonotonicXgridsState } = await server.ssrLoadModule(
    "@xgrids-k1/frontend/stateOrdering.ts",
  ));
});

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

function snapshot(revision, generation, phase = "streaming", sessionId = "device-session-a") {
  return {
    phase: "connected",
    message: `${phase}:${revision}:${generation}`,
    device_session: sessionId === null
      ? null
      : {
          device_session_id: sessionId,
          device_id: `device-for-${sessionId}`,
          connectivity: "connected",
        },
    camera_preview: {
      phase,
      revision,
      generation,
      active_source_id: generation === null ? null : "sensor.camera.left",
      delivery: null,
    },
  };
}

test("accepts the first camera preview snapshot", () => {
  const incoming = snapshot(1, 1);
  assert.equal(selectMonotonicXgridsState(null, incoming), incoming);
});

test("rejects a lower revision even when its generation is higher", () => {
  const current = snapshot(8, 3);
  const stale = snapshot(7, 99);
  assert.equal(selectMonotonicXgridsState(current, stale), current);
});

test("uses generation only as a tie-breaker for equal revisions", () => {
  const current = snapshot(8, 3);
  const stale = snapshot(8, 2);
  const equal = snapshot(8, 3, "selected");

  assert.equal(selectMonotonicXgridsState(current, stale), current);
  assert.equal(selectMonotonicXgridsState(current, equal), equal);
});

test("accepts a newer stop revision with a null generation", () => {
  const current = snapshot(8, 3);
  const stopped = snapshot(9, null, "idle");

  assert.equal(selectMonotonicXgridsState(current, stopped), stopped);
});

test("rejects an unversioned camera snapshot after a versioned one", () => {
  const current = snapshot(8, 3);
  const stale = {
    phase: "connected",
    device_session: current.device_session,
  };

  assert.equal(selectMonotonicXgridsState(current, stale), current);
});

test("accepts revision reset when the authoritative device session changes", () => {
  const current = snapshot(18, 7, "streaming", "device-session-a");
  const nextDevice = snapshot(0, null, "idle", "device-session-b");

  assert.equal(selectMonotonicXgridsState(current, nextDevice), nextDevice);
});

test("accepts backend reset that clears and later recreates the device session", () => {
  const current = snapshot(18, 7, "streaming", "device-session-a");
  const reset = snapshot(0, null, "idle", null);
  const reconnected = snapshot(0, null, "idle", "device-session-c");

  assert.equal(selectMonotonicXgridsState(current, reset), reset);
  assert.equal(selectMonotonicXgridsState(reset, reconnected), reconnected);
});

test("rejects the entire stale atomic snapshot instead of merging unrelated fields", () => {
  const current = {
    ...snapshot(8, 3),
    metrics: { point_count: 2_500 },
  };
  const stale = {
    ...snapshot(7, 2),
    metrics: { point_count: 9_999 },
  };

  const accepted = selectMonotonicXgridsState(current, stale);
  assert.equal(accepted, current);
  assert.equal(accepted.metrics.point_count, 2_500);
});
