import { createHash, createHmac, timingSafeEqual } from "node:crypto";

/*
 * Quem entra na sala logado no Ktalogu. O painel (admin.ktalogu.com.br, onde
 * fica a sessão) confere quem é, assina "esta pessoa é da empresa X, nesta
 * sala, por 15 minutos" e devolve para a sala. A loja só confere a
 * assinatura: não vê a sessão do painel e não confia em nada que não venha
 * assinado. A mesma conta existe em apps/admin/src/lib/live/identidade.ts.
 */

export type Identidade = {
  sala: string;
  empresa: string;
  nome: string;
  logo: string | null;
  /* É da empresa dona da sala (com permissão): entra como quem organiza. */
  dono: boolean;
  vence: number;
};

function segredo(): Buffer | null {
  const chave = String(process.env.SUPABASE_SERVICE_ROLE_KEY || "").trim();
  return chave ? createHash("sha256").update(`ktalogu-live-identidade:${chave}`).digest() : null;
}

export function lerIdentidade(token: unknown, salaId: string, agora = Date.now()): Identidade | null {
  if (typeof token !== "string" || token.length > 2000 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]{20,64}$/.test(token)) return null;
  const chave = segredo();
  if (!chave) return null;
  const [corpo, assinatura] = token.split(".");
  const esperada = createHmac("sha256", chave).update(corpo).digest("base64url");
  const a = Buffer.from(esperada);
  const b = Buffer.from(assinatura);
  if (a.length !== b.length || !timingSafeEqual(a, b)) return null;
  let dados: Record<string, unknown>;
  try {
    dados = JSON.parse(Buffer.from(corpo, "base64url").toString("utf8")) as Record<string, unknown>;
  } catch {
    return null;
  }
  const vence = Number(dados.x);
  if (dados.s !== salaId || !Number.isFinite(vence) || vence < agora) return null;
  const empresa = typeof dados.e === "string" && /^[0-9a-f-]{36}$/i.test(dados.e) ? dados.e : null;
  const nome = typeof dados.n === "string" ? dados.n.replace(/\s+/g, " ").trim().slice(0, 60) : "";
  if (!empresa || nome.length < 2) return null;
  const logo = typeof dados.l === "string" && /^https:\/\//.test(dados.l) && dados.l.length <= 1000 ? dados.l : null;
  return { sala: salaId, empresa, nome, logo, dono: dados.d === true, vence };
}
