import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
  advanceScreenShareStreamCursor,
  isScreenShareGrantActive,
  parseScreenShareClientMessage,
  parseScreenShareServerMessage,
} from "../media/signalingValidation.ts";
import type {
  ScreenShareAccessGrant,
  ScreenShareBinding,
  ScreenShareSignalRelay,
} from "../media/signalingTypes.ts";

const BINDING: ScreenShareBinding = {
  officeId: "lumbridge-hq",
  levelId: "level-1",
  roomId: "lobby",
  screenId: "lobby-monitor",
};
const CREDENTIAL = {
  sessionId: "opaque-session",
  participantId: "opaque-participant",
  role: "viewer" as const,
  grantToken: "opaque-secret-token-at-least-sixteen",
};

describe("office screen signaling protocol", () => {
  it("requires literal viewer opt-in and exact JSON keys", () => {
    const join = {
      type: "screen-share-join-request",
      protocolVersion: 1,
      sequence: 0,
      timestampMs: 1_000,
      requestId: "join-1",
      binding: BINDING,
      role: "viewer",
      viewerOptIn: true,
    };
    assert.equal(parseScreenShareClientMessage(join).ok, true);
    assert.equal(parseScreenShareClientMessage({ ...join, viewerOptIn: false }).ok, false);
    assert.equal(parseScreenShareClientMessage({ ...join, subject: "identity-leak" }).ok, false);
    assert.equal(parseScreenShareClientMessage({ ...join, locator: "https://media.invalid" }).ok, false);
  });

  it("bounds SDP, ICE and disallows self-signaling", () => {
    const request = {
      type: "screen-share-signal-request",
      protocolVersion: 1,
      sequence: 1,
      timestampMs: 1_001,
      binding: BINDING,
      credential: CREDENTIAL,
      targetParticipantId: "opaque-presenter",
      signal: { kind: "sdp", descriptionType: "answer", sdp: "v=0" },
    };
    assert.equal(parseScreenShareClientMessage(request).ok, true);
    assert.equal(parseScreenShareClientMessage({ ...request, targetParticipantId: CREDENTIAL.participantId }).ok, false);
    assert.equal(parseScreenShareClientMessage({
      ...request,
      signal: { ...request.signal, sdp: "x".repeat(24 * 1024 + 1) },
    }).ok, false);
  });

  it("accepts server-issued opaque peer snapshots but no credentials in fan-out", () => {
    const message = {
      type: "screen-share-participants",
      protocolVersion: 1,
      sequence: 3,
      timestampMs: 1_003,
      sessionId: CREDENTIAL.sessionId,
      binding: BINDING,
      participants: [{ participantId: "opaque-presenter", role: "presenter" }],
      leaseExpiresAtMs: 2_000,
    };
    assert.equal(parseScreenShareServerMessage(message).ok, true);
    assert.equal(parseScreenShareServerMessage({
      ...message,
      participants: [{ ...message.participants[0], grantToken: "leak" }],
    }).ok, false);
    assert.equal(parseScreenShareServerMessage({
      ...message,
      participants: Array.from({ length: 8 }, (_, index) => ({ participantId: `viewer-${index}`, role: "viewer" })),
    }).ok, false);
  });

  it("checks grant time windows without exposing bearer material in state", () => {
    const grant: ScreenShareAccessGrant = { credential: CREDENTIAL, issuedAtMs: 1_000, expiresAtMs: 2_000 };
    assert.equal(isScreenShareGrantActive(grant, 1_000), true);
    assert.equal(isScreenShareGrantActive(grant, 1_999), true);
    assert.equal(isScreenShareGrantActive(grant, 2_000), false);
    assert.equal(isScreenShareGrantActive(grant, 999), false);
  });

  it("advances only same-session monotonic peer messages", () => {
    const relay: ScreenShareSignalRelay = {
      type: "screen-share-signal-relay",
      protocolVersion: 1,
      sequence: 5,
      timestampMs: 1_005,
      sessionId: CREDENTIAL.sessionId,
      binding: BINDING,
      fromParticipantId: "opaque-presenter",
      targetParticipantId: CREDENTIAL.participantId,
      signal: { kind: "ice-complete" },
    };
    const first = advanceScreenShareStreamCursor(null, relay);
    assert.equal(first.ok, true);
    if (!first.ok) return;
    assert.equal(advanceScreenShareStreamCursor(first.value, relay).ok, false);
    assert.equal(advanceScreenShareStreamCursor(first.value, { ...relay, sequence: 6, sessionId: "foreign" }).ok, false);
    assert.equal(advanceScreenShareStreamCursor(first.value, { ...relay, sequence: 6, timestampMs: 1_004 }).ok, false);
    assert.equal(advanceScreenShareStreamCursor(first.value, { ...relay, sequence: 6, timestampMs: 1_006 }).ok, true);
  });
});
