import { createHmac, randomUUID, timingSafeEqual } from 'node:crypto';

export const AUTH_COOKIE_NAME = process.env.WEB_AUTH_COOKIE_NAME?.trim() || 'ai_toy_session';

function authUsername() {
  return process.env.WEB_AUTH_USERNAME?.trim() || '';
}

function authPassword() {
  return process.env.WEB_AUTH_PASSWORD || '';
}

function authSecret() {
  return process.env.WEB_AUTH_SESSION_SECRET || '';
}

export function isAuthConfigured() {
  return Boolean(authUsername() && authPassword() && authSecret());
}

export function authCookieSecure() {
  const value = process.env.WEB_AUTH_COOKIE_SECURE?.trim().toLowerCase();
  if (value) return !['0', 'false', 'no'].includes(value);
  const publicUrl = process.env.PUBLIC_APP_URL || process.env.NEXT_PUBLIC_APP_URL || '';
  return publicUrl.startsWith('https://');
}

function base64UrlEncode(input: string) {
  return Buffer.from(input, 'utf-8').toString('base64url');
}

function base64UrlDecode(input: string) {
  return Buffer.from(input, 'base64url').toString('utf-8');
}

function sign(body: string) {
  return createHmac('sha256', authSecret()).update(body).digest('hex');
}

function safeCompare(a: string, b: string) {
  const left = Buffer.from(a);
  const right = Buffer.from(b);
  return left.length === right.length && timingSafeEqual(left, right);
}

export function makeAuthToken(username: string, ttlSeconds: number) {
  if (!isAuthConfigured()) throw new Error('WEB_AUTH not configured');
  const body = base64UrlEncode(JSON.stringify({
    u: username,
    exp: Math.floor(Date.now() / 1000) + ttlSeconds,
    n: randomUUID(),
  }));
  return `${body}.${sign(body)}`;
}

export function verifyAuthToken(token?: string | null): string | null {
  if (!isAuthConfigured() || !token || !token.includes('.')) return null;
  const [body, suppliedSig] = token.split('.', 2);
  if (!body || !suppliedSig || !safeCompare(sign(body), suppliedSig)) return null;

  try {
    const payload = JSON.parse(base64UrlDecode(body)) as { u?: unknown; exp?: unknown };
    const username = String(payload.u || '');
    const expiresAt = Number(payload.exp || 0);
    if (username !== authUsername() || !Number.isFinite(expiresAt)) return null;
    if (expiresAt < Math.floor(Date.now() / 1000)) return null;
    return username;
  } catch {
    return null;
  }
}

export function validateCredentials(username: string, password: string) {
  if (!isAuthConfigured()) return false;
  return safeCompare(username.trim(), authUsername()) && safeCompare(password, authPassword());
}

export function configuredUsername() {
  return authUsername();
}
