/**
 * Token Manager - Handles secure token storage and retrieval
 * Supports both in-memory and httpOnly cookie storage
 */

class TokenManager {
  private inMemoryAccessToken: string | null = null;
  private readonly ACCESS_TOKEN_KEY = 'veza_access_token';
  private readonly REFRESH_TOKEN_KEY = 'veza_refresh_token';
  private readonly REMEMBER_ME_KEY = 'veza_remember_me';

  /**
   * Store tokens
   */
  setTokens(accessToken: string, refreshToken: string, rememberMe: boolean = false) {
    // Store access token in memory for quick access
    this.inMemoryAccessToken = accessToken;
    
    // CORRECTION DURABLE: Aussi stocker access_token dans localStorage pour persistance
    // Le token sera disponible après rechargement de la page
    localStorage.setItem(this.ACCESS_TOKEN_KEY, accessToken);

    // Store refresh token based on remember me preference
    if (rememberMe) {
      // Store in httpOnly cookie (would need backend to set this)
      this.setCookie(this.REFRESH_TOKEN_KEY, refreshToken, 30); // 30 days
    } else {
      // Store in session storage (browser session only)
      sessionStorage.setItem(this.REFRESH_TOKEN_KEY, refreshToken);
    }

    // Store remember me preference
    localStorage.setItem(this.REMEMBER_ME_KEY, rememberMe.toString());
  }

  /**
   * Get access token from memory or localStorage
   * CORRECTION DURABLE: Restaurer depuis localStorage si pas en mémoire
   */
  getAccessToken(): string | null {
    // Si le token est en mémoire, le retourner directement
    if (this.inMemoryAccessToken) {
      return this.inMemoryAccessToken;
    }
    
    // Sinon, essayer de le restaurer depuis localStorage (après rechargement de page)
    const storedToken = localStorage.getItem(this.ACCESS_TOKEN_KEY);
    if (storedToken) {
      this.inMemoryAccessToken = storedToken;
      return storedToken;
    }
    
    return null;
  }

  /**
   * Get refresh token
   */
  getRefreshToken(): string | null {
    // Try to get from cookie first (for remember me)
    const cookieToken = this.getCookie(this.REFRESH_TOKEN_KEY);
    if (cookieToken) {
      return cookieToken;
    }

    // Fall back to session storage
    return sessionStorage.getItem(this.REFRESH_TOKEN_KEY);
  }

  /**
   * Check if remember me is enabled
   */
  isRememberMe(): boolean {
    const rememberMe = localStorage.getItem(this.REMEMBER_ME_KEY);
    return rememberMe === 'true';
  }

  /**
   * Clear all tokens
   * CORRECTION DURABLE: Aussi nettoyer access_token de localStorage
   */
  clearTokens() {
    this.inMemoryAccessToken = null;
    localStorage.removeItem(this.ACCESS_TOKEN_KEY);
    sessionStorage.removeItem(this.REFRESH_TOKEN_KEY);
    this.deleteCookie(this.REFRESH_TOKEN_KEY);
    localStorage.removeItem(this.REMEMBER_ME_KEY);
  }

  /**
   * Check if user is authenticated
   */
  isAuthenticated(): boolean {
    return this.getAccessToken() !== null;
  }

  /**
   * Set cookie helper
   */
  private setCookie(name: string, value: string, days: number) {
    const date = new Date();
    date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
    const expires = `expires=${date.toUTCString()}`;
    document.cookie = `${name}=${value};${expires};path=/;SameSite=Lax`;
  }

  /**
   * Get cookie helper
   */
  private getCookie(name: string): string | null {
    const nameEQ = `${name  }=`;
    const ca = document.cookie.split(';');
    for (let i = 0; i < ca.length; i++) {
      let c = ca[i];
      while (c.charAt(0) === ' ') c = c.substring(1, c.length);
      if (c.indexOf(nameEQ) === 0) {
        return c.substring(nameEQ.length, c.length);
      }
    }
    return null;
  }

  /**
   * Delete cookie helper
   */
  private deleteCookie(name: string) {
    document.cookie = `${name}=;expires=Thu, 01 Jan 1970 00:00:00 UTC;path=/;`;
  }

  /**
   * Update access token (silent refresh)
   * CORRECTION DURABLE: Aussi mettre à jour dans localStorage
   */
  updateAccessToken(accessToken: string) {
    this.inMemoryAccessToken = accessToken;
    localStorage.setItem(this.ACCESS_TOKEN_KEY, accessToken);
  }
}

export const tokenManager = new TokenManager();
