// Edge-safe JWT payload decoding. We never verify the signature here — these helpers
// only read claims from our own httpOnly cookie (presence/expiry for route guards).
// The gateway verifies the signature on every real API call.

export interface JwtClaims {
  sub?: string;
  email?: string;
  tenant_id?: string;
  tenant_slug?: string;
  is_admin?: string | boolean;
  is_tenant_admin?: string | boolean;
  exp?: number;
  [key: string]: unknown;
}

function base64UrlDecode(input: string): string {
  const b64 = input.replace(/-/g, "+").replace(/_/g, "/");
  const pad = b64.length % 4 === 0 ? "" : "=".repeat(4 - (b64.length % 4));
  const raw =
    typeof atob === "function"
      ? atob(b64 + pad)
      : Buffer.from(b64 + pad, "base64").toString("binary");
  // Reinterpret the binary string as UTF-8 so non-ASCII claims (names) survive.
  return decodeURIComponent(
    raw
      .split("")
      .map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2))
      .join("")
  );
}

export function decodeJwt(token: string): JwtClaims | null {
  try {
    const part = token.split(".")[1];
    if (!part) return null;
    return JSON.parse(base64UrlDecode(part)) as JwtClaims;
  } catch {
    return null;
  }
}

/** True when the token is missing an exp or is at/past expiry. */
export function isJwtExpired(claims: JwtClaims | null): boolean {
  if (!claims?.exp) return true;
  return claims.exp * 1000 <= Date.now();
}
