/**
 * Safe localStorage wrapper with proper error handling and validation
 * 
 * Handles:
 * - Private browsing mode (localStorage unavailable)
 * - Storage quota exceeded
 * - JSON parse errors
 * - Cross-origin restrictions
 */

import { logger } from './logger';

export class LocalStorageError extends Error {
  constructor(message: string, public readonly cause?: Error) {
    super(message);
    this.name = 'LocalStorageError';
  }
}

/**
 * Check if localStorage is available
 */
export function isLocalStorageAvailable(): boolean {
  try {
    const testKey = '__localStorage_test__';
    localStorage.setItem(testKey, 'test');
    localStorage.removeItem(testKey);
    return true;
  } catch {
    return false;
  }
}

/**
 * Safely get an item from localStorage
 */
export function getItem(key: string): string | null {
  try {
    if (!isLocalStorageAvailable()) {
      return null;
    }
    return localStorage.getItem(key);
  } catch (error) {
    logger.warn(`Failed to get localStorage item: ${key}`, { error });
    return null;
  }
}

/**
 * Safely set an item in localStorage
 */
export function setItem(key: string, value: string): boolean {
  try {
    if (!isLocalStorageAvailable()) {
      return false;
    }
    localStorage.setItem(key, value);
    return true;
  } catch (error) {
    if (error instanceof Error && error.name === 'QuotaExceededError') {
      logger.warn('localStorage quota exceeded', { key });
    } else {
      logger.warn(`Failed to set localStorage item: ${key}`, { error });
    }
    return false;
  }
}

/**
 * Safely remove an item from localStorage
 */
export function removeItem(key: string): boolean {
  try {
    if (!isLocalStorageAvailable()) {
      return false;
    }
    localStorage.removeItem(key);
    return true;
  } catch (error) {
    logger.warn(`Failed to remove localStorage item: ${key}`, { error });
    return false;
  }
}

/**
 * Safely clear all localStorage
 */
export function clear(): boolean {
  try {
    if (!isLocalStorageAvailable()) {
      return false;
    }
    localStorage.clear();
    return true;
  } catch (error) {
    logger.warn('Failed to clear localStorage', { error });
    return false;
  }
}

/**
 * Get and parse a JSON object from localStorage
 */
export function getJSON<T>(key: string, defaultValue: T): T {
  try {
    const item = getItem(key);
    if (!item) {
      return defaultValue;
    }
    
    const parsed = JSON.parse(item);
    return parsed as T;
  } catch (error) {
    logger.warn(`Failed to parse localStorage JSON for key: ${key}`, { error });
    // Remove corrupted data
    removeItem(key);
    return defaultValue;
  }
}

/**
 * Stringify and set a JSON object in localStorage
 */
export function setJSON<T>(key: string, value: T): boolean {
  try {
    const serialized = JSON.stringify(value);
    return setItem(key, serialized);
  } catch (error) {
    logger.warn(`Failed to stringify localStorage JSON for key: ${key}`, { error });
    return false;
  }
}

/**
 * Check if a key exists in localStorage
 */
export function hasItem(key: string): boolean {
  return getItem(key) !== null;
}

/**
 * Get multiple items at once
 */
export function getItems(keys: string[]): Record<string, string | null> {
  const result: Record<string, string | null> = {};
  for (const key of keys) {
    result[key] = getItem(key);
  }
  return result;
}

/**
 * Set multiple items at once
 */
export function setItems(items: Record<string, string>): boolean {
  let allSuccessful = true;
  for (const [key, value] of Object.entries(items)) {
    if (!setItem(key, value)) {
      allSuccessful = false;
    }
  }
  return allSuccessful;
}

/**
 * Remove multiple items at once
 */
export function removeItems(keys: string[]): boolean {
  let allSuccessful = true;
  for (const key of keys) {
    if (!removeItem(key)) {
      allSuccessful = false;
    }
  }
  return allSuccessful;
}
