# Estratégia de Sincronização Offline - Implementação Completa

## Visão Geral

Este documento detalha a estratégia completa para implementar sincronização offline no aplicativo de entregas, permitindo que o aplicativo funcione sem dependência de internet após uma sincronização inicial completa.

## Arquitetura de Sincronização

### 1. Fluxo de Sincronização

```
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Aplicativo    │    │   Servidor      │    │   Banco Local   │
│                 │    │                 │    │   (SQLite)      │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         │ 1. Login              │                       │
         ├──────────────────────►│                       │
         │◄──────────────────────┤                       │
         │                       │                       │
         │ 2. Sync Inicial       │                       │
         ├──────────────────────►│                       │
         │◄──────────────────────┤                       │
         │                       │                       │
         │ 3. Salvar Local       │                       │
         ├─────────────────────────────────────────────►│
         │                       │                       │
         │ 4. Modo Offline       │                       │
         │    (Usar dados locais)│                       │
         ├─────────────────────────────────────────────►│
         │                       │                       │
         │ 5. Sync Incremental   │                       │
         │    (Quando online)    │                       │
         ├──────────────────────►│                       │
         │◄──────────────────────┤                       │
         │                       │                       │
         │ 6. Atualizar Local    │                       │
         ├─────────────────────────────────────────────►│
```

### 2. Estados de Sincronização

```typescript
enum SyncStatus {
  SYNCED = 'synced',           // Sincronizado com servidor
  PENDING = 'pending',         // Aguardando sincronização
  CONFLICT = 'conflict',       // Conflito detectado
  ERROR = 'error',            // Erro na sincronização
  OFFLINE = 'offline'         // Modo offline ativo
}

enum SyncType {
  FULL = 'full',              // Sincronização completa
  INCREMENTAL = 'incremental', // Sincronização incremental
  SELECTIVE = 'selective'     // Sincronização seletiva
}
```

## Implementação do Sistema de Sincronização

### 1. Contexto de Sincronização Expandido

**Arquivo**: `src/contexts/InitialSyncContext.tsx`

```typescript
interface InitialSyncContextData {
  // Estados
  isInitialSyncComplete: boolean;
  syncProgress: number;
  syncStatus: SyncStatus;
  lastSyncTime: number | null;
  pendingChanges: number;
  
  // Métodos
  startInitialSync: () => Promise<void>;
  retryInitialSync: () => Promise<void>;
  performIncrementalSync: () => Promise<void>;
  performSelectiveSync: (ids: string[]) => Promise<void>;
  resolveConflict: (conflictId: string, resolution: ConflictResolution) => Promise<void>;
  
  // Utilitários
  getSyncStats: () => Promise<SyncStats>;
  clearSyncData: () => Promise<void>;
}

interface SyncStats {
  totalRecords: number;
  syncedRecords: number;
  pendingRecords: number;
  conflictedRecords: number;
  errorRecords: number;
  lastSyncDuration: number;
  averageSyncTime: number;
}

interface ConflictResolution {
  type: 'server_wins' | 'client_wins' | 'merge';
  data?: any;
}
```

### 2. Serviço de Sincronização Principal

**Arquivo**: `src/services/syncService.ts`

```typescript
class SyncService {
  private api: ApiService;
  private database: DatabaseService;
  private offlineStorage: OfflineStorageService;
  private syncQueue: SyncQueue;
  private conflictResolver: ConflictResolver;

  constructor() {
    this.api = new ApiService();
    this.database = new DatabaseService();
    this.offlineStorage = new OfflineStorageService();
    this.syncQueue = new SyncQueue();
    this.conflictResolver = new ConflictResolver();
  }

  // Sincronização inicial completa
  async performInitialSync(): Promise<SyncResult> {
    try {
      console.log('=== INICIANDO SINCRONIZAÇÃO INICIAL ===');
      
      const syncResult: SyncResult = {
        success: true,
        totalRecords: 0,
        syncedRecords: 0,
        errors: [],
        duration: 0
      };

      const startTime = Date.now();

      // 1. Sincronizar dados de usuário
      await this.syncUserData();
      syncResult.syncedRecords += 1;

      // 2. Sincronizar entregas
      const deliveriesResult = await this.syncDeliveries();
      syncResult.syncedRecords += deliveriesResult.count;

      // 3. Sincronizar configurações
      await this.syncSettings();
      syncResult.syncedRecords += 1;

      // 4. Sincronizar dados de referência
      await this.syncReferenceData();
      syncResult.syncedRecords += 5; // Aproximadamente

      // 5. Marcar sincronização como completa
      await this.database.saveSetting('initial_sync_complete', 'true');
      await this.database.saveSetting('last_sync_time', Date.now().toString());

      syncResult.duration = Date.now() - startTime;
      syncResult.totalRecords = syncResult.syncedRecords;

      console.log('=== SINCRONIZAÇÃO INICIAL CONCLUÍDA ===');
      console.log(`Total de registros: ${syncResult.totalRecords}`);
      console.log(`Duração: ${syncResult.duration}ms`);

      return syncResult;

    } catch (error) {
      console.error('Erro na sincronização inicial:', error);
      throw new SyncError('Falha na sincronização inicial', error);
    }
  }

  // Sincronização incremental
  async performIncrementalSync(): Promise<SyncResult> {
    try {
      console.log('=== INICIANDO SINCRONIZAÇÃO INCREMENTAL ===');
      
      const lastSyncTime = await this.database.getSetting('last_sync_time');
      const syncResult: SyncResult = {
        success: true,
        totalRecords: 0,
        syncedRecords: 0,
        errors: [],
        duration: 0
      };

      const startTime = Date.now();

      // 1. Buscar mudanças do servidor desde última sincronização
      const serverChanges = await this.api.getChangesSince(lastSyncTime);
      
      // 2. Buscar mudanças locais não sincronizadas
      const localChanges = await this.database.getUnsyncedRecords();

      // 3. Resolver conflitos
      const conflicts = await this.detectConflicts(serverChanges, localChanges);
      await this.resolveConflicts(conflicts);

      // 4. Aplicar mudanças do servidor
      await this.applyServerChanges(serverChanges);

      // 5. Enviar mudanças locais
      await this.sendLocalChanges(localChanges);

      // 6. Atualizar timestamp de sincronização
      await this.database.saveSetting('last_sync_time', Date.now().toString());

      syncResult.duration = Date.now() - startTime;
      console.log('=== SINCRONIZAÇÃO INCREMENTAL CONCLUÍDA ===');

      return syncResult;

    } catch (error) {
      console.error('Erro na sincronização incremental:', error);
      throw new SyncError('Falha na sincronização incremental', error);
    }
  }

  // Sincronização seletiva
  async performSelectiveSync(recordIds: string[]): Promise<SyncResult> {
    try {
      console.log(`=== INICIANDO SINCRONIZAÇÃO SELETIVA (${recordIds.length} registros) ===`);
      
      const syncResult: SyncResult = {
        success: true,
        totalRecords: recordIds.length,
        syncedRecords: 0,
        errors: [],
        duration: 0
      };

      const startTime = Date.now();

      for (const recordId of recordIds) {
        try {
          await this.syncSingleRecord(recordId);
          syncResult.syncedRecords += 1;
        } catch (error) {
          syncResult.errors.push({
            recordId,
            error: error.message
          });
        }
      }

      syncResult.duration = Date.now() - startTime;
      console.log('=== SINCRONIZAÇÃO SELETIVA CONCLUÍDA ===');

      return syncResult;

    } catch (error) {
      console.error('Erro na sincronização seletiva:', error);
      throw new SyncError('Falha na sincronização seletiva', error);
    }
  }

  // Métodos auxiliares
  private async syncUserData(): Promise<void> {
    const userData = await this.api.getCurrentUser();
    await this.database.saveUser(userData);
  }

  private async syncDeliveries(): Promise<{ count: number }> {
    const deliveries = await this.api.getDeliveries();
    let count = 0;

    for (const delivery of deliveries) {
      await this.database.saveDelivery(delivery);
      count += 1;
    }

    return { count };
  }

  private async syncSettings(): Promise<void> {
    const settings = await this.api.getSettings();
    for (const [key, value] of Object.entries(settings)) {
      await this.database.saveSetting(key, value);
    }
  }

  private async syncReferenceData(): Promise<void> {
    // Sincronizar dados de referência como:
    // - Lista de produtos
    // - Configurações de entrega
    // - Dados de clientes
    // - Configurações de rota
  }
}
```

### 3. Fila de Sincronização

**Arquivo**: `src/services/syncQueue.ts`

```typescript
interface SyncQueueItem {
  id: string;
  type: 'create' | 'update' | 'delete';
  table: string;
  recordId: string;
  data: any;
  timestamp: number;
  retryCount: number;
  maxRetries: number;
  priority: 'high' | 'normal' | 'low';
}

class SyncQueue {
  private queue: SyncQueueItem[] = [];
  private processing: boolean = false;

  // Adicionar item à fila
  async addItem(item: Omit<SyncQueueItem, 'id' | 'timestamp' | 'retryCount'>): Promise<string> {
    const queueItem: SyncQueueItem = {
      ...item,
      id: `sync_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      timestamp: Date.now(),
      retryCount: 0,
      maxRetries: item.maxRetries || 3
    };

    this.queue.push(queueItem);
    this.queue.sort((a, b) => this.getPriorityValue(b.priority) - this.getPriorityValue(a.priority));

    console.log(`Item adicionado à fila: ${queueItem.id}`);
    return queueItem.id;
  }

  // Processar fila
  async processQueue(): Promise<void> {
    if (this.processing || this.queue.length === 0) {
      return;
    }

    this.processing = true;
    console.log(`Processando fila com ${this.queue.length} itens`);

    while (this.queue.length > 0) {
      const item = this.queue.shift();
      if (!item) break;

      try {
        await this.processItem(item);
        console.log(`Item processado com sucesso: ${item.id}`);
      } catch (error) {
        console.error(`Erro ao processar item ${item.id}:`, error);
        
        item.retryCount += 1;
        
        if (item.retryCount < item.maxRetries) {
          // Reagendar item
          this.queue.push(item);
          console.log(`Item reagendado: ${item.id} (tentativa ${item.retryCount})`);
        } else {
          console.error(`Item falhou após ${item.maxRetries} tentativas: ${item.id}`);
        }
      }
    }

    this.processing = false;
    console.log('Processamento da fila concluído');
  }

  private async processItem(item: SyncQueueItem): Promise<void> {
    switch (item.type) {
      case 'create':
        await this.api.createRecord(item.table, item.data);
        break;
      case 'update':
        await this.api.updateRecord(item.table, item.recordId, item.data);
        break;
      case 'delete':
        await this.api.deleteRecord(item.table, item.recordId);
        break;
    }

    // Marcar como sincronizado no banco local
    await this.database.markAsSynced(item.table, item.recordId);
  }

  private getPriorityValue(priority: string): number {
    switch (priority) {
      case 'high': return 3;
      case 'normal': return 2;
      case 'low': return 1;
      default: return 2;
    }
  }
}
```

### 4. Resolução de Conflitos

**Arquivo**: `src/services/conflictResolver.ts`

```typescript
interface Conflict {
  id: string;
  table: string;
  recordId: string;
  localData: any;
  serverData: any;
  conflictFields: string[];
  timestamp: number;
}

class ConflictResolver {
  // Detectar conflitos
  async detectConflicts(serverChanges: any[], localChanges: any[]): Promise<Conflict[]> {
    const conflicts: Conflict[] = [];

    for (const serverChange of serverChanges) {
      const localChange = localChanges.find(lc => lc.id === serverChange.id);
      
      if (localChange) {
        const conflictFields = this.findConflictFields(serverChange, localChange);
        
        if (conflictFields.length > 0) {
          conflicts.push({
            id: `conflict_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
            table: serverChange.table,
            recordId: serverChange.id,
            localData: localChange,
            serverData: serverChange,
            conflictFields,
            timestamp: Date.now()
          });
        }
      }
    }

    return conflicts;
  }

  // Resolver conflito
  async resolveConflict(conflict: Conflict, resolution: ConflictResolution): Promise<void> {
    let resolvedData: any;

    switch (resolution.type) {
      case 'server_wins':
        resolvedData = conflict.serverData;
        break;
      case 'client_wins':
        resolvedData = conflict.localData;
        break;
      case 'merge':
        resolvedData = this.mergeData(conflict.localData, conflict.serverData, resolution.data);
        break;
    }

    // Atualizar banco local com dados resolvidos
    await this.database.updateRecord(conflict.table, conflict.recordId, resolvedData);
    
    // Marcar conflito como resolvido
    await this.database.markConflictResolved(conflict.id);
  }

  private findConflictFields(serverData: any, localData: any): string[] {
    const conflictFields: string[] = [];
    const fieldsToCheck = ['status', 'notes', 'photos', 'signature', 'completed_time'];

    for (const field of fieldsToCheck) {
      if (serverData[field] !== localData[field]) {
        conflictFields.push(field);
      }
    }

    return conflictFields;
  }

  private mergeData(localData: any, serverData: any, mergeRules?: any): any {
    const merged = { ...localData };

    // Aplicar regras de merge específicas
    if (mergeRules) {
      for (const [field, rule] of Object.entries(mergeRules)) {
        switch (rule) {
          case 'latest':
            merged[field] = serverData[field];
            break;
          case 'append':
            if (Array.isArray(merged[field]) && Array.isArray(serverData[field])) {
              merged[field] = [...merged[field], ...serverData[field]];
            }
            break;
          case 'combine':
            merged[field] = `${merged[field]} ${serverData[field]}`.trim();
            break;
        }
      }
    }

    return merged;
  }
}
```

## Estrutura de Banco de Dados para Sincronização

### 1. Tabelas Adicionais

```sql
-- Tabela de controle de sincronização
CREATE TABLE IF NOT EXISTS sync_control (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  table_name TEXT NOT NULL,
  last_sync_timestamp INTEGER,
  sync_status TEXT DEFAULT 'pending',
  created_at INTEGER DEFAULT (strftime('%s', 'now')),
  updated_at INTEGER DEFAULT (strftime('%s', 'now'))
);

-- Tabela de conflitos
CREATE TABLE IF NOT EXISTS sync_conflicts (
  id TEXT PRIMARY KEY,
  table_name TEXT NOT NULL,
  record_id TEXT NOT NULL,
  local_data TEXT,
  server_data TEXT,
  conflict_fields TEXT,
  resolution TEXT,
  resolved_at INTEGER,
  created_at INTEGER DEFAULT (strftime('%s', 'now'))
);

-- Tabela de log de sincronização
CREATE TABLE IF NOT EXISTS sync_log (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  sync_type TEXT NOT NULL,
  table_name TEXT,
  record_id TEXT,
  action TEXT,
  success INTEGER DEFAULT 1,
  error_message TEXT,
  duration INTEGER,
  timestamp INTEGER DEFAULT (strftime('%s', 'now'))
);

-- Adicionar campos de controle às tabelas existentes
ALTER TABLE deliveries ADD COLUMN version INTEGER DEFAULT 1;
ALTER TABLE deliveries ADD COLUMN last_modified INTEGER DEFAULT (strftime('%s', 'now'));
ALTER TABLE deliveries ADD COLUMN sync_timestamp INTEGER;
ALTER TABLE deliveries ADD COLUMN conflict_resolution TEXT;
```

### 2. Índices para Performance

```sql
-- Índices para sincronização
CREATE INDEX IF NOT EXISTS idx_deliveries_sync_timestamp ON deliveries(sync_timestamp);
CREATE INDEX IF NOT EXISTS idx_deliveries_last_modified ON deliveries(last_modified);
CREATE INDEX IF NOT EXISTS idx_deliveries_version ON deliveries(version);
CREATE INDEX IF NOT EXISTS idx_sync_log_timestamp ON sync_log(timestamp);
CREATE INDEX IF NOT EXISTS idx_sync_conflicts_resolved ON sync_conflicts(resolved_at);
```

## Implementação de Endpoints para Sincronização

### 1. Endpoints do Servidor

```typescript
// Endpoints necessários no servidor
interface SyncEndpoints {
  // Sincronização inicial
  'GET /v1/sync/initial': () => Promise<InitialSyncData>;
  
  // Sincronização incremental
  'GET /v1/sync/changes': (since: number) => Promise<ChangeSet>;
  'POST /v1/sync/changes': (changes: ChangeSet) => Promise<SyncResult>;
  
  // Sincronização seletiva
  'POST /v1/sync/selective': (ids: string[]) => Promise<SelectiveSyncData>;
  
  // Resolução de conflitos
  'POST /v1/sync/conflicts/resolve': (conflicts: ConflictResolution[]) => Promise<void>;
  
  // Status de sincronização
  'GET /v1/sync/status': () => Promise<SyncStatus>;
}
```

### 2. Implementação no Cliente

```typescript
// src/services/api.ts - Métodos adicionais
class ApiService {
  // Obter dados para sincronização inicial
  async getInitialSyncData(): Promise<InitialSyncData> {
    const response = await this.request('/v1/sync/initial');
    return response.data;
  }

  // Obter mudanças desde timestamp
  async getChangesSince(timestamp: number): Promise<ChangeSet> {
    const response = await this.request(`/v1/sync/changes?since=${timestamp}`);
    return response.data;
  }

  // Enviar mudanças locais
  async sendLocalChanges(changes: ChangeSet): Promise<SyncResult> {
    const response = await this.request('/v1/sync/changes', {
      method: 'POST',
      body: JSON.stringify(changes)
    });
    return response.data;
  }

  // Sincronização seletiva
  async performSelectiveSync(ids: string[]): Promise<SelectiveSyncData> {
    const response = await this.request('/v1/sync/selective', {
      method: 'POST',
      body: JSON.stringify({ ids })
    });
    return response.data;
  }

  // Resolver conflitos
  async resolveConflicts(resolutions: ConflictResolution[]): Promise<void> {
    await this.request('/v1/sync/conflicts/resolve', {
      method: 'POST',
      body: JSON.stringify({ resolutions })
    });
  }

  // Obter status de sincronização
  async getSyncStatus(): Promise<SyncStatus> {
    const response = await this.request('/v1/sync/status');
    return response.data;
  }
}
```

## Interface de Usuário para Sincronização

### 1. Tela de Sincronização Inicial

```typescript
// src/screens/sync/InitialSyncScreen.tsx
const InitialSyncScreen: React.FC = () => {
  const { startInitialSync, syncProgress, syncStatus } = useInitialSync();
  const [isLoading, setIsLoading] = useState(false);

  const handleStartSync = async () => {
    setIsLoading(true);
    try {
      await startInitialSync();
      // Navegar para tela principal após sincronização
      navigation.replace('Main');
    } catch (error) {
      Alert.alert('Erro', 'Falha na sincronização inicial');
    } finally {
      setIsLoading(false);
    }
  };

  return (
    <View style={styles.container}>
      <LinearGradient colors={[COLORS.primary, "#3B82F6"]} style={styles.header}>
        <Text style={styles.title}>Sincronização Inicial</Text>
        <Text style={styles.subtitle}>
          Baixando dados necessários para funcionamento offline
        </Text>
      </LinearGradient>

      <View style={styles.content}>
        <View style={styles.progressContainer}>
          <ProgressBar progress={syncProgress} />
          <Text style={styles.progressText}>
            {Math.round(syncProgress * 100)}% concluído
          </Text>
        </View>

        <View style={styles.statusContainer}>
          <Text style={styles.statusText}>
            Status: {getStatusText(syncStatus)}
          </Text>
        </View>

        <TouchableOpacity
          style={[styles.syncButton, isLoading && styles.syncButtonDisabled]}
          onPress={handleStartSync}
          disabled={isLoading}
        >
          <Ionicons name="cloud-download" size={24} color="white" />
          <Text style={styles.syncButtonText}>
            {isLoading ? 'Sincronizando...' : 'Iniciar Sincronização'}
          </Text>
        </TouchableOpacity>
      </View>
    </View>
  );
};
```

### 2. Componente de Status de Sincronização

```typescript
// src/components/SyncStatusIndicator.tsx
const SyncStatusIndicator: React.FC = () => {
  const { syncStatus, lastSyncTime, pendingChanges } = useSync();
  const [showDetails, setShowDetails] = useState(false);

  const getStatusColor = (status: SyncStatus) => {
    switch (status) {
      case SyncStatus.SYNCED: return COLORS.success;
      case SyncStatus.PENDING: return COLORS.warning;
      case SyncStatus.CONFLICT: return COLORS.danger;
      case SyncStatus.ERROR: return COLORS.danger;
      case SyncStatus.OFFLINE: return COLORS.textLight;
      default: return COLORS.textLight;
    }
  };

  const getStatusIcon = (status: SyncStatus) => {
    switch (status) {
      case SyncStatus.SYNCED: return 'checkmark-circle';
      case SyncStatus.PENDING: return 'time';
      case SyncStatus.CONFLICT: return 'warning';
      case SyncStatus.ERROR: return 'close-circle';
      case SyncStatus.OFFLINE: return 'cloud-offline';
      default: return 'help-circle';
    }
  };

  return (
    <TouchableOpacity
      style={styles.container}
      onPress={() => setShowDetails(!showDetails)}
    >
      <View style={styles.statusRow}>
        <Ionicons
          name={getStatusIcon(syncStatus)}
          size={16}
          color={getStatusColor(syncStatus)}
        />
        <Text style={[styles.statusText, { color: getStatusColor(syncStatus) }]}>
          {getStatusText(syncStatus)}
        </Text>
        {pendingChanges > 0 && (
          <View style={styles.badge}>
            <Text style={styles.badgeText}>{pendingChanges}</Text>
          </View>
        )}
      </View>

      {showDetails && (
        <View style={styles.detailsContainer}>
          <Text style={styles.detailText}>
            Última sincronização: {formatDate(lastSyncTime)}
          </Text>
          <Text style={styles.detailText}>
            Mudanças pendentes: {pendingChanges}
          </Text>
        </View>
      )}
    </TouchableOpacity>
  );
};
```

### 3. Tela de Resolução de Conflitos

```typescript
// src/screens/sync/ConflictResolutionScreen.tsx
const ConflictResolutionScreen: React.FC = () => {
  const { conflicts, resolveConflict } = useSync();
  const [selectedConflict, setSelectedConflict] = useState<Conflict | null>(null);

  const handleResolveConflict = async (resolution: ConflictResolution) => {
    if (!selectedConflict) return;

    try {
      await resolveConflict(selectedConflict.id, resolution);
      setSelectedConflict(null);
      Alert.alert('Sucesso', 'Conflito resolvido com sucesso');
    } catch (error) {
      Alert.alert('Erro', 'Falha ao resolver conflito');
    }
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>Resolução de Conflitos</Text>
      
      <FlatList
        data={conflicts}
        keyExtractor={(item) => item.id}
        renderItem={({ item }) => (
          <TouchableOpacity
            style={styles.conflictItem}
            onPress={() => setSelectedConflict(item)}
          >
            <Text style={styles.conflictTitle}>
              Conflito em {item.table} - {item.recordId}
            </Text>
            <Text style={styles.conflictFields}>
              Campos: {item.conflictFields.join(', ')}
            </Text>
          </TouchableOpacity>
        )}
      />

      {selectedConflict && (
        <ConflictResolutionModal
          conflict={selectedConflict}
          onResolve={handleResolveConflict}
          onClose={() => setSelectedConflict(null)}
        />
      )}
    </View>
  );
};
```

## Estratégias de Otimização

### 1. Compressão de Dados

```typescript
// src/utils/compression.ts
import { compress, decompress } from 'lz-string';

export class DataCompression {
  static compress(data: any): string {
    const jsonString = JSON.stringify(data);
    return compress(jsonString);
  }

  static decompress(compressedData: string): any {
    const jsonString = decompress(compressedData);
    return JSON.parse(jsonString);
  }

  static async compressFile(filePath: string): Promise<string> {
    const fileContent = await FileSystem.readAsStringAsync(filePath);
    return this.compress(fileContent);
  }
}
```

### 2. Cache Inteligente

```typescript
// src/services/cacheService.ts
class CacheService {
  private cache = new Map<string, CacheEntry>();
  private maxSize = 100; // MB
  private currentSize = 0;

  async set(key: string, data: any, ttl: number = 3600000): Promise<void> {
    const compressedData = DataCompression.compress(data);
    const size = compressedData.length;

    // Verificar se há espaço suficiente
    if (this.currentSize + size > this.maxSize * 1024 * 1024) {
      await this.evictOldEntries();
    }

    this.cache.set(key, {
      data: compressedData,
      timestamp: Date.now(),
      ttl,
      size
    });

    this.currentSize += size;
  }

  async get(key: string): Promise<any | null> {
    const entry = this.cache.get(key);
    
    if (!entry) return null;

    // Verificar se expirou
    if (Date.now() - entry.timestamp > entry.ttl) {
      this.cache.delete(key);
      this.currentSize -= entry.size;
      return null;
    }

    return DataCompression.decompress(entry.data);
  }

  private async evictOldEntries(): Promise<void> {
    const entries = Array.from(this.cache.entries())
      .sort((a, b) => a[1].timestamp - b[1].timestamp);

    // Remover 20% das entradas mais antigas
    const toRemove = Math.floor(entries.length * 0.2);
    
    for (let i = 0; i < toRemove; i++) {
      const [key, entry] = entries[i];
      this.cache.delete(key);
      this.currentSize -= entry.size;
    }
  }
}
```

### 3. Sincronização em Background

```typescript
// src/services/backgroundSync.ts
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';

const BACKGROUND_SYNC_TASK = 'background-sync';

TaskManager.defineTask(BACKGROUND_SYNC_TASK, async () => {
  try {
    const syncService = new SyncService();
    await syncService.performIncrementalSync();
    
    return BackgroundFetch.BackgroundFetchResult.NewData;
  } catch (error) {
    console.error('Erro na sincronização em background:', error);
    return BackgroundFetch.BackgroundFetchResult.Failed;
  }
});

export class BackgroundSyncService {
  static async registerBackgroundSync(): Promise<void> {
    try {
      await BackgroundFetch.registerTaskAsync(BACKGROUND_SYNC_TASK, {
        minimumInterval: 15 * 60, // 15 minutos
        stopOnTerminate: false,
        startOnBoot: true,
      });
    } catch (error) {
      console.error('Erro ao registrar sincronização em background:', error);
    }
  }

  static async unregisterBackgroundSync(): Promise<void> {
    try {
      await BackgroundFetch.unregisterTaskAsync(BACKGROUND_SYNC_TASK);
    } catch (error) {
      console.error('Erro ao desregistrar sincronização em background:', error);
    }
  }
}
```

## Monitoramento e Logs

### 1. Sistema de Logs

```typescript
// src/services/logger.ts
interface LogEntry {
  level: 'debug' | 'info' | 'warn' | 'error';
  message: string;
  timestamp: number;
  context?: any;
  userId?: string;
}

class Logger {
  private logs: LogEntry[] = [];
  private maxLogs = 1000;

  log(level: LogEntry['level'], message: string, context?: any): void {
    const logEntry: LogEntry = {
      level,
      message,
      timestamp: Date.now(),
      context,
      userId: this.getCurrentUserId()
    };

    this.logs.push(logEntry);

    // Manter apenas os logs mais recentes
    if (this.logs.length > this.maxLogs) {
      this.logs = this.logs.slice(-this.maxLogs);
    }

    // Log no console para desenvolvimento
    if (__DEV__) {
      console[level](`[${new Date().toISOString()}] ${message}`, context);
    }
  }

  async exportLogs(): Promise<string> {
    return JSON.stringify(this.logs, null, 2);
  }

  async clearLogs(): Promise<void> {
    this.logs = [];
  }

  private getCurrentUserId(): string | undefined {
    // Implementar obtenção do ID do usuário atual
    return undefined;
  }
}

export const logger = new Logger();
```

### 2. Métricas de Performance

```typescript
// src/services/metrics.ts
interface SyncMetrics {
  totalSyncs: number;
  successfulSyncs: number;
  failedSyncs: number;
  averageSyncTime: number;
  totalDataTransferred: number;
  conflictsResolved: number;
}

class MetricsService {
  private metrics: SyncMetrics = {
    totalSyncs: 0,
    successfulSyncs: 0,
    failedSyncs: 0,
    averageSyncTime: 0,
    totalDataTransferred: 0,
    conflictsResolved: 0
  };

  recordSync(success: boolean, duration: number, dataSize: number): void {
    this.metrics.totalSyncs += 1;
    
    if (success) {
      this.metrics.successfulSyncs += 1;
    } else {
      this.metrics.failedSyncs += 1;
    }

    this.metrics.totalDataTransferred += dataSize;
    
    // Calcular tempo médio
    const totalTime = this.metrics.averageSyncTime * (this.metrics.totalSyncs - 1) + duration;
    this.metrics.averageSyncTime = totalTime / this.metrics.totalSyncs;
  }

  recordConflictResolution(): void {
    this.metrics.conflictsResolved += 1;
  }

  getMetrics(): SyncMetrics {
    return { ...this.metrics };
  }

  async exportMetrics(): Promise<string> {
    return JSON.stringify(this.metrics, null, 2);
  }
}

export const metrics = new MetricsService();
```

## Considerações de Segurança

### 1. Criptografia de Dados Sensíveis

```typescript
// src/utils/encryption.ts
import CryptoJS from 'crypto-js';

export class DataEncryption {
  private static readonly SECRET_KEY = 'your-secret-key'; // Em produção, usar variável de ambiente

  static encrypt(data: string): string {
    return CryptoJS.AES.encrypt(data, this.SECRET_KEY).toString();
  }

  static decrypt(encryptedData: string): string {
    const bytes = CryptoJS.AES.decrypt(encryptedData, this.SECRET_KEY);
    return bytes.toString(CryptoJS.enc.Utf8);
  }

  static encryptObject(obj: any): string {
    return this.encrypt(JSON.stringify(obj));
  }

  static decryptObject<T>(encryptedData: string): T {
    const decrypted = this.decrypt(encryptedData);
    return JSON.parse(decrypted);
  }
}
```

### 2. Validação de Dados

```typescript
// src/utils/validation.ts
export class DataValidation {
  static validateDelivery(delivery: any): boolean {
    const requiredFields = ['id', 'outId', 'customerName', 'status'];
    
    for (const field of requiredFields) {
      if (!delivery[field]) {
        throw new Error(`Campo obrigatório ausente: ${field}`);
      }
    }

    // Validar status
    const validStatuses = ['pending', 'in_progress', 'delivered', 'failed'];
    if (!validStatuses.includes(delivery.status)) {
      throw new Error(`Status inválido: ${delivery.status}`);
    }

    return true;
  }

  static sanitizeData(data: any): any {
    // Remover campos desnecessários
    const sanitized = { ...data };
    delete sanitized.internalId;
    delete sanitized.tempData;
    
    return sanitized;
  }
}
```

## Conclusão

Esta estratégia de sincronização offline fornece uma solução completa e robusta para permitir que o aplicativo funcione sem dependência de internet. A implementação inclui:

1. **Sincronização inicial completa** para carregar todos os dados necessários
2. **Sincronização incremental** para manter dados atualizados
3. **Resolução automática de conflitos** com interface para resolução manual
4. **Fila de sincronização** com retry automático
5. **Monitoramento e logs** para debugging e análise
6. **Otimizações de performance** com compressão e cache
7. **Segurança** com criptografia e validação

A implementação pode ser feita de forma incremental, começando com a sincronização inicial e expandindo gradualmente para incluir todas as funcionalidades avançadas.
