import { Injectable } from '@angular/core';
import { Preferences } from '@capacitor/preferences';

// Clave para almacenar la imagen de perfil en el almacenamiento local
const PROFILE_IMAGE_KEY = 'profileImage';

// Flag para evitar inicializaciones múltiples
let __storageInitialized = false;

@Injectable({
  providedIn: 'root'
})
export class StorageService {

  constructor() { 
    this.initializeStorage();
  }
  
  /**
   * Inicializa el almacenamiento y verifica que funcione correctamente
   */
  private async initializeStorage() {
    if (__storageInitialized) return;
    
    try {
      // Guardar un valor de prueba para verificar que el almacenamiento funciona
      await Preferences.set({
        key: '__storage_test',
        value: 'ok'
      });
      
      // Verificar que podemos recuperar el valor
      const { value } = await Preferences.get({ key: '__storage_test' });
      
      if (value === 'ok') {
        console.log('Almacenamiento local inicializado correctamente');
        __storageInitialized = true;
      } else {
        console.error('Error al inicializar el almacenamiento: valor de prueba incorrecto');
      }
    } catch (error) {
      console.error('Error al inicializar el almacenamiento:', error);
    }
  }

  async set(key: string, value: any): Promise<void> {
    await this.waitForInitialization();
    
    try {
      // Manejar blobs y data URIs en objetos complejos
      const processedValue = this.prepareValueForStorage(value);
      
      // Convertir a string y almacenar
      const valueStr = JSON.stringify(processedValue);
      console.log(`Guardando en storage (${key}):`, valueStr.length > 100 ? valueStr.substring(0, 100) + '...' : valueStr);
      
      await Preferences.set({
        key,
        value: valueStr
      });
    } catch (error) {
      console.error(`Error al guardar en storage (${key}):`, error);
    }
  }
  
  /**
   * Espera a que se inicialice el almacenamiento
   */
  private async waitForInitialization() {
    if (__storageInitialized) return;
    
    let attempts = 0;
    while (!__storageInitialized && attempts < 10) {
      await new Promise(resolve => setTimeout(resolve, 100));
      attempts++;
    }
    
    if (!__storageInitialized) {
      await this.initializeStorage();
    }
  }
  
  /**
   * Prepara valores para almacenamiento, manejando casos especiales
   * como objetos con Blobs que no se pueden serializar
   */
  private prepareValueForStorage(value: any): any {
    if (value === null || value === undefined) {
      return value;
    }
    
    // Si es un array, procesar cada elemento
    if (Array.isArray(value)) {
      return value.map(item => this.prepareValueForStorage(item));
    }
    
    // Si es un objeto que no es una fecha ni un blob
    if (typeof value === 'object' && !(value instanceof Date) && !(value instanceof Blob)) {
      const processed: any = {};
      
      for (const key in value) {
        if (Object.prototype.hasOwnProperty.call(value, key)) {
          // Saltar propiedades blob directamente
          if (value[key] instanceof Blob) {
            continue;
          }
          
          // Para cada propiedad, procesarla recursivamente
          processed[key] = this.prepareValueForStorage(value[key]);
        }
      }
      
      return processed;
    }
    
    // Si es una fecha, convertir a string ISO
    if (value instanceof Date) {
      return value.toISOString();
    }
    
    // Cualquier otro valor primitivo
    return value;
  }

  async get(key: string): Promise<any> {
    await this.waitForInitialization();
    
    try {
      const { value } = await Preferences.get({ key });
      
      if (value) {
        const parsed = JSON.parse(value);
        console.log(`Recuperando de storage (${key}):`, 
          typeof parsed === 'object' ? 'Objeto recuperado' : 
          (value.length > 100 ? value.substring(0, 100) + '...' : value));
        return parsed;
      }
    } catch (error) {
      console.error(`Error al recuperar de storage (${key}):`, error);
    }
    
    return null;
  }

  async remove(key: string): Promise<void> {
    await this.waitForInitialization();
    try {
      await Preferences.remove({ key });
      console.log(`Eliminado del storage: ${key}`);
    } catch (error) {
      console.error(`Error al eliminar de storage (${key}):`, error);
    }
  }

  async clear(): Promise<void> {
    await this.waitForInitialization();
    try {
      await Preferences.clear();
      console.log('Storage limpiado completamente');
    } catch (error) {
      console.error('Error al limpiar storage:', error);
    }
  }

  /**
   * Guarda la imagen de perfil del usuario en almacenamiento local
   * @param dataUrl La imagen en formato data URL
   */
  async saveProfileImage(dataUrl: string): Promise<void> {
    return this.set(PROFILE_IMAGE_KEY, { dataUrl, timestamp: new Date().toISOString() });
  }

  /**
   * Recupera la imagen de perfil del usuario del almacenamiento local
   * @returns La imagen en formato data URL o null si no existe
   */
  async getProfileImage(): Promise<string | null> {
    const data = await this.get(PROFILE_IMAGE_KEY);
    return data?.dataUrl || null;
  }

  /**
   * Comprueba si hay una imagen de perfil almacenada localmente
   */
  async hasProfileImage(): Promise<boolean> {
    const image = await this.getProfileImage();
    return image !== null;
  }
}
