import AsyncStorage from '@react-native-async-storage/async-storage';
import { MobileSignalInfo } from '../hooks/useMobileSignal';

// Chaves para armazenamento
const OFFLINE_KEYS = {
  DELIVERIES: 'offline_deliveries',
  PHOTOS: 'offline_photos',
  SIGNATURES: 'offline_signatures',
  DELIVERY_STATUS: 'offline_delivery_status',
  SYNC_QUEUE: 'offline_sync_queue',
  LAST_SYNC: 'offline_last_sync',
};

// Interface para dados offline
export interface OfflineData {
  id: string;
  timestamp: number;
  data: any;
  type: 'delivery' | 'photo' | 'signature' | 'status';
  retryCount: number;
  maxRetries: number;
}

// Interface para fila de sincronização
export interface SyncQueueItem {
  id: string;
  action: 'create' | 'update' | 'delete';
  endpoint: string;
  data: any;
  timestamp: number;
  retryCount: number;
  maxRetries: number;
}

class OfflineStorageService {
  // Verificar se deve usar armazenamento offline
  shouldUseOffline(signalInfo: MobileSignalInfo): boolean {
    return signalInfo.shouldUseOffline;
  }

  // Salvar dados offline
  async saveOfflineData(type: OfflineData['type'], data: any): Promise<string> {
    try {
      const offlineData: OfflineData = {
        id: `${type}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        timestamp: Date.now(),
        data,
        type,
        retryCount: 0,
        maxRetries: 3,
      };

      const key = this.getOfflineKey(type);
      const existingData = await this.getOfflineData(type);
      existingData.push(offlineData);

      await AsyncStorage.setItem(key, JSON.stringify(existingData));
      
      return offlineData.id;
    } catch (error) {
      console.error('Erro ao salvar dados offline:', error);
      throw error;
    }
  }

  // Obter dados offline por tipo
  async getOfflineData(type: OfflineData['type']): Promise<OfflineData[]> {
    try {
      const key = this.getOfflineKey(type);
      const data = await AsyncStorage.getItem(key);
      return data ? JSON.parse(data) : [];
    } catch (error) {
      console.error('Erro ao obter dados offline:', error);
      return [];
    }
  }

  // Obter chave de armazenamento por tipo
  private getOfflineKey(type: OfflineData['type']): string {
    switch (type) {
      case 'delivery':
        return OFFLINE_KEYS.DELIVERIES;
      case 'photo':
        return OFFLINE_KEYS.PHOTOS;
      case 'signature':
        return OFFLINE_KEYS.SIGNATURES;
      case 'status':
        return OFFLINE_KEYS.DELIVERY_STATUS;
      default:
        return OFFLINE_KEYS.DELIVERIES;
    }
  }

  // Adicionar item à fila de sincronização
  async addToSyncQueue(item: Omit<SyncQueueItem, 'id' | 'timestamp' | 'retryCount'>): Promise<string> {
    try {
      const syncItem: SyncQueueItem = {
        ...item,
        id: `sync_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
        timestamp: Date.now(),
        retryCount: 0,
      };

      const existingQueue = await this.getSyncQueue();
      existingQueue.push(syncItem);

      await AsyncStorage.setItem(OFFLINE_KEYS.SYNC_QUEUE, JSON.stringify(existingQueue));
      
      return syncItem.id;
    } catch (error) {
      console.error('Erro ao adicionar à fila de sincronização:', error);
      throw error;
    }
  }

  // Obter fila de sincronização
  async getSyncQueue(): Promise<SyncQueueItem[]> {
    try {
      const data = await AsyncStorage.getItem(OFFLINE_KEYS.SYNC_QUEUE);
      return data ? JSON.parse(data) : [];
    } catch (error) {
      console.error('Erro ao obter fila de sincronização:', error);
      return [];
    }
  }

  // Remover item da fila de sincronização
  async removeFromSyncQueue(id: string): Promise<void> {
    try {
      const queue = await this.getSyncQueue();
      const filteredQueue = queue.filter(item => item.id !== id);
      await AsyncStorage.setItem(OFFLINE_KEYS.SYNC_QUEUE, JSON.stringify(filteredQueue));
      
    } catch (error) {
      console.error('Erro ao remover da fila de sincronização:', error);
    }
  }

  // Incrementar contador de tentativas
  async incrementRetryCount(id: string): Promise<void> {
    try {
      const queue = await this.getSyncQueue();
      const item = queue.find(q => q.id === id);
      
      if (item) {
        item.retryCount++;
        
        if (item.retryCount >= item.maxRetries) {
          // Remover item se excedeu o número máximo de tentativas
          await this.removeFromSyncQueue(id);
        } else {
          // Atualizar fila com novo contador
          await AsyncStorage.setItem(OFFLINE_KEYS.SYNC_QUEUE, JSON.stringify(queue));
        }
      }
    } catch (error) {
      console.error('Erro ao incrementar contador de tentativas:', error);
    }
  }

  // Limpar dados offline por tipo
  async clearOfflineData(type: OfflineData['type']): Promise<void> {
    try {
      const key = this.getOfflineKey(type);
      await AsyncStorage.removeItem(key);
      
    } catch (error) {
      console.error('Erro ao limpar dados offline:', error);
    }
  }

  // Limpar todos os dados offline
  async clearAllOfflineData(): Promise<void> {
    try {
      await AsyncStorage.multiRemove([
        OFFLINE_KEYS.DELIVERIES,
        OFFLINE_KEYS.PHOTOS,
        OFFLINE_KEYS.SIGNATURES,
        OFFLINE_KEYS.DELIVERY_STATUS,
        OFFLINE_KEYS.SYNC_QUEUE,
      ]);
      
    } catch (error) {
      console.error('Erro ao limpar todos os dados offline:', error);
    }
  }

  // Obter estatísticas de dados offline
  async getOfflineStats(): Promise<{
    deliveries: number;
    photos: number;
    signatures: number;
    status: number;
    syncQueue: number;
    totalSize: number;
  }> {
    try {
      const deliveries = await this.getOfflineData('delivery');
      const photos = await this.getOfflineData('photo');
      const signatures = await this.getOfflineData('signature');
      const status = await this.getOfflineData('status');
      const syncQueue = await this.getSyncQueue();

      const totalSize = deliveries.length + photos.length + signatures.length + status.length + syncQueue.length;

      return {
        deliveries: deliveries.length,
        photos: photos.length,
        signatures: signatures.length,
        status: status.length,
        syncQueue: syncQueue.length,
        totalSize,
      };
    } catch (error) {
      console.error('Erro ao obter estatísticas offline:', error);
      return {
        deliveries: 0,
        photos: 0,
        signatures: 0,
        status: 0,
        syncQueue: 0,
        totalSize: 0,
      };
    }
  }

  // Verificar se há dados para sincronizar
  async hasDataToSync(): Promise<boolean> {
    try {
      const stats = await this.getOfflineStats();
      return stats.totalSize > 0;
    } catch (error) {
      console.error('Erro ao verificar dados para sincronizar:', error);
      return false;
    }
  }

  // Salvar timestamp da última sincronização
  async setLastSync(): Promise<void> {
    try {
      await AsyncStorage.setItem(OFFLINE_KEYS.LAST_SYNC, Date.now().toString());
    } catch (error) {
      console.error('Erro ao salvar timestamp da última sincronização:', error);
    }
  }

  // Obter timestamp da última sincronização
  async getLastSync(): Promise<number | null> {
    try {
      const timestamp = await AsyncStorage.getItem(OFFLINE_KEYS.LAST_SYNC);
      return timestamp ? parseInt(timestamp) : null;
    } catch (error) {
      console.error('Erro ao obter timestamp da última sincronização:', error);
      return null;
    }
  }
}

export const offlineStorage = new OfflineStorageService();
export default offlineStorage; 