import { test, expect } from "bun:test";
import {
  createRealtimeRegistry,
  bridgeRealtime,
  defineRoom,
  type RawSocket,
} from "../src/index.ts";
import { createPubSub } from "../../pubsub/src/index.ts";

/** A fake socket that records what the server sends to it. */
function fakeSocket(): RawSocket & { received: string[] } {
  const received: string[] = [];
  return { received, send: (d: string) => received.push(d), close: () => {} };
}

test("bridgeRealtime: a room broadcast on one registry reaches connections on another", async () => {
  // One shared bus stands in for Redis across two 'processes' (registries).
  const bus = createPubSub();

  const room = defineRoom({
    onMessage(client, msg) {
      client.room.broadcast({ echo: msg }); // everyone in the room, on every process
    },
  });

  const rA = createRealtimeRegistry();
  const rB = createRealtimeRegistry();
  bridgeRealtime(rA, bus);
  bridgeRealtime(rB, bus);

  // A client connected to registry B, in room "chat".
  const sB = fakeSocket();
  await rB.open(sB, { room: "chat", def: room });

  // A client connected to registry A triggers a broadcast.
  const sA = fakeSocket();
  await rA.open(sA, { room: "chat", def: room });
  await rA.message(sA, JSON.stringify({ hi: 1 }));

  // The broadcast crossed the bus: B's client received it even though the
  // broadcast happened on registry A.
  const gotOnB = sB.received.find((p) => p.includes("echo"));
  expect(gotOnB).toBeTruthy();
  expect(JSON.parse(gotOnB!)).toEqual({ echo: { hi: 1 } });
});

test("bridgeRealtime: no bus means broadcasts stay local", async () => {
  const room = defineRoom({
    onMessage(client, msg) {
      client.room.broadcast({ echo: msg });
    },
  });
  const rA = createRealtimeRegistry();
  const rB = createRealtimeRegistry(); // NOT bridged to A

  const sB = fakeSocket();
  await rB.open(sB, { room: "chat", def: room });
  const sA = fakeSocket();
  await rA.open(sA, { room: "chat", def: room });
  await rA.message(sA, JSON.stringify({ hi: 1 }));

  expect(sB.received.length).toBe(0); // isolated — nothing crossed
});
