import type { AvatarData } from './types';

const STORAGE_PREFIX = 'aisthetix';
const AVATAR_KEY = `${STORAGE_PREFIX}-avatar`;
const VISITOR_ID_KEY = `${STORAGE_PREFIX}-visitor-id`;
const BODY_INPUTS_KEY = `${STORAGE_PREFIX}-body-inputs`;

/**
 * Written by widget versions up to 0.5.0, which kept up to ten full-resolution
 * try-on results here — several megabytes — even though nothing ever read them.
 * It filled localStorage and made saveAvatar() fail, taking the persistent-photo
 * feature down with it. Nothing writes this key any more; we only clean it up.
 */
const LEGACY_HISTORY_KEY = `${STORAGE_PREFIX}-history`;

/** Reclaim the space the old history left behind. Safe to call repeatedly. */
export function purgeLegacyHistory(): boolean {
  try {
    if (localStorage.getItem(LEGACY_HISTORY_KEY) === null) {
      return false;
    }
    localStorage.removeItem(LEGACY_HISTORY_KEY);
    return true;
  } catch {
    return false;
  }
}

// Avatar Storage
export function getAvatar(): AvatarData | null {
  try {
    const data = localStorage.getItem(AVATAR_KEY);
    if (data) {
      return JSON.parse(data);
    }
  } catch (e) {
    console.error('Error reading avatar from storage:', e);
  }
  return null;
}

export function saveAvatar(imageData: string): void {
  try {
    const avatar: AvatarData = {
      imageData,
      createdAt: new Date().toISOString(),
    };
    const serialized = JSON.stringify(avatar);

    // Estimate size (roughly 3/4 of base64 string size due to encoding overhead)
    const sizeInBytes = serialized.length * 2; // UTF-16 encoding
    const maxSize = 5 * 1024 * 1024; // 5MB limit

    if (sizeInBytes > maxSize) {
      throw new Error('Image too large to store locally (exceeds 5MB limit)');
    }

    try {
      localStorage.setItem(AVATAR_KEY, serialized);
    } catch (storageError) {
      if (storageError instanceof Error && storageError.name === 'QuotaExceededError') {
        // A browser that used an older widget may still be carrying megabytes of
        // dead history. Reclaim it and try once more before giving up.
        if (purgeLegacyHistory()) {
          localStorage.setItem(AVATAR_KEY, serialized);
          return;
        }
        throw new Error('Storage quota exceeded. Please clear browser cache or try a smaller image.');
      }
      throw storageError;
    }
  } catch (e) {
    console.error('Error saving avatar to storage:', e);
    // Re-throw with user-friendly message
    if (e instanceof Error) {
      throw e;
    }
    throw new Error('Failed to save avatar');
  }
}

export function clearAvatar(): void {
  try {
    localStorage.removeItem(AVATAR_KEY);
  } catch (e) {
    console.error('Error clearing avatar from storage:', e);
  }
}

// Visitor ID for per-user rate limiting
export function getVisitorId(): string {
  try {
    let visitorId = localStorage.getItem(VISITOR_ID_KEY);
    if (!visitorId) {
      visitorId = `anon_${crypto.randomUUID()}`;
      localStorage.setItem(VISITOR_ID_KEY, visitorId);
    }
    return visitorId;
  } catch {
    // If localStorage unavailable, generate ephemeral ID (resets on page reload)
    return `anon_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
}

// Consent Storage — asked once per visitor before an AI try-on is generated
const CONSENT_KEY = 'aisthetix_tryon_consent';

export function hasConsent(): boolean {
  try {
    return localStorage.getItem(CONSENT_KEY) === '1';
  } catch {
    return false;
  }
}

export function setConsent(): void {
  try {
    localStorage.setItem(CONSENT_KEY, '1');
  } catch {
    // If localStorage is unavailable, consent will simply be re-requested next visit.
  }
}

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

export function getBodyInputs(): { heightCm: number | null; weightKg: number | null } {
  try {
    const parsed = JSON.parse(localStorage.getItem(BODY_INPUTS_KEY) || 'null');
    return {
      heightCm: typeof parsed?.heightCm === 'number' ? parsed.heightCm : null,
      weightKg: typeof parsed?.weightKg === 'number' ? parsed.weightKg : null,
    };
  } catch {
    return { heightCm: null, weightKg: null };
  }
}

export function saveBodyInputs(heightCm: number, weightKg: number | null): void {
  try {
    localStorage.setItem(BODY_INPUTS_KEY, JSON.stringify({ heightCm, weightKg }));
  } catch {
    // Remembering is optional; the estimate itself still works.
  }
}
