/**
 * Socket tokens the web app mints for the game server (same AUTH_SECRET, HS256):
 *  - TV links: display-only, revoked by bumping Room.tvTokenVersion
 *  - host tokens: short-lived, for a signed-in venue user controlling their venue's events
 * Guest tokens are minted by the game server itself when a player joins.
 * Server-only: import from server components, route handlers and server actions.
 */
import { SignJWT } from 'jose';
import { JWT_AUDIENCE, JWT_ISSUER, TOKEN_TTL, type HostClaims, type TvClaims } from '@pintrush/protocol';
import { formSecret } from '../server-env';

function key(): Uint8Array {
  return new TextEncoder().encode(formSecret());
}

/** Display-only token for a room's TV. No expiry: revoke by bumping the room's tvTokenVersion. */
export async function signTvToken(claims: Omit<TvClaims, 'scope'>): Promise<string> {
  return new SignJWT({ ...claims, scope: 'tv' })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuer(JWT_ISSUER)
    .setAudience(JWT_AUDIENCE)
    .setIssuedAt()
    .sign(key());
}

/** Host control token (12 h). `sub` is the venue user's id (or a platform admin acting for the venue). */
export async function signHostToken(claims: Omit<HostClaims, 'scope'>): Promise<string> {
  const iat = Math.floor(Date.now() / 1000);
  return new SignJWT({ ...claims, scope: 'host' })
    .setProtectedHeader({ alg: 'HS256' })
    .setIssuer(JWT_ISSUER)
    .setAudience(JWT_AUDIENCE)
    .setIssuedAt(iat)
    .setExpirationTime(iat + TOKEN_TTL.hostSeconds)
    .setSubject(claims.sub)
    .sign(key());
}

/** Absolute TV URL for a room, e.g. https://pintrush.com/tv/<roomId>?t=<token>. */
export async function tvUrl(siteUrl: string, room: { id: string; venueId: string; tvTokenVersion: number }): Promise<string> {
  const token = await signTvToken({ roomId: room.id, venueId: room.venueId, v: room.tvTokenVersion });
  return `${siteUrl.replace(/\/$/, '')}/tv/${room.id}?t=${encodeURIComponent(token)}`;
}

/** The URL a QR code on a TV/poster points at: /join/<CODE>?room=<roomId>. */
export function joinUrl(siteUrl: string, joinCode: string, roomId?: string): string {
  const base = `${siteUrl.replace(/\/$/, '')}/join/${encodeURIComponent(joinCode)}`;
  return roomId ? `${base}?room=${roomId}` : base;
}
