/**
 * Component: Client-Side JWT Utilities
 * Documentation: documentation/frontend/routing-auth.md
 */

import { RMABLogger } from './logger';

const logger = RMABLogger.create('JWTClient');

interface JWTPayload {
  sub: string;
  plexId: string;
  username: string;
  role: string;
  iat: number;
  exp: number;
}

/**
 * Decode JWT without verification (client-side only)
 * Note: This does NOT verify the signature - only use for reading claims
 */
export function decodeJWT(token: string): JWTPayload | null {
  try {
    const parts = token.split('.');
    if (parts.length !== 3) {
      return null;
    }

    const payload = parts[1];
    const decoded = JSON.parse(atob(payload.replace(/-/g, '+').replace(/_/g, '/')));
    return decoded as JWTPayload;
  } catch (error) {
    logger.error('Failed to decode JWT', { error: error instanceof Error ? error.message : String(error) });
    return null;
  }
}

/**
 * Check if token is expired
 */
export function isTokenExpired(token: string): boolean {
  const decoded = decodeJWT(token);
  if (!decoded || !decoded.exp) {
    return true;
  }

  const now = Math.floor(Date.now() / 1000);
  return decoded.exp < now;
}

/**
 * Get milliseconds until token expires
 */
export function getTokenExpiryMs(token: string): number | null {
  const decoded = decodeJWT(token);
  if (!decoded || !decoded.exp) {
    return null;
  }

  const now = Math.floor(Date.now() / 1000);
  const expiresIn = decoded.exp - now;
  return expiresIn > 0 ? expiresIn * 1000 : 0;
}

/**
 * Get milliseconds until token should be refreshed (5 mins before expiry)
 */
export function getRefreshTimeMs(token: string): number | null {
  const expiryMs = getTokenExpiryMs(token);
  if (expiryMs === null) {
    return null;
  }

  const REFRESH_BUFFER_MS = 5 * 60 * 1000; // 5 minutes
  const refreshTime = expiryMs - REFRESH_BUFFER_MS;
  return refreshTime > 0 ? refreshTime : 0;
}
