import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { Alert } from 'react-native';
import { useMobileSignal, MobileSignalInfo } from '../hooks/useMobileSignal';
import { offlineStorage, OfflineData, SyncQueueItem } from '../services/offlineStorage';

interface OfflineContextData {
  isOfflineMode: boolean;
  offlineStats: {
    deliveries: number;
    photos: number;
    signatures: number;
    status: number;
    syncQueue: number;
    totalSize: number;
  };
  pendingSyncCount: number;
  isSyncing: boolean;
  lastSyncTime: number | null;
  
  // Funções
  saveOfflineData: (type: OfflineData['type'], data: any) => Promise<string>;
  addToSyncQueue: (item: Omit<SyncQueueItem, 'id' | 'timestamp' | 'retryCount'>) => Promise<string>;
  syncOfflineData: () => Promise<void>;
  clearOfflineData: (type?: OfflineData['type']) => Promise<void>;
  checkOfflineStatus: () => Promise<void>;
}

const OfflineContext = createContext<OfflineContextData>({} as OfflineContextData);

export const useOffline = () => {
  const context = useContext(OfflineContext);
  if (!context) {
    throw new Error('useOffline deve ser usado dentro de um OfflineProvider');
  }
  return context;
};

interface OfflineProviderProps {
  children: React.ReactNode;
}

export const OfflineProvider: React.FC<OfflineProviderProps> = ({ children }) => {
  const { signalInfo } = useMobileSignal();
  
  const [isOfflineMode, setIsOfflineMode] = useState(false);
  const [offlineStats, setOfflineStats] = useState({
    deliveries: 0,
    photos: 0,
    signatures: 0,
    status: 0,
    syncQueue: 0,
    totalSize: 0,
  });
  const [pendingSyncCount, setPendingSyncCount] = useState(0);
  const [isSyncing, setIsSyncing] = useState(false);
  const [lastSyncTime, setLastSyncTime] = useState<number | null>(null);

  // Verificar se deve usar modo offline baseado no sinal
  useEffect(() => {
    const shouldUseOffline = signalInfo.shouldUseOffline;
    setIsOfflineMode(shouldUseOffline);
    
    if (shouldUseOffline) {
      // Notificar usuário sobre modo offline
      Alert.alert(
        'Modo Offline Ativado',
        'Sinal de conexão fraco. Os dados serão salvos localmente e sincronizados quando a conexão melhorar.',
        [{ text: 'OK' }]
      );
    }
  }, [signalInfo.shouldUseOffline]);

  // Verificar status offline periodicamente
  const checkOfflineStatus = useCallback(async () => {
    try {
      const stats = await offlineStorage.getOfflineStats();
      const lastSync = await offlineStorage.getLastSync();
      
      setOfflineStats(stats);
      setPendingSyncCount(stats.totalSize);
      setLastSyncTime(lastSync);
    } catch (error) {
      // Silently fail
    }
  }, []);

  // Verificar status inicial e quando mudar o modo offline
  useEffect(() => {
    checkOfflineStatus();
  }, [checkOfflineStatus, isOfflineMode]);

  // Salvar dados offline
  const saveOfflineData = useCallback(async (type: OfflineData['type'], data: any): Promise<string> => {
    try {
      if (!isOfflineMode) {
        throw new Error('Modo offline não está ativo');
      }
      
      const id = await offlineStorage.saveOfflineData(type, data);
      await checkOfflineStatus(); // Atualizar estatísticas
      
      return id;
    } catch (error) {
      console.error('Erro ao salvar dados offline:', error);
      throw error;
    }
  }, [isOfflineMode, checkOfflineStatus]);

  // Adicionar à fila de sincronização
  const addToSyncQueue = useCallback(async (item: Omit<SyncQueueItem, 'id' | 'timestamp' | 'retryCount'>): Promise<string> => {
    try {
      const id = await offlineStorage.addToSyncQueue(item);
      await checkOfflineStatus(); // Atualizar estatísticas
      
      return id;
    } catch (error) {
      console.error('Erro ao adicionar à fila de sincronização:', error);
      throw error;
    }
  }, [checkOfflineStatus]);

  // Sincronizar dados offline
  const syncOfflineData = useCallback(async () => {
    if (isSyncing) {
      return;
    }

    try {
      setIsSyncing(true);
      
      // Obter fila de sincronização
      const syncQueue = await offlineStorage.getSyncQueue();
      const offlineData = await offlineStorage.getOfflineData('delivery');
      
      if (syncQueue.length === 0 && offlineData.length === 0) {
        return;
      }
      
      
      // Aqui você implementaria a lógica de sincronização real
      // Por enquanto, vamos simular o processo
      
      // Simular sincronização
      await new Promise(resolve => setTimeout(resolve, 2000));
      
      // Limpar dados sincronizados
      await offlineStorage.clearAllOfflineData();
      await offlineStorage.setLastSync();
      
      // Atualizar estatísticas
      await checkOfflineStatus();
      
      
      Alert.alert(
        'Sincronização Concluída',
        'Todos os dados offline foram sincronizados com sucesso!',
        [{ text: 'OK' }]
      );
      
    } catch (error) {
      console.error('Erro durante sincronização:', error);
      
      Alert.alert(
        'Erro na Sincronização',
        'Ocorreu um erro durante a sincronização. Tente novamente.',
        [{ text: 'OK' }]
      );
    } finally {
      setIsSyncing(false);
    }
  }, [isSyncing, checkOfflineStatus]);

  // Limpar dados offline
  const clearOfflineData = useCallback(async (type?: OfflineData['type']) => {
    try {
      if (type) {
        await offlineStorage.clearOfflineData(type);
      } else {
        await offlineStorage.clearAllOfflineData();
      }
      
      await checkOfflineStatus(); // Atualizar estatísticas
      
    } catch (error) {
      console.error('Erro ao limpar dados offline:', error);
    }
  }, [checkOfflineStatus]);

  const contextValue: OfflineContextData = {
    isOfflineMode,
    offlineStats,
    pendingSyncCount,
    isSyncing,
    lastSyncTime,
    saveOfflineData,
    addToSyncQueue,
    syncOfflineData,
    clearOfflineData,
    checkOfflineStatus,
  };

  return (
    <OfflineContext.Provider value={contextValue}>
      {children}
    </OfflineContext.Provider>
  );
}; 