/** Authenticated, POST-body-only office WebRTC signaling routes. */

import type { FastifyInstance, FastifyReply } from "fastify";
import { parseScreenShareClientMessage } from "../../../src/media/signalingValidation.ts";
import { parseIceConfigRequest } from "../../../src/media/iceValidation.ts";
import type {
  ScreenShareBinding,
  ScreenShareCreateRequest,
  ScreenShareJoinRequest,
  ScreenShareResumeRequest,
  ScreenShareRevokeRequest,
  ScreenShareSignalRequest,
  ScreenShareStopRequest,
} from "../../../src/media/signalingTypes.ts";
import { bundledOffice, officeHasMediaBinding, type MediaSignalFailureCode } from "../media/index.ts";
import type { Services } from "../services.ts";

const BODY_LIMIT = 32 * 1024;
const REVALIDATE_MS = 15_000;
const UNAUTHORIZED = { error: "unauthorized", message: "Media signaling requires a signed-in member." };

function status(code: MediaSignalFailureCode): number {
  if (code === "unauthorized" || code === "expired") return 401;
  if (code === "conflict") return 409;
  if (code === "capacity" || code === "rate-limited") return 429;
  return 400;
}

function fail(reply: FastifyReply, failure: { code: MediaSignalFailureCode; message: string }) {
  const code = status(failure.code);
  if (code === 401) reply.header("www-authenticate", "Bearer");
  return reply.code(code).send({ error: failure.code, message: failure.message });
}

async function bindingAllowed(binding: ScreenShareBinding, services: Services): Promise<boolean> {
  const doc = await services.offices.get(binding.officeId);
  const office = doc?.floor ?? bundledOffice(binding.officeId);
  return office !== null && officeHasMediaBinding(office, binding);
}

function parse(body: unknown) {
  const parsed = parseScreenShareClientMessage(body);
  return parsed.ok ? parsed.value : null;
}

export function registerMedia(app: FastifyInstance, services: Services): void {
  app.post<{ Body: unknown }>("/api/v1/media/ice", { bodyLimit: 1_024 }, async (req, reply) => {
    const viewer = await services.auth.resolve(req);
    if (!viewer.authenticated || viewer.subject === null) {
      return reply.code(401).header("www-authenticate", "Bearer").send(UNAUTHORIZED);
    }
    const parsed = parseIceConfigRequest(req.body);
    if (!parsed.ok) return reply.code(400).send({ error: "invalid", message: "ICE configuration request is invalid." });
    if (!(await bindingAllowed(parsed.value.binding, services))) {
      return reply.code(404).send({ error: "not_found", message: "No such authored office screen." });
    }
    const authorization = services.media.authorizeIce(
      parsed.value.credential,
      parsed.value.binding,
      viewer.subject,
    );
    if (!authorization.ok) return fail(reply, authorization);
    // The provider immediately replaces these with separate keyed digests and
    // retains neither the stable auth subject nor trusted proxy address.
    const issued = services.ice.issue(parsed.value, {
      subject: viewer.subject,
      trustedIp: req.ip,
    }, authorization.value.expiresAtMs);
    if (!issued.ok) {
      const statusCode = issued.code === "rate-limited" ? 429 : 503;
      return reply.code(statusCode)
        .header("retry-after", String(Math.ceil(issued.value.retryAfterMs / 1_000)))
        .send(issued.value);
    }
    return reply.code(200).header("pragma", "no-cache").send(issued.value);
  });

  app.post<{ Body: unknown }>("/api/v1/media/join", { bodyLimit: BODY_LIMIT }, async (req, reply) => {
    const viewer = await services.auth.resolve(req);
    if (!viewer.authenticated || viewer.subject === null) {
      return reply.code(401).header("www-authenticate", "Bearer").send(UNAUTHORIZED);
    }
    const message = parse(req.body);
    if (!message || (message.type !== "screen-share-create-request" && message.type !== "screen-share-join-request")) {
      return reply.code(400).send({ error: "invalid", message: "Media join request is invalid." });
    }
    // Authentication precedes lookup so anonymous callers cannot enumerate private packs.
    if (!(await bindingAllowed(message.binding, services))) {
      return reply.code(404).send({ error: "not_found", message: "No such authored office screen." });
    }
    const joined = services.media.join(message as ScreenShareCreateRequest | ScreenShareJoinRequest, viewer.subject);
    if (!joined.ok) return fail(reply, joined);
    return reply.code(201).send(joined.value);
  });

  app.post<{ Body: unknown }>("/api/v1/media/signal", { bodyLimit: BODY_LIMIT }, async (req, reply) => {
    const viewer = await services.auth.resolve(req);
    if (!viewer.authenticated || viewer.subject === null) {
      return reply.code(401).header("www-authenticate", "Bearer").send(UNAUTHORIZED);
    }
    const message = parse(req.body);
    if (!message || message.type !== "screen-share-signal-request") {
      return reply.code(400).send({ error: "invalid", message: "Media signal request is invalid." });
    }
    if (!(await bindingAllowed(message.binding, services))) {
      return reply.code(404).send({ error: "not_found", message: "No such authored office screen." });
    }
    const signaled = services.media.signal(message as ScreenShareSignalRequest, viewer.subject);
    if (!signaled.ok) return fail(reply, signaled);
    return reply.code(204).send();
  });

  app.post<{ Body: unknown }>("/api/v1/media/events", { bodyLimit: BODY_LIMIT }, async (req, reply) => {
    const viewer = await services.auth.resolve(req);
    if (!viewer.authenticated || viewer.subject === null) {
      return reply.code(401).header("www-authenticate", "Bearer").send(UNAUTHORIZED);
    }
    const subject = viewer.subject;
    const message = parse(req.body);
    if (!message || message.type !== "screen-share-resume-request") {
      return reply.code(400).send({ error: "invalid", message: "Media resume request is invalid." });
    }
    if (!(await bindingAllowed(message.binding, services))) {
      return reply.code(404).send({ error: "not_found", message: "No such authored office screen." });
    }
    const resumed = services.media.resume(message as ScreenShareResumeRequest, subject);
    if (!resumed.ok) return fail(reply, resumed);

    reply.hijack();
    reply.raw.writeHead(200, {
      "cache-control": "private, no-store",
      connection: "keep-alive",
      "content-type": "text/event-stream; charset=utf-8",
      "x-accel-buffering": "no",
    });
    const write = (value: unknown) => reply.raw.write(`data: ${JSON.stringify(value)}\n\n`);
    write(resumed.value);
    const activeCredential = resumed.value.grant.credential;
    const subscribed = services.media.subscribe(activeCredential, subject, write);
    if (!subscribed.ok) { reply.raw.end(); return; }
    const interval = setInterval(() => {
      // Re-resolve the caller, rather than treating the identity result from
      // stream-open as permanent. This bounds issuer revocation and JWT expiry
      // even while WebRTC itself continues peer-to-peer.
      void services.auth.resolve(req).then((current) => {
        if (!current.authenticated || current.subject !== subject) {
          reply.raw.end();
          return;
        }
        const valid = services.media.revalidate(activeCredential, subject);
        if (!valid.ok) reply.raw.end();
        else reply.raw.write(": keepalive\n\n");
      }).catch(() => reply.raw.end());
    }, REVALIDATE_MS);
    interval.unref();
    // The POST request body closes as soon as it is parsed; the response owns
    // the fetch-streamed SSE lifetime.
    reply.raw.once("close", () => { clearInterval(interval); subscribed.value(); });
  });

  app.post<{ Body: unknown }>("/api/v1/media/leave", { bodyLimit: BODY_LIMIT }, async (req, reply) => {
    const viewer = await services.auth.resolve(req);
    if (!viewer.authenticated || viewer.subject === null) {
      return reply.code(401).header("www-authenticate", "Bearer").send(UNAUTHORIZED);
    }
    const message = parse(req.body);
    if (!message || (message.type !== "screen-share-stop-request" && message.type !== "screen-share-revoke-request")) {
      return reply.code(400).send({ error: "invalid", message: "Media leave request is invalid." });
    }
    if (!(await bindingAllowed(message.binding, services))) {
      return reply.code(404).send({ error: "not_found", message: "No such authored office screen." });
    }
    const left = services.media.leave(message as ScreenShareStopRequest | ScreenShareRevokeRequest, viewer.subject, viewer.admin);
    if (!left.ok) return fail(reply, left);
    return reply.code(204).send();
  });
}
