import { describe, expect, it, vi } from "vitest";

import {
  createEventSyncController,
  type EventSyncDependencies,
} from "../../apps/web/src/event-sync.js";
import { isSseEvent } from "../../packages/shared-contracts/src/index.js";

function dependencies() {
  return {
    bootstrap: vi.fn(async () => undefined),
    refetchEntity: vi.fn(async () => undefined),
    refetchModels: vi.fn(async () => undefined),
  } satisfies EventSyncDependencies;
}

describe("TDD-WP0-EVT-001 REST refetch", () => {
  it("accepts only fixed non-sensitive event fields and separated versions", () => {
    expect(
      isSseEvent({
        config_set_version: 7,
        entity_ref: "models:current",
        event_id: 1,
        event_type: "model_config_changed",
        occurred_at: "2026-07-27T09:00:00.000Z",
      }),
    ).toBe(true);
    expect(
      isSseEvent({
        entity_ref: "models:runtime",
        event_id: 2,
        event_type: "model_runtime_changed",
        occurred_at: "2026-07-27T09:00:01.000Z",
        runtime_availability_version: 12,
      }),
    ).toBe(true);
    expect(
      isSseEvent({
        config_set_version: 7,
        entity_ref: "models:current",
        event_id: 3,
        event_type: "model_changed",
        occurred_at: "2026-07-27T09:00:02.000Z",
        prompt: "private body",
        runtime_availability_version: 12,
      }),
    ).toBe(false);
  });

  it("uses REST for every event and bootstraps once after a sequence gap", async () => {
    const calls = dependencies();
    const controller = createEventSyncController(calls);

    await controller.handleEvent({
      entity_ref: "projects:project-1",
      event_id: 10,
      event_type: "project_state_changed",
      occurred_at: "2026-07-27T09:00:00.000Z",
      state_version: 4,
    });
    await controller.handleEvent({
      config_set_version: 8,
      entity_ref: "models:current",
      event_id: 12,
      event_type: "model_config_changed",
      occurred_at: "2026-07-27T09:00:01.000Z",
    });

    expect(calls.refetchEntity).toHaveBeenCalledWith("projects:project-1");
    expect(calls.bootstrap).toHaveBeenCalledTimes(1);
    expect(calls.refetchModels).toHaveBeenCalledWith({
      configSetVersion: 8,
      reason: "config",
    });
  });

  it("bootstraps once per disconnect incident and never applies event payload as truth", async () => {
    const calls = dependencies();
    const controller = createEventSyncController(calls);

    await controller.handleDisconnect();
    await controller.handleDisconnect();
    expect(calls.bootstrap).toHaveBeenCalledTimes(1);

    await controller.handleEvent({
      entity_ref: "storage:local",
      event_id: 21,
      event_type: "storage_state_changed",
      occurred_at: "2026-07-27T09:00:02.000Z",
      state_version: 9,
    });
    await controller.handleDisconnect();

    expect(calls.bootstrap).toHaveBeenCalledTimes(2);
    expect(calls.refetchEntity).toHaveBeenCalledWith("storage:local");
    expect(calls.refetchEntity).not.toHaveBeenCalledWith(expect.objectContaining({ state_version: 9 }));
  });
});
