/**
 * Edge 5.2: Safe Storage Utility
 * Provides safe wrappers for localStorage and sessionStorage with fallback support
 * for private browsing mode and unsupported browsers.
 *
 * In private browsing mode, localStorage may throw errors when accessed.
 * This utility handles those errors gracefully by falling back to in-memory storage.
 */

import { logger } from './logger';

/**
 * In-memory storage fallback for when localStorage/sessionStorage is unavailable
 */
class MemoryStorage implements Storage {
  private data: Map<string, string> = new Map();

  get length(): number {
    return this.data.size;
  }

  clear(): void {
    this.data.clear();
  }

  getItem(key: string): string | null {
    return this.data.get(key) || null;
  }

  key(index: number): string | null {
    const keys = Array.from(this.data.keys());
    return keys[index] || null;
  }

  removeItem(key: string): void {
    this.data.delete(key);
  }

  setItem(key: string, value: string): void {
    this.data.set(key, value);
  }
}

/**
 * Edge 5.2: Test if localStorage is available and working
 * Returns true if localStorage can be used, false otherwise
 */
function isLocalStorageAvailable(): boolean {
  if (typeof window === 'undefined') {
    return false; // SSR environment
  }

  try {
    const testKey = '__veza_storage_test__';
    localStorage.setItem(testKey, 'test');
    localStorage.removeItem(testKey);
    return true;
  } catch {
    // localStorage is not available (private browsing, quota exceeded, etc.)
    return false;
  }
}

/**
 * Edge 5.2: Test if sessionStorage is available and working
 * Returns true if sessionStorage can be used, false otherwise
 */
function isSessionStorageAvailable(): boolean {
  if (typeof window === 'undefined') {
    return false; // SSR environment
  }

  try {
    const testKey = '__veza_session_storage_test__';
    sessionStorage.setItem(testKey, 'test');
    sessionStorage.removeItem(testKey);
    return true;
  } catch {
    // sessionStorage is not available (private browsing, quota exceeded, etc.)
    return false;
  }
}

// Create fallback storage instances
const memoryLocalStorage = new MemoryStorage();
const memorySessionStorage = new MemoryStorage();

// Determine which storage to use
const localStorageAvailable = isLocalStorageAvailable();
const sessionStorageAvailable = isSessionStorageAvailable();

// Log warnings if fallback is being used
if (typeof window !== 'undefined' && !localStorageAvailable) {
  logger.warn(
    '[SafeStorage] localStorage not available, using in-memory fallback',
    {
      reason: 'private_browsing_or_quota_exceeded',
    },
  );
}

if (typeof window !== 'undefined' && !sessionStorageAvailable) {
  logger.warn(
    '[SafeStorage] sessionStorage not available, using in-memory fallback',
    {
      reason: 'private_browsing_or_quota_exceeded',
    },
  );
}

/**
 * Edge 5.2: Safe localStorage wrapper
 * Automatically falls back to in-memory storage if localStorage is unavailable
 *
 * @example
 * ```typescript
 * import { safeLocalStorage } from '@/utils/safeStorage';
 *
 * // Use like regular localStorage
 * safeLocalStorage.setItem('key', 'value');
 * const value = safeLocalStorage.getItem('key');
 * safeLocalStorage.removeItem('key');
 * ```
 */
export const safeLocalStorage: Storage = localStorageAvailable
  ? window.localStorage
  : memoryLocalStorage;

/**
 * Edge 5.2: Safe sessionStorage wrapper
 * Automatically falls back to in-memory storage if sessionStorage is unavailable
 *
 * @example
 * ```typescript
 * import { safeSessionStorage } from '@/utils/safeStorage';
 *
 * // Use like regular sessionStorage
 * safeSessionStorage.setItem('key', 'value');
 * const value = safeSessionStorage.getItem('key');
 * safeSessionStorage.removeItem('key');
 * ```
 */
export const safeSessionStorage: Storage = sessionStorageAvailable
  ? window.sessionStorage
  : memorySessionStorage;

/**
 * Edge 5.2: Check if localStorage is available (not using fallback)
 */
export function isLocalStorageSupported(): boolean {
  return localStorageAvailable;
}

/**
 * Edge 5.2: Check if sessionStorage is available (not using fallback)
 */
export function isSessionStorageSupported(): boolean {
  return sessionStorageAvailable;
}
