import { describe, it, expect, vi } from "vitest";
import { z } from "zod";
import { channelRoom } from "@/channel-room";
import { SocketIORealtimeBroadcaster } from "@/socket-io-realtime-broadcaster";
import { defineRealtimeChannel } from "@/realtime-channel";

const ch = defineRealtimeChannel(
  "a.b",
  z.object({ x: z.number() }).strict(),
  { scope: "public" },
);

describe("SocketIORealtimeBroadcaster", () => {
  it("emits to the channel's room with the channel name as event", async () => {
    const emit = vi.fn();
    const to = vi.fn(() => ({ emit }));
    const io = { to } as never;
    const b = new SocketIORealtimeBroadcaster(io);
    await b.broadcast(ch, { x: 1 });
    expect(to).toHaveBeenCalledWith(channelRoom("a.b"));
    expect(emit).toHaveBeenCalledWith("a.b", { x: 1 });
  });

  it("validates payload before emitting", async () => {
    const emit = vi.fn();
    const to = vi.fn(() => ({ emit }));
    const io = { to } as never;
    const b = new SocketIORealtimeBroadcaster(io);
    await expect(
      b.broadcast(ch, { x: "not a number" } as never),
    ).rejects.toThrow();
    expect(emit).not.toHaveBeenCalled();
  });
});
