import { readFileSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";

/** Socket events and the membership check each one must run. */
export const SOCKET_EVENT_GATES: Record<string, string> = {
  "workspace:join": "checkWorkspaceMembership",
  "channel:join": "checkChannelMembership",
  "presence:heartbeat": "only workspaces already joined via workspace:join",
  "typing:start": "checkChannelMembership",
  "call:signal": "isCallParticipant on both ends",
  "channel:leave": "local room leave; no tenant data",
  "message:send": "sendMessage (withTenant + requireChannelMembership)",
  "read:ack": "markChannelRead (withTenant + requireChannelMembership)",
  "thread:ack": "markThreadRead (withTenant + requireChannelMembership)",
};

export const GATEWAY_HTTP_GATES: Record<string, "public" | "tenant"> = {
  "GET /health": "public",
  "GET /workspaces/:workspaceId/presence": "tenant",
};

describe("gateway isolation catalog", () => {
  it("lists every @SubscribeMessage", () => {
    const src = readFileSync(join(__dirname, "app.gateway.ts"), "utf8");
    const found = [...src.matchAll(/@SubscribeMessage\("([^"]+)"\)/g)].map((m) => m[1]!);
    expect([...new Set(found)].sort()).toEqual(Object.keys(SOCKET_EVENT_GATES).sort());
  });

  it("lists every HTTP controller route", () => {
    const health = readFileSync(join(__dirname, "health.controller.ts"), "utf8");
    const presence = readFileSync(join(__dirname, "presence.controller.ts"), "utf8");
    expect(health).toMatch(/@Controller\("health"\)/);
    expect(presence).toMatch(/@Controller\("workspaces\/:workspaceId\/presence"\)/);
    expect(presence).toMatch(/checkWorkspaceMembership/);
    expect(Object.keys(GATEWAY_HTTP_GATES).sort()).toEqual([
      "GET /health",
      "GET /workspaces/:workspaceId/presence",
    ]);
  });
});
