/**
 * TokenStorage - Service de gestion du stockage des tokens
 * T0169: Service simple pour stocker, récupérer et supprimer les tokens d'authentification
 *
 * SECURITY: Migration vers cookies httpOnly COMPLÉTÉE
 * - Access Token: Stocké en mémoire uniquement (pas de localStorage)
 * - Refresh Token: Stocké dans un cookie httpOnly par le backend (pas accessible via JavaScript)
 *
 * IMPORTANT: Le backend sette maintenant des cookies httpOnly pour le refresh token.
 * Le système détecte automatiquement les cookies httpOnly et réduit l'utilisation de localStorage.
 *
 * NOTE: Mode hybride maintenu pour compatibilité :
 * - Le backend sette des cookies httpOnly (priorité)
 * - localStorage est utilisé uniquement comme fallback pour compatibilité legacy
 * - L'access token reste en mémoire uniquement (protection XSS)
 */

const ACCESS_TOKEN_KEY = 'veza_access_token';
const REFRESH_TOKEN_KEY = 'veza_refresh_token';

// SECURITY: Stockage en mémoire pour l'access token (plus sécurisé que localStorage)
let accessTokenMemory: string | null = null;

// CRITIQUE FIX #17: Flag pour indiquer si on utilise les cookies httpOnly (détecté automatiquement)
// Le backend sette maintenant des cookies httpOnly, donc ce flag devrait être true après le premier login
let useHttpOnlyCookies = false;

/**
 * CRITIQUE FIX #17: Détecte si le backend utilise des cookies httpOnly
 * Vérifie si le refresh token est disponible via cookie (non accessible via JS)
 * @returns true si les cookies httpOnly sont utilisés
 */
function detectHttpOnlyCookies(): boolean {
  // Si on a un access token mais pas de refresh token dans localStorage,
  // c'est qu'on utilise des cookies httpOnly
  const hasAccessToken =
    !!accessTokenMemory || !!localStorage.getItem(ACCESS_TOKEN_KEY);
  const hasRefreshTokenInStorage = !!localStorage.getItem(REFRESH_TOKEN_KEY);

  // Si on a un access token mais pas de refresh token dans localStorage,
  // on suppose que le backend utilise des cookies httpOnly
  return hasAccessToken && !hasRefreshTokenInStorage;
}

/**
 * Réinitialise le stockage en mémoire (utile pour les tests)
 * @internal
 */
export function _resetTokenMemory(): void {
  accessTokenMemory = null;
}

/**
 * Classe TokenStorage pour gérer le stockage des tokens
 * T0169: Service de gestion du stockage tokens avec localStorage
 */
export class TokenStorage {
  /**
   * Stocke les tokens d'authentification
   * SECURITY: Access token stocké en mémoire uniquement (protection XSS)
   * Le refresh token est dans un cookie httpOnly set par le backend
   *
   * CRITIQUE FIX #17: Réduire l'utilisation de localStorage maintenant que la migration est complète
   *
   * @param accessToken - Token d'accès JWT (stocké en mémoire uniquement)
   * @param refreshToken - Token de rafraîchissement (dans cookie httpOnly, localStorage utilisé uniquement comme fallback)
   */
  static setTokens(accessToken: string, refreshToken: string): void {
    // SECURITY: Stocker l'access token en mémoire uniquement (protection XSS)
    accessTokenMemory = accessToken;

    // CRITIQUE FIX #17: Le backend sette maintenant des cookies httpOnly
    // Si refreshToken === 'cookie-based', c'est qu'on utilise des cookies httpOnly
    // Ne pas stocker dans localStorage dans ce cas
    if (refreshToken === 'cookie-based') {
      useHttpOnlyCookies = true;
      // Ne pas stocker le refresh token dans localStorage si on utilise des cookies httpOnly
      // Garder seulement l'access token en localStorage comme fallback pour compatibilité
      localStorage.setItem(ACCESS_TOKEN_KEY, accessToken);
      localStorage.removeItem(REFRESH_TOKEN_KEY); // Nettoyer localStorage si présent
      return;
    }

    // CRITIQUE FIX #17: Mode legacy - garder dans localStorage pour compatibilité
    // Ceci est un fallback pour les anciens systèmes qui n'utilisent pas encore les cookies httpOnly
    localStorage.setItem(ACCESS_TOKEN_KEY, accessToken);
    localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken);
    useHttpOnlyCookies = false;
  }

  /**
   * Récupère le token d'accès depuis la mémoire ou localStorage
   * SECURITY: Priorité à la mémoire (plus sécurisé)
   *
   * @returns Token d'accès ou null si non trouvé
   */
  static getAccessToken(): string | null {
    // SECURITY: Priorité à la mémoire (plus sécurisé)
    if (accessTokenMemory) {
      return accessTokenMemory;
    }

    // Fallback: localStorage (pour compatibilité pendant migration)
    return localStorage.getItem(ACCESS_TOKEN_KEY);
  }

  /**
   * Récupère le token de rafraîchissement depuis localStorage
   * T0169: Récupère refresh token
   *
   * CRITIQUE FIX #17: Si on utilise des cookies httpOnly, retourner null
   * car le refresh token n'est pas accessible via JavaScript
   *
   * @returns Token de rafraîchissement ou null si non trouvé ou si cookies httpOnly utilisés
   */
  static getRefreshToken(): string | null {
    // CRITIQUE FIX #17: Si on utilise des cookies httpOnly, le refresh token n'est pas dans localStorage
    if (useHttpOnlyCookies || detectHttpOnlyCookies()) {
      return null; // Le refresh token est dans un cookie httpOnly, non accessible via JS
    }
    return localStorage.getItem(REFRESH_TOKEN_KEY);
  }

  /**
   * Supprime tous les tokens (mémoire + localStorage)
   * SECURITY: Nettoie aussi la mémoire pour l'access token
   *
   * NOTE: Les cookies httpOnly seront supprimés par le backend lors du logout
   */
  static clearTokens(): void {
    // SECURITY: Nettoyer la mémoire
    accessTokenMemory = null;

    // Nettoyer localStorage (pour compatibilité pendant migration)
    localStorage.removeItem(ACCESS_TOKEN_KEY);
    localStorage.removeItem(REFRESH_TOKEN_KEY);
  }

  /**
   * Vérifie si des tokens sont présents
   * T0169: Vérifie la présence des tokens
   *
   * CRITIQUE FIX #17: Si on utilise des cookies httpOnly, vérifier seulement l'access token
   * car le refresh token n'est pas accessible via JavaScript
   *
   * @returns true si l'access token est présent (et refresh token présent si pas de cookies httpOnly), false sinon
   */
  static hasTokens(): boolean {
    const hasAccessToken = !!this.getAccessToken();

    // CRITIQUE FIX #17: Si on utilise des cookies httpOnly, le refresh token est dans le cookie
    // On considère qu'on a des tokens si on a un access token et qu'on utilise des cookies httpOnly
    if (useHttpOnlyCookies || detectHttpOnlyCookies()) {
      return hasAccessToken; // Le refresh token est dans un cookie httpOnly
    }

    // Mode legacy: vérifier les deux tokens
    return hasAccessToken && !!this.getRefreshToken();
  }
}
