import { describe, expect, it } from "vitest";
import type { WorkerLike } from "./WorkerSupervisor";
import {
  StartupBufferedWorker,
  workerStartupReady,
} from "./StartupBufferedWorker";

class FakeWorker implements WorkerLike {
  onmessage: ((event: MessageEvent<unknown>) => void) | null = null;
  onerror: ((event: ErrorEvent) => void) | null = null;
  onmessageerror: ((event: MessageEvent<unknown>) => void) | null = null;
  readonly messages: unknown[] = [];
  terminated = false;

  postMessage(message: unknown): void {
    this.messages.push(message);
  }

  terminate(): void {
    this.terminated = true;
  }

  emit(message: unknown): void {
    this.onmessage?.({ data: message } as MessageEvent<unknown>);
  }
}

describe("startup-buffered worker", () => {
  it("flushes held requests once and forwards later traffic", () => {
    const underlying = new FakeWorker();
    const worker = new StartupBufferedWorker(underlying);
    const responses: unknown[] = [];
    worker.onmessage = (event) => responses.push(event.data);

    worker.postMessage("first");
    worker.postMessage("second");
    expect(underlying.messages).toEqual([]);

    underlying.emit(workerStartupReady());
    expect(underlying.messages).toEqual(["first", "second"]);

    worker.postMessage("third");
    underlying.emit({ response: true });
    expect(underlying.messages).toEqual(["first", "second", "third"]);
    expect(responses).toEqual([{ response: true }]);
  });

  it("drops held requests when terminated before readiness", () => {
    const underlying = new FakeWorker();
    const worker = new StartupBufferedWorker(underlying);
    worker.postMessage("never sent");
    worker.terminate();
    underlying.emit(workerStartupReady());

    expect(underlying.messages).toEqual([]);
    expect(underlying.terminated).toBe(true);
  });
});
