/**
 * Two token audiences share one secret but never one shape:
 *  - "agent"    : issued at login, carries agent id + role.
 *  - "customer" : issued when a pre-chat form is submitted, scoped to exactly
 *                 one conversation. This is what lets a customer close the tab,
 *                 come back, and resume the same chat with full history.
 */
import jwt from 'jsonwebtoken';
import { env } from '../config/env.js';
import { unauthorized } from '../utils/errors.js';

export interface AgentClaims {
  sub: string;            // agents.id
  typ: 'agent';
  email: string;
  name: string;
  role: 'agent' | 'admin';
}

export interface CustomerClaims {
  sub: string;            // customers.id
  typ: 'customer';
  conversationId: string;
}

export type Claims = AgentClaims | CustomerClaims;

export function signAgentToken(claims: Omit<AgentClaims, 'typ'>): string {
  return jwt.sign({ ...claims, typ: 'agent' }, env.JWT_SECRET, {
    expiresIn: env.JWT_EXPIRES_IN as jwt.SignOptions['expiresIn'],
  });
}

/** Customer tokens outlive a browser session so chats survive a refresh. */
export function signCustomerToken(claims: Omit<CustomerClaims, 'typ'>): string {
  return jwt.sign({ ...claims, typ: 'customer' }, env.JWT_SECRET, { expiresIn: '7d' });
}

export function verifyToken(token: string): Claims {
  try {
    return jwt.verify(token, env.JWT_SECRET) as Claims;
  } catch {
    throw unauthorized('Invalid or expired token');
  }
}

export function verifyAgentToken(token: string): AgentClaims {
  const claims = verifyToken(token);
  if (claims.typ !== 'agent') throw unauthorized('Agent token required');
  return claims;
}

export function verifyCustomerToken(token: string): CustomerClaims {
  const claims = verifyToken(token);
  if (claims.typ !== 'customer') throw unauthorized('Customer token required');
  return claims;
}
