import { SignJWT } from 'jose'

// dezky Meet (Jitsi-backed) room URL builder.
//
// Every booking with a video location gets a room name that is stable for the
// life of that booking (callers pass in a per-booking room id). When a JWT
// secret is configured we mint a short-lived HS256 token that authorizes the
// caller to join *that specific room*, which lets a locked-down dezky Meet
// deployment reject anonymous joins. Without a secret we fall back to a plain
// public room URL — exactly the previous behaviour — so this is purely additive.

export interface MeetJwtConfig {
  // Shared HS256 secret (Jitsi `app_secret`). When absent, no token is minted.
  jwtSecret?: string
  // Jitsi `app_id` — the JWT `iss`/`aud`. Required for a valid token.
  appId?: string
  // Meet hostname, e.g. "meet.dezky.local". Defaults applied by the caller.
  domain: string
}

// How long a minted join token stays valid. Generous so a confirmation email
// link still works a while after booking; the room itself is still gated.
const TOKEN_TTL_SECONDS = 60 * 60 * 24 * 7 // 7 days

// True when we have everything needed to mint an authorizing token.
export function meetJwtEnabled(cfg: MeetJwtConfig): boolean {
  return !!cfg.jwtSecret && !!cfg.appId
}

// Builds the dezky Meet room URL for a booking. When JWT is enabled the URL
// carries a `?jwt=` token authorizing exactly `room`; otherwise a plain URL.
// `room` MUST be stable per booking so the link keeps working.
export async function buildMeetUrl(cfg: MeetJwtConfig, room: string): Promise<string> {
  const base = `https://${cfg.domain}/${room}`
  if (!meetJwtEnabled(cfg)) return base
  const token = await mintMeetJwt(cfg, room)
  return `${base}?jwt=${token}`
}

// Mints a Jitsi-compatible HS256 JWT scoped to a single room. The `room` claim
// restricts the token to that room only; `*` would authorize any room, which we
// deliberately avoid.
async function mintMeetJwt(cfg: MeetJwtConfig, room: string): Promise<string> {
  const key = new TextEncoder().encode(cfg.jwtSecret!)
  const nowSeconds = Math.floor(Date.now() / 1000)
  return new SignJWT({ room })
    .setProtectedHeader({ alg: 'HS256', typ: 'JWT' })
    .setIssuer(cfg.appId!)
    .setAudience(cfg.appId!)
    .setSubject(cfg.domain)
    .setIssuedAt(nowSeconds)
    .setExpirationTime(nowSeconds + TOKEN_TTL_SECONDS)
    .sign(key)
}
