import { hmacSha256Hex, timingSafeEqualHex } from './crypto.js';

// Ticket format (base64url JSON + '.' + hex hmac)
// payload: { userId, username, exp, iat }

function base64UrlDecode(str) {
  str = str.replace(/-/g, '+').replace(/_/g, '/');
  while (str.length % 4) str += '=';
  return Buffer.from(str, 'base64').toString('utf8');
}

export function verifyTicket(sharedSecret, ticket) {
  if (typeof ticket !== 'string') return { ok: false, error: 'invalid_ticket' };
  const parts = ticket.split('.');
  if (parts.length !== 2) return { ok: false, error: 'invalid_ticket_format' };
  const [payloadB64, sigHex] = parts;

  const expected = hmacSha256Hex(sharedSecret, payloadB64);
  if (!timingSafeEqualHex(expected, sigHex)) return { ok: false, error: 'invalid_ticket_signature' };

  let payload;
  try {
    payload = JSON.parse(base64UrlDecode(payloadB64));
  } catch {
    return { ok: false, error: 'invalid_ticket_payload' };
  }

  const now = Math.floor(Date.now() / 1000);
  if (!payload?.userId || !payload?.exp) return { ok: false, error: 'invalid_ticket_fields' };
  if (payload.exp < now) return { ok: false, error: 'ticket_expired' };

  if (typeof payload.username !== 'string') {
    return { ok: false, error: 'missing_username' };
  }

  const normalizedUsername = payload.username.trim();
  if (!normalizedUsername) {
    return { ok: false, error: 'missing_username' };
  }

  if (normalizedUsername.length > 32 || /[\x00-\x1F\x7F]/.test(normalizedUsername)) {
    return { ok: false, error: 'invalid_username' };
  }

  payload.username = normalizedUsername;

  return { ok: true, payload };
}
