import { api } from './api';
import { executeQuery, saveSetting, getSetting, getPendingDeliveryInvoices, markDeliveryInvoiceAsSynced } from './database';
import { offlineStorage } from './offlineStorage';
import { photoUploadService } from './photoUploadService';
import NetInfo from '@react-native-community/netinfo';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { API_BASE_URL, AUTH_TOKEN_KEY } from '@env';

export interface OfflineDelivery {
  id: string;
  outId: string;
  customerName: string;
  street: string;
  streetNumber: string;
  neighborhood: string;
  city: string;
  state: string;
  zipCode: string;
  customerPhone: string;
  lat: number;
  lng: number;
  deliverySeq: number;
  routing: number;
  status: string;
  outDate: string;
  notes?: string;
  photos?: string[];
  signature?: string;
  completedAt?: number;
  completedBy?: string;
  version: number;
  lastModified: number;
  syncTimestamp?: number;
}

export interface SyncResult {
  success: boolean;
  totalRecords: number;
  syncedRecords: number;
  failedRecords: number;
  errors: Array<{ recordId: string; error: string }>;
  duration: number;
}

export interface SyncStats {
  totalDeliveries: number;
  pendingDeliveries: number;
  syncedDeliveries: number;
  lastSyncTime: number | null;
  offlineMode: boolean;
}

class OfflineSyncService {
  private isOnline: boolean = true;
  private syncInProgress: boolean = false;

  constructor() {
    this.initializeNetworkListener();
  }

  private initializeNetworkListener() {
    NetInfo.addEventListener(state => {
      // Verificar se state existe e tem a propriedade isConnected
      if (state && typeof state.isConnected !== 'undefined') {
        this.isOnline = state.isConnected;
    // console.log('Status da rede:', this.isOnline ? 'Online' : 'Offline');
      } else {
        this.isOnline = false;
      }
    });
  }

  // Verificar se está online
  async checkConnectivity(): Promise<boolean> {
    try {
      const state = await NetInfo.fetch();
      if (state && typeof state.isConnected !== 'undefined') {
        return state.isConnected;
      } else {
        return false;
      }
    } catch (error) {
      return false;
    }
  }

  // Carregar dados iniciais (apenas online)
  async loadInitialData(): Promise<{ deliveries: OfflineDelivery[]; customers: any[]; invoices: any[] }> {
    if (!this.isOnline) {
      throw new Error('Conexão com internet necessária para carregar dados iniciais');
    }

    try {
      // console.log('=== CARREGANDO DADOS INICIAIS ===');
      
      // 0. Limpar todas as tabelas SQLite antes de carregar novos dados
      // console.log('=== LIMPANDO TABELAS SQLITE ANTES DO CARREGAMENTO ===');
      const { usingSQLite, executeQuery } = await import('../services/database');
      
      if (usingSQLite) {
        // console.log('🗑️ Limpando todas as tabelas SQLite...');
        await executeQuery('DELETE FROM deliveries');
        await executeQuery('DELETE FROM customers');
        await executeQuery('DELETE FROM customer_invoices');
        await executeQuery('DELETE FROM delivery_images');
        await executeQuery('DELETE FROM sync_queue');
        await executeQuery('DELETE FROM photo_uploads');
        await executeQuery('DELETE FROM sync_log');
        await executeQuery('DELETE FROM sync_conflicts');
        // console.log('✅ Todas as tabelas SQLite foram limpas');
      } else {
        // console.log('⚠️ SQLite não disponível, pulando limpeza das tabelas');
      }
      
      // 1. Carregar entregas
      const deliveries = await api.getDeliveries();
      // console.log(`Carregadas ${deliveries.length} entregas`);

      // 2. Carregar dados de clientes (se necessário)
      const customers = await this.loadCustomerData(deliveries);
      // console.log(`Carregados ${customers.length} clientes`);

      // 3. Carregar notas fiscais para todos os clientes
      // console.log('=== CARREGANDO NOTAS FISCAIS ===');
      const invoices = await this.loadAllCustomerInvoices(deliveries);
      // console.log(`Carregadas ${invoices.length} notas fiscais`);

      // 4. Salvar no banco local
      await this.saveDeliveriesToLocal(deliveries);
      await this.saveCustomersToLocal(customers);
      await this.saveInvoicesToLocal(invoices);

      // 5. Marcar como dados iniciais carregados
      await saveSetting('initial_data_loaded', 'true');
      await saveSetting('last_data_load', Date.now().toString());
      
      return { deliveries, customers, invoices };
    } catch (error) {
      throw new Error(`Falha ao carregar dados: ${error.message}`);
    }
  }

  // Carregar dados de clientes
  private async loadCustomerData(deliveries: any[]): Promise<any[]> {
    const customers: any[] = [];
    
    for (const delivery of deliveries) {
      try {
        // Buscar dados do cliente se necessário
        const customerData = {
          id: delivery.customerId || delivery.outId,
          name: delivery.customerName,
          address: {
            street: delivery.street,
            streetNumber: delivery.streetNumber,
            neighborhood: delivery.neighborhood,
            city: delivery.city,
            state: delivery.state,
            zipCode: delivery.zipCode,
          },
          phone: delivery.customerPhone,
          coordinates: {
            lat: delivery.lat,
            lng: delivery.lng,
          }
        };
        
        customers.push(customerData);
      } catch (error) {
        // Ignorar erro ao carregar dados do cliente
      }
    }
    
    return customers;
  }

  // Carregar notas fiscais de todos os clientes
  private async loadAllCustomerInvoices(deliveries: any[]): Promise<any[]> {
    const allInvoices: any[] = [];
    
    // Extrair clientes únicos das entregas
    const uniqueCustomers = new Map();
    
    for (const delivery of deliveries) {
      if (delivery.customerId && delivery.outId && !uniqueCustomers.has(delivery.customerId)) {
        uniqueCustomers.set(delivery.customerId, {
          customerId: delivery.customerId,
          outId: delivery.outId
        });
      }
    }
    
    // Carregar notas fiscais para cada cliente
    for (const [customerId, customerData] of uniqueCustomers) {
      try {
        const invoices = await api.getCustomerInvoices(customerData.outId, customerId);
        
        // Adicionar informações do cliente às notas fiscais
        const invoicesWithCustomer = invoices.map(invoice => ({
          ...invoice,
          customerId: customerId,
          outId: customerData.outId
        }));
        
        allInvoices.push(...invoicesWithCustomer);
        
        // Pequena pausa para não sobrecarregar a API
        await new Promise(resolve => setTimeout(resolve, 100));
        
      } catch (error) {
        // Continuar com outros clientes mesmo se um falhar
      }
    }
    return allInvoices;
  }

  // Salvar entregas no banco local (APENAS SQLite)
  private async saveDeliveriesToLocal(deliveries: any[]): Promise<void> {
    try {
      // Verificar se está usando SQLite
      const { usingSQLite, executeQuery } = await import('../services/database');
      
      if (!usingSQLite) {
        throw new Error('SQLite not available - app requires SQLite to function');
      }

        // Limpar entregas existentes
        await executeQuery('DELETE FROM deliveries');
        
        for (const delivery of deliveries) {
          await executeQuery(
            `INSERT OR REPLACE INTO deliveries (
              id, outId, customerId, customerName, street, streetNumber, neighborhood,
              city, state, zipCode, customerPhone, lat, lng, latFrom, lngFrom,
              deliverySeq, routing, sellerId, storeId, status, outDate, notes,
              signature, photos, completedTime, completedBy, version, lastModified, 
              syncTimestamp, syncStatus
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
            [
              delivery.id || delivery.outId, 
              delivery.outId, 
              delivery.customerId,
              delivery.customerName,
              delivery.street, 
              delivery.streetNumber, 
              delivery.neighborhood,
              delivery.city, 
              delivery.state, 
              delivery.zipCode,
              delivery.customerPhone, 
              delivery.lat, 
              delivery.lng,
              delivery.latFrom,
              delivery.lngFrom,
              delivery.deliverySeq, 
              delivery.routing, 
              delivery.sellerId,
              delivery.storeId,
              delivery.status,
              delivery.outDate, 
              delivery.notes || '', 
              null, // signature
              null, // photos
              null, // completedTime
              null, // completedBy
              1, // version
              Date.now(), // lastModified
              Date.now(), // syncTimestamp
              'synced' // syncStatus
            ]
          );
        }
    } catch (error) {
      throw error;
    }
  }

  // Salvar clientes no banco local
  private async saveCustomersToLocal(customers: any[]): Promise<void> {
    try {
      const { usingSQLite, executeQuery } = await import('../services/database');
      
      if (!usingSQLite) {
        throw new Error('SQLite not available');
      }

      // Limpar clientes existentes
      await executeQuery('DELETE FROM customers');
      
      for (const customer of customers) {
        await executeQuery(
          `INSERT OR REPLACE INTO customers (
            id, name, street, streetNumber, neighborhood, city, state,
            zipCode, phone, lat, lng, created_at
          ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
          [
            customer.id, customer.name, customer.address.street,
            customer.address.streetNumber, customer.address.neighborhood,
            customer.address.city, customer.address.state, customer.address.zipCode,
            customer.phone, customer.coordinates.lat, customer.coordinates.lng,
            Date.now()
          ]
        );
      }
    } catch (error) {
      throw error;
    }
  }

  // Salvar notas fiscais no banco local
  private async saveInvoicesToLocal(invoices: any[]): Promise<void> {
    try {
      const { usingSQLite, executeQuery } = await import('../services/database');
      
      if (!usingSQLite) {
        throw new Error('SQLite not available');
      }

        // Limpar notas fiscais existentes
        await executeQuery('DELETE FROM customer_invoices');
        
        for (const invoice of invoices) {
          await executeQuery(
            `INSERT OR REPLACE INTO customer_invoices (
              id, invoiceId, transactionId, customerId, customerName, invoiceValue, status, items, created_at, sync_status
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
            [
              `${invoice.customerId}-${invoice.invoiceId}`,
              invoice.invoiceId,
              invoice.transactionId,
              invoice.customerId,
              invoice.customerName,
              invoice.invoiceValue,
              invoice.status,
              JSON.stringify(invoice.itens || []),
              Date.now(),
              'synced'
            ]
          );
        }
    } catch (error) {
      throw error;
    }
  }

  // Completar entrega offline
  async completeDeliveryOffline(deliveryData: {
    deliveryId: string;
    status: string;
    photos?: string[];
    signature?: string;
    notes?: string;
    completedBy: string;
  }): Promise<void> {
    try {
      const now = Date.now();
      
      // 1. Atualizar entrega no banco local
      await executeQuery(
        `UPDATE deliveries SET 
          status = ?, notes = ?, completedTime = ?, completedBy = ?, 
          lastModified = ?, syncStatus = 'pending'
         WHERE id = ?`,
        [
          deliveryData.status, 
          deliveryData.notes || '', 
          now, 
          deliveryData.completedBy,
          now, 
          deliveryData.deliveryId
        ]
      );

      // 2. Adicionar fotos à fila de upload se existirem
      if (deliveryData.photos && deliveryData.photos.length > 0) {
        // Obter transactionId da entrega
        const deliveryResult = await executeQuery(
          'SELECT outId FROM deliveries WHERE id = ?',
          [deliveryData.deliveryId]
        );
        
        if (deliveryResult.rows.length > 0) {
          const transactionId = deliveryResult.rows._array[0].outId;
          
          // Adicionar cada foto à fila de upload
          for (const photoPath of deliveryData.photos) {
            await this.addPhotosToUpload(
              deliveryData.deliveryId,
              transactionId,
              [photoPath]
            );
          }
        }
      }

      // 3. Salvar assinatura offline se existir
      if (deliveryData.signature) {
        await this.saveSignatureOffline(deliveryData.deliveryId, deliveryData.signature);
      }

      // 4. Adicionar à fila de sincronização usando o novo sistema
      await this.addToSyncQueue({
        table_name: 'deliveries',
        record_id: deliveryData.deliveryId,
        action: 'UPDATE',
        data: {
          status: deliveryData.status,
          notes: deliveryData.notes,
          completedTime: now,
          completedBy: deliveryData.completedBy,
          signature: deliveryData.signature,
        },
        priority: 1
      });
    } catch (error) {
      throw error;
    }
  }

  // Salvar fotos offline
  private async savePhotosOffline(deliveryId: string, photos: string[]): Promise<void> {
    try {
      for (let i = 0; i < photos.length; i++) {
        const photoKey = `delivery_${deliveryId}_photo_${i}`;
        await offlineStorage.saveOfflineData('photos', photoKey, {
          deliveryId,
          photoIndex: i,
          photoUri: photos[i],
          timestamp: Date.now(),
        });
      }
    } catch (error) {
      throw error;
    }
  }

  // Salvar assinatura offline
  private async saveSignatureOffline(deliveryId: string, signature: string): Promise<void> {
    try {
      const signatureKey = `delivery_${deliveryId}_signature`;
      await offlineStorage.saveOfflineData('signatures', signatureKey, {
        deliveryId,
        signatureUri: signature,
        timestamp: Date.now(),
      });
    } catch (error) {
      throw error;
    }
  }

  // Adicionar à fila de sincronização
  private async addToSyncQueue(item: any): Promise<void> {
    try {
      await offlineStorage.addToSyncQueue(item);
    } catch (error) {
      throw error;
    }
  }

  // Obter entregas pendentes de envio
  async getPendingDeliveries(): Promise<any[]> {
    try {
      const { usingSQLite, executeQuery } = await import('../services/database');
      
      if (!usingSQLite) {
        return [];
      }

      const result = await executeQuery(`
        SELECT 
          d.*,
          COUNT(pu.id) as pendingPhotos,
          COUNT(di.id) as uploadedPhotos
        FROM deliveries d
        LEFT JOIN photo_uploads pu ON d.id = pu.deliveryId AND pu.uploadStatus = 'pending'
        LEFT JOIN delivery_images di ON d.id = di.deliveryId AND di.uploadStatus = 'uploaded'
        WHERE d.syncStatus = 'pending' 
           OR d.status IN ('delivered', 'failed', 'in_progress')
        GROUP BY d.id
        ORDER BY d.lastModified DESC
      `);
      
      const pendingDeliveries = result.rows._array.map(row => ({
        id: row.id,
        outId: row.outId,
        customerName: row.customerName,
        street: row.street,
        streetNumber: row.streetNumber,
        neighborhood: row.neighborhood,
        city: row.city,
        state: row.state,
        status: row.status,
        syncStatus: row.syncStatus,
        lastModified: row.lastModified,
        completedTime: row.completedTime,
        completedBy: row.completedBy,
        notes: row.notes,
        pendingPhotos: row.pendingPhotos || 0,
        uploadedPhotos: row.uploadedPhotos || 0,
        hasSignature: row.signature ? true : false
      }));
      
      return pendingDeliveries;
    } catch (error) {
      return [];
    }
  }

  // Sincronizar entregas específicas
  async syncSpecificDeliveries(deliveryIds: string[], skipLockCheck: boolean = false): Promise<SyncResult> {
    if (!this.isOnline) {
      throw new Error('Conexão com internet necessária para sincronização');
    }

    // Só verifica o lock se não estiver sendo chamado de dentro de outra sincronização
    if (!skipLockCheck && this.syncInProgress) {
      throw new Error('Sincronização já em andamento');
    }

    // Só seta o lock se não estiver já setado (para evitar resetar durante sincronização aninhada)
    const shouldSetLock = !this.syncInProgress;
    if (shouldSetLock) {
    this.syncInProgress = true;
    }
    const startTime = Date.now();

    try {
      console.log(`=== SINCRONIZANDO ${deliveryIds.length} ENTREGAS ESPECÍFICAS ===`);
      
      const result: SyncResult = {
        success: true,
        totalRecords: deliveryIds.length,
        syncedRecords: 0,
        failedRecords: 0,
        errors: [],
        duration: 0,
      };

      for (const deliveryId of deliveryIds) {
        try {
          await this.syncSingleDelivery(deliveryId);
          result.syncedRecords++;
        } catch (error) {
          result.failedRecords++;
          result.errors.push({
            recordId: deliveryId,
            error: error.message,
          });
        }
      }

      result.duration = Date.now() - startTime;
      result.success = result.failedRecords === 0;

      console.log('=== SINCRONIZAÇÃO ESPECÍFICA CONCLUÍDA ===');
      return result;

    } catch (error) {
      console.error('Erro na sincronização específica:', error);
      throw error;
    } finally {
      // Só libera o lock se foi este método que o setou
      if (shouldSetLock) {
      this.syncInProgress = false;
      }
    }
  }

  // Sincronizar todas as entregas pendentes
  async syncAllPendingDeliveries(): Promise<SyncResult> {
    if (!this.isOnline) {
      throw new Error('Conexão com internet necessária para sincronização');
    }

    if (this.syncInProgress) {
      throw new Error('Sincronização já em andamento');
    }

    this.syncInProgress = true;
    const startTime = Date.now();

    try {
      console.log('=== SINCRONIZANDO TODAS AS ENTREGAS PENDENTES ===');
      
      const result: SyncResult = {
        success: false,
        totalRecords: 0,
        syncedRecords: 0,
        failedRecords: 0,
        errors: []
      };

      // 1. Sincronizar entregas individuais por nota fiscal primeiro
      console.log('=== SINCRONIZANDO ENTREGAS INDIVIDUAIS POR NOTA FISCAL ===');
      try {
        const deliveryInvoicesResult = await this.syncDeliveryInvoices();
        result.totalRecords += deliveryInvoicesResult.totalRecords;
        result.syncedRecords += deliveryInvoicesResult.syncedRecords;
        result.failedRecords += deliveryInvoicesResult.failedRecords;
        result.errors.push(...deliveryInvoicesResult.errors);
        console.log('✅ Entregas individuais sincronizadas:', deliveryInvoicesResult.syncedRecords);
      } catch (error) {
        console.error('❌ Erro ao sincronizar entregas individuais:', error);
        result.errors.push({
          recordId: 'delivery_invoices',
          error: error.message
        });
      }
      
      // 2. Sincronizar entregas principais
      console.log('=== SINCRONIZANDO ENTREGAS PRINCIPAIS ===');
      try {
        const pendingDeliveries = await this.getPendingDeliveries();
        const deliveryIds = pendingDeliveries.map(d => d.id);
        
        // Passar skipLockCheck=true porque já estamos dentro de uma sincronização
        const deliveriesResult = await this.syncSpecificDeliveries(deliveryIds, true);
        result.totalRecords += deliveriesResult.totalRecords;
        result.syncedRecords += deliveriesResult.syncedRecords;
        result.failedRecords += deliveriesResult.failedRecords;
        result.errors.push(...deliveriesResult.errors);
        console.log('✅ Entregas principais sincronizadas:', deliveriesResult.syncedRecords);
      } catch (error) {
        console.error('❌ Erro ao sincronizar entregas principais:', error);
        result.errors.push({
          recordId: 'deliveries',
          error: error.message
        });
      }

      result.duration = Date.now() - startTime;
      result.success = result.failedRecords === 0;

      console.log('=== SINCRONIZAÇÃO COMPLETA CONCLUÍDA ===');
      console.log('📊 Resultado final:', {
        totalRecords: result.totalRecords,
        syncedRecords: result.syncedRecords,
        failedRecords: result.failedRecords,
        success: result.success
      });
      
      return result;

    } catch (error) {
      console.error('Erro na sincronização completa:', error);
      throw error;
    } finally {
      this.syncInProgress = false;
    }
  }

  // Sincronizar entrega individual
  private async syncSingleDelivery(deliveryId: string): Promise<void> {
    try {
      // 1. Buscar dados da entrega
      const delivery = await this.getDeliveryById(deliveryId);
      if (!delivery) {
        throw new Error(`Entrega ${deliveryId} não encontrada`);
      }

      // 2. Buscar fotos offline
      const photos = await this.getOfflinePhotos(deliveryId);

      // 3. Buscar assinatura offline
      const signature = await this.getOfflineSignature(deliveryId);

      // 4. Preparar dados para envio
      // Para entregas já finalizadas, usar o endpoint de atualização de status
      const { api } = await import('./api');
      
      // Adicionar timeout para evitar travamentos
      const apiCallPromise = (async () => {
        if (delivery.status === 'delivered' || delivery.status === 'failed') {
          // Atualizar status da entrega
          return await api.updateDeliveryStatus({
            outId: parseInt(delivery.outId),
            customerId: parseInt(delivery.customerId),
            status: delivery.status === 'delivered' ? 'delivered' : 'failed',
            lat: delivery.lat ? parseFloat(delivery.lat.toString()) : null,
            lng: delivery.lng ? parseFloat(delivery.lng.toString()) : null,
            notes: delivery.notes || ''
          });
        } else {
          // Para entregas em progresso, criar nova entrega
      const deliveryData = {
        ...delivery,
        photos,
        signature,
        completedAt: delivery.lastModified,
      };

          return await api.createDelivery(deliveryData);
        }
      })();
      
      // Timeout de 30 segundos para a chamada da API
      const timeoutPromise = new Promise((_, reject) => {
        setTimeout(() => reject(new Error('Timeout: A chamada da API demorou mais de 30 segundos')), 30000);
      });
      
      await Promise.race([apiCallPromise, timeoutPromise]);

      // 5. Marcar como sincronizada
      await executeQuery(
        'UPDATE deliveries SET syncStatus = ?, syncTimestamp = ? WHERE id = ?',
        ['synced', Date.now(), deliveryId]
      );

      // 6. Remover da fila de sincronização
      await this.removeFromSyncQueue(deliveryId);

    } catch (error) {
      console.error(`❌ Erro ao sincronizar entrega ${deliveryId}:`, error);
      throw error;
    }
  }

  // Buscar entrega por ID
  private async getDeliveryById(deliveryId: string): Promise<OfflineDelivery | null> {
    try {
      const result = await executeQuery(
        'SELECT * FROM deliveries WHERE id = ?',
        [deliveryId]
      );
      
      if (result.rows && result.rows._array && result.rows._array.length > 0) {
        return result.rows._array[0] as OfflineDelivery;
      }
      return null;
    } catch (error) {
      return null;
    }
  }

  // Buscar entregas pendentes
  private async getPendingDeliveries(): Promise<OfflineDelivery[]> {
    try {
      const result = await executeQuery(
        'SELECT * FROM deliveries WHERE syncTimestamp IS NULL OR syncTimestamp < lastModified'
      );
      return result.rows._array as OfflineDelivery[];
    } catch (error) {
      return [];
    }
  }

  // Buscar fotos offline do SQLite
  private async getOfflinePhotos(deliveryId: string): Promise<string[]> {
    try {
      // Buscar fotos da tabela photo_uploads no SQLite
      const { getPendingPhotoUploads } = await import('./database');
      const allPendingUploads = await getPendingPhotoUploads();
      
      // Filtrar fotos da entrega específica
      const deliveryPhotos = allPendingUploads.filter(
        upload => upload.deliveryId === deliveryId && upload.localPath
      );
      
      const photoPaths = deliveryPhotos.map(upload => upload.localPath);
      
      return photoPaths;
    } catch (error) {
      return [];
    }
  }

  // Buscar assinatura offline do SQLite
  private async getOfflineSignature(deliveryId: string): Promise<string | null> {
    try {
      // Buscar assinatura da tabela deliveries no SQLite
      const { executeQuery } = await import('./database');
      const result = await executeQuery(
        'SELECT signature FROM deliveries WHERE id = ?',
        [deliveryId]
      );
      
      if (result.rows && result.rows._array && result.rows._array.length > 0) {
        const signature = result.rows._array[0].signature;
        return signature || null;
      }
      
      return null;
    } catch (error) {
      return null;
    }
  }

  // Remover da fila de sincronização (não necessário mais, pois usamos SQLite)
  private async removeFromSyncQueue(deliveryId: string): Promise<void> {
    try {
      // A fila de sincronização agora é gerenciada pelo SQLite através do syncStatus
      // Não precisamos mais remover do AsyncStorage
    } catch (error) {
      // Não lançar erro, pois não é crítico
    }
  }

  // Obter estatísticas de sincronização
  async getSyncStats(): Promise<SyncStats> {
    try {
      // Total de entregas na tabela deliveries
      const totalResult = await executeQuery('SELECT COUNT(*) as count FROM deliveries');
      const totalDeliveries = totalResult.rows._array[0]?.count || 0;
      
      // Entregas individuais pendentes (delivery_invoices com syncStatus = 'pending')
      // Esta é a contagem correta, pois a sincronização funciona com delivery_invoices
      const pendingDeliveryInvoicesResult = await executeQuery(
        `SELECT COUNT(*) as count FROM delivery_invoices 
         WHERE syncStatus = 'pending'`
      );
      const pendingDeliveries = pendingDeliveryInvoicesResult.rows._array[0]?.count || 0;
      
      // Entregas sincronizadas: entregas que não têm nenhuma delivery_invoice pendente
      // OU entregas que têm todas as delivery_invoices sincronizadas
      const syncedResult = await executeQuery(
        `SELECT COUNT(DISTINCT d.id) as count 
         FROM deliveries d
         LEFT JOIN delivery_invoices di ON d.id = di.deliveryId AND di.syncStatus = 'pending'
         WHERE di.id IS NULL
         AND d.status IN ('delivered', 'failed', 'absent', 'refused')`
      );
      const syncedDeliveries = syncedResult.rows._array[0]?.count || 0;
      
      const lastSyncTime = await getSetting('last_sync_time');
  
      const stats = {
        totalDeliveries,
        pendingDeliveries,
        syncedDeliveries,
        lastSyncTime: lastSyncTime ? parseInt(lastSyncTime) : null,
        offlineMode: !this.isOnline,
      };
      
      return stats;
    } catch (error) {
      return {
        totalDeliveries: 0,
        pendingDeliveries: 0,
        syncedDeliveries: 0,
        lastSyncTime: null,
        offlineMode: true,
      };
    }
  }

  // Sincronizar entregas individuais por nota fiscal - NOVA IMPLEMENTAÇÃO
  async syncDeliveryInvoices(): Promise<SyncResult> {
      const result: SyncResult = {
        success: false,
        totalRecords: 0,
        syncedRecords: 0,
        failedRecords: 0,
      errors: [],
      duration: 0
    };

    const startTime = Date.now();

    try {
      if (!this.isOnline) {
        throw new Error('Dispositivo offline');
      }

      const { executeQuery } = await import('./database');
      const { api } = await import('./api');
      const { markDeliveryInvoiceAsSynced, saveDeliveryInvoice } = await import('./database');

      // 1. Buscar entregas pendentes (mas não retornar ainda - fazer upload de fotos primeiro)
      let pendingDeliveryInvoices = await getPendingDeliveryInvoices();

      // 2. Se não há entregas individuais, verificar se há entregas principais com fotos pendentes
      // (mas continuar para fazer upload de fotos mesmo assim)
      if (pendingDeliveryInvoices.length === 0) {
        // Buscar entregas principais que foram finalizadas mas não têm delivery_invoices
        const deliveriesWithPhotos = await executeQuery(
          `SELECT DISTINCT d.*, pu.transactionId
           FROM deliveries d
           INNER JOIN photo_uploads pu ON d.id = pu.deliveryId
           WHERE d.status IN ('delivered', 'failed')
           AND d.syncStatus = 'pending'
           AND pu.serverUrl IS NULL
           AND pu.uploadStatus IN ('pending', 'failed')
           ORDER BY d.lastModified DESC
           LIMIT 10`
        );
        
        const deliveries = deliveriesWithPhotos.rows._array || [];
        
        // Criar delivery_invoices para essas entregas
        for (const delivery of deliveries) {
          try {
            // Buscar transactionId das fotos
            const photosResult = await executeQuery(
              `SELECT DISTINCT transactionId FROM photo_uploads 
               WHERE deliveryId = ? AND transactionId IS NOT NULL
               LIMIT 1`,
              [delivery.id]
            );
            
            if (photosResult.rows._array && photosResult.rows._array.length > 0) {
              const transactionId = photosResult.rows._array[0].transactionId;
              const deliveryInvoiceId = `${delivery.id}-${transactionId}-0`;
              
              // Verificar se já existe
              const existsResult = await executeQuery(
                'SELECT id FROM delivery_invoices WHERE id = ?',
                [deliveryInvoiceId]
              );
              
              if (!existsResult.rows._array || existsResult.rows._array.length === 0) {
                // Criar delivery_invoice
                await saveDeliveryInvoice({
                  id: deliveryInvoiceId,
                  deliveryId: delivery.id,
                  outId: delivery.outId.toString(),
                  transactionId: transactionId,
                  deliveryDate: new Date().toISOString(),
                  receiverDoc: '',
                  receiverName: delivery.customerName || '',
                  lat: delivery.lat?.toString() || '',
                  lng: delivery.lng?.toString() || '',
                  broken: false,
                  devolution: false,
                  reasonDevolution: '',
                  deliveryImages: JSON.stringify([]),
                  userId: parseInt(delivery.completedBy || '0')
                });
              }
            }
          } catch (e: any) {
            // Ignorar erro ao criar delivery_invoice
          }
        }
        
        // Buscar novamente após criar os registros
        pendingDeliveryInvoices = await getPendingDeliveryInvoices();
      }

      // 3. Obter coordenadas do GPS (fazer antes do upload de fotos para não atrasar)
      let gpsLat: string | null = null;
      let gpsLng: string | null = null;
      try {
        const Location = await import('expo-location');
        const { status } = await Location.requestForegroundPermissionsAsync();
        if (status === 'granted') {
          const location = await Location.getCurrentPositionAsync({
            accuracy: Location.Accuracy.High,
          });
          gpsLat = location.coords.latitude.toString();
          gpsLng = location.coords.longitude.toString();
        }
      } catch (e) {
        // Ignorar erro ao obter GPS
      }

      // 4. Fazer upload de TODAS as fotos pendentes usando o endpoint correto
      // IMPORTANTE: Fazer isso ANTES de verificar se há entregas pendentes,
      // pois as fotos precisam estar no servidor antes de sincronizar
      console.log('📸 INICIANDO UPLOAD DE FOTOS PENDENTES');
      
      try {
        // Buscar todas as fotos pendentes agrupadas por transactionId
        const pendingPhotosResult = await executeQuery(
          `SELECT * FROM photo_uploads 
           WHERE uploadStatus IN ('pending', 'failed') 
           AND serverUrl IS NULL
           ORDER BY transactionId, created_at ASC`
        );
        
        const pendingPhotos = pendingPhotosResult.rows._array || [];

      if (pendingPhotos.length > 0) {
        // Agrupar por transactionId
        const photosByTransaction: { [key: number]: any[] } = {};
        for (const photo of pendingPhotos) {
          const tid = photo.transactionId;
          if (!photosByTransaction[tid]) {
            photosByTransaction[tid] = [];
          }
          photosByTransaction[tid].push(photo);
        }

        // Enviar fotos por transactionId
        for (const [transactionIdStr, photos] of Object.entries(photosByTransaction)) {
          const transactionId = parseInt(transactionIdStr);
          try {
            console.log(`📤 Enviando ${photos.length} foto(s) para transactionId ${transactionId}`);

            // Preparar array de URIs das fotos
            const fileUris: string[] = [];
            for (const photo of photos) {
              // Verificar se o arquivo existe
              const FileSystem = await import('expo-file-system/legacy');
              const fileInfo = await FileSystem.getInfoAsync(photo.localPath);
              if (fileInfo.exists) {
                fileUris.push(photo.localPath);
              }
            }

            if (fileUris.length === 0) {
              continue;
            }

            // Enviar para o endpoint /api/v1/base/send-image
            // Usar a mesma abordagem que api.ts para obter token e API_BASE_URL
            // AUTH_TOKEN_KEY e API_BASE_URL já estão importados no topo do arquivo
            
            // Buscar token usando a mesma chave que api.ts usa
            const token = await AsyncStorage.getItem(AUTH_TOKEN_KEY);
            
            if (!token) {
              throw new Error('Token não encontrado');
            }
            
            const endpoint = `${API_BASE_URL}/api/v1/base/send-image`;

            // Preparar FormData (React Native usa FormData global)
            const formData = new FormData();
            
            // Adicionar cada arquivo
            for (const uri of fileUris) {
              formData.append('files', {
                uri: uri,
                type: 'image/jpeg',
                name: `delivery_${transactionId}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}.jpg`
              } as any);
            }
            
            // Adicionar transactionId
            formData.append('transactionId', transactionId.toString());

            const response = await fetch(endpoint, {
              method: 'POST',
              headers: {
                'Authorization': `Bearer ${token}`,
                // Não definir Content-Type - o fetch define automaticamente para FormData
              },
              body: formData as any,
            });

            const responseText = await response.text();

            if (!response.ok) {
              throw new Error(`Erro no upload: ${response.status} - ${responseText}`);
            }

            let result: any;
            try {
              result = JSON.parse(responseText);
            } catch (e) {
              throw new Error('Erro ao parsear resposta do servidor');
            }

            if (!result.success) {
              throw new Error(result.message || 'Erro no upload');
            }

            // Processar URLs retornadas conforme formato da API
            // Formato esperado: { success: true, urls: [...], transactionId: 1234567890 }
            let urls: string[] = [];
            
            if (result.urls && Array.isArray(result.urls)) {
              // Formato: { success: true, urls: ["url1", "url2"], transactionId: 123 }
              urls = result.urls;
            } else if (result.data && Array.isArray(result.data)) {
              // Formato alternativo: { success: true, data: [{ url: "..." }] }
              urls = result.data.map((item: any) => item.url || item);
            } else if (result.data && typeof result.data === 'string') {
              // Formato alternativo: { success: true, data: "url" }
              urls = [result.data];
            }

            console.log(`✅ Upload concluído: ${urls.length} URL(s) recebida(s)`);

            // Atualizar banco com as URLs retornadas
            if (urls.length > 0) {
              for (let i = 0; i < photos.length && i < urls.length; i++) {
                const photo = photos[i];
                const url = urls[i];
                
                if (url && typeof url === 'string') {
                  await executeQuery(
                    `UPDATE photo_uploads 
                     SET serverUrl = ?, uploadStatus = 'completed', uploadProgress = 100, uploadAttempts = uploadAttempts + 1
                     WHERE id = ?`,
                    [url, photo.id]
                  );
                }
              }
            }

          } catch (error: any) {
            console.error(`❌ Erro ao enviar fotos para transactionId ${transactionId}:`, error.message);
            // Marcar como failed mas continuar
            for (const photo of photos) {
              await executeQuery(
                `UPDATE photo_uploads 
                 SET uploadStatus = 'failed', errorMessage = ?
                 WHERE id = ?`,
                [error.message || 'Erro no upload', photo.id]
              );
            }
          }
        }

        console.log('✅ Processo de upload de fotos concluído');
      }
      } catch (uploadError: any) {
        console.error('❌ Erro crítico no processo de upload de fotos:', uploadError.message);
        // Continuar mesmo com erro - não bloquear a sincronização
      }

      // 5. Verificar se há entregas pendentes após upload de fotos
      if (pendingDeliveryInvoices.length === 0) {
        result.success = true;
        result.duration = Date.now() - startTime;
        return result;
      }

      // 6. Preparar array de entregas
      const deliveriesArray: any[] = [];
      const invoiceMap = new Map<string, any>(); // Mapear invoice.id para invoice

      for (const invoice of pendingDeliveryInvoices) {
        try {
          console.log(`📦 Preparando entrega: ${invoice.id} (transactionId atual: ${invoice.transactionId})`);

          // Validar/obter transactionId correto das notas fiscais da API
          let correctTransactionId = invoice.transactionId;
          try {
            console.log(`🔍 Validando transactionId para outId: ${invoice.outId}, customerId: ${invoice.deliveryId}`);
            
            // Buscar delivery para obter customerId
            const deliveryResult = await executeQuery(
              'SELECT customerId FROM deliveries WHERE id = ?',
              [invoice.deliveryId]
            );
            
            if (deliveryResult.rows._array && deliveryResult.rows._array.length > 0) {
              const customerId = deliveryResult.rows._array[0].customerId;
              const outId = parseInt(invoice.outId);
              
              if (customerId && outId) {
                console.log(`📡 Buscando notas fiscais da API para outId: ${outId}, customerId: ${customerId}`);
                
                // Buscar notas fiscais da API para validar transactionId
                const { api } = await import('./api');
                const customerInvoices = await api.getCustomerInvoices(outId, parseInt(customerId));
                
                console.log(`📋 Notas fiscais encontradas: ${customerInvoices.length}`);
                console.log(`📋 Notas fiscais da API:`, JSON.stringify(customerInvoices.map((inv: any) => ({
                  transactionId: inv.transactionId,
                  invoiceDeliveryId: inv.invoiceDeliveryId,
                  invoiceId: inv.invoiceId
                })), null, 2));
                console.log(`📋 TransactionId salvo na tabela: ${invoice.transactionId}`);
                
                // Procurar a nota fiscal que corresponde ao transactionId salvo
                let matchingInvoice = customerInvoices.find((inv: any) => 
                  inv.transactionId === parseInt(invoice.transactionId) || 
                  inv.transactionId === invoice.transactionId
                );
                
                // Se não encontrou por transactionId, tentar por invoiceDeliveryId
                if (!matchingInvoice) {
                  const invoiceIdParts = invoice.id.split('-');
                  if (invoiceIdParts.length > 1) {
                    const savedTransactionId = parseInt(invoiceIdParts[1]);
                    matchingInvoice = customerInvoices.find((inv: any) => 
                      inv.transactionId === savedTransactionId
                    );
                  }
                }
                
                if (matchingInvoice && matchingInvoice.transactionId) {
                  correctTransactionId = matchingInvoice.transactionId;
                  console.log(`✅ TransactionId validado da API: ${correctTransactionId} (era: ${invoice.transactionId})`);
                } else if (customerInvoices.length > 0) {
                  // Se não encontrou correspondência, usar a primeira nota fiscal (mais recente)
                  correctTransactionId = customerInvoices[0].transactionId;
                  console.log(`⚠️ TransactionId salvo (${invoice.transactionId}) não encontrado na API, usando primeira nota fiscal: ${correctTransactionId}`);
                  console.log(`⚠️ Isso pode indicar que o transactionId foi alterado ou a nota fiscal foi atualizada na API`);
                } else {
                  console.log(`⚠️ Nenhuma nota fiscal encontrada na API, mantendo transactionId original: ${correctTransactionId}`);
                }
              }
            }
          } catch (validationError: any) {
            console.error(`⚠️ Erro ao validar transactionId, usando valor salvo:`, validationError.message);
            // Continuar com o transactionId salvo se houver erro na validação
          }

          // Buscar fotos com URL para este transactionId (usar o correto)
          const transactionIdToUse = correctTransactionId;
          console.log(`📸 Buscando fotos para transactionId: ${transactionIdToUse}`);
          const photosResult = await executeQuery(
            `SELECT serverUrl FROM photo_uploads 
             WHERE transactionId = ? AND serverUrl IS NOT NULL
             ORDER BY created_at ASC`,
            [transactionIdToUse]
          );

          const photos = photosResult.rows._array || [];
          const deliveryImages: any[] = [];

          // Adicionar fotos do tipo EN
          for (const photo of photos) {
            if (photo.serverUrl && !deliveryImages.some(img => img.url === photo.serverUrl)) {
              deliveryImages.push({
                type: 'EN',
                url: photo.serverUrl
              });
            }
          }

          // Buscar assinatura
          const sigResult = await executeQuery(
            'SELECT signature FROM deliveries WHERE id = ?',
            [invoice.deliveryId]
          );

          if (sigResult.rows._array?.[0]?.signature) {
            const sig = sigResult.rows._array[0].signature;
            if (sig.startsWith('http') || sig.length > 100) {
              deliveryImages.push({
                type: 'SIG',
                url: sig
              });
            }
          }

          // Montar payload exato conforme API
          // Garantir tipos corretos: outId, transactionId e userId como números; lat/lng como strings
          // IMPORTANTE: Usar o transactionId validado da API
          const payload: any = {
            outId: parseInt(invoice.outId) || 0,
            transactionId: parseInt(transactionIdToUse) || 0,
            deliveryDate: invoice.deliveryDate || new Date().toISOString(),
            receiverDoc: invoice.receiverDoc || '',
            receiverName: invoice.receiverName || '',
            lat: (gpsLat || (invoice.lat ? invoice.lat.toString() : '')).toString(),
            lng: (gpsLng || (invoice.lng ? invoice.lng.toString() : '')).toString(),
            broken: invoice.broken === true || invoice.broken === 1,
            devolution: invoice.devolution === true || invoice.devolution === 1,
            reasonDevolution: (invoice.devolution === true || invoice.devolution === 1) 
              ? (invoice.reasonDevolution || null) 
              : null,
            deliveryImages: deliveryImages || [],
            userId: parseInt(invoice.userId) || 0
          };

          console.log(`📦 Payload preparado para entrega ${invoice.id}:`, JSON.stringify(payload, null, 2));
          console.log(`   - outId: ${payload.outId} (${typeof payload.outId})`);
          console.log(`   - transactionId: ${payload.transactionId} (${typeof payload.transactionId})`);
          console.log(`   - userId: ${payload.userId} (${typeof payload.userId})`);
          console.log(`   - lat: "${payload.lat}" (${typeof payload.lat})`);
          console.log(`   - lng: "${payload.lng}" (${typeof payload.lng})`);
          console.log(`   - devolution: ${payload.devolution} (${typeof payload.devolution})`);
          console.log(`   - reasonDevolution: ${payload.reasonDevolution}`);
          console.log(`   - deliveryImages: ${payload.deliveryImages.length} imagem(ns)`);

          deliveriesArray.push(payload);
          invoiceMap.set(invoice.id, invoice); // Armazenar referência do invoice
          result.totalRecords++;
          // Não incrementar syncedRecords aqui - será incrementado apenas após envio bem-sucedido

        } catch (error: any) {
          console.error(`❌ Erro ao preparar entrega ${invoice.id}:`, error.message);
          result.failedRecords++;
          result.errors.push({
            recordId: invoice.id,
            error: error.message || 'Erro desconhecido'
          });
          result.totalRecords++;
        }
      }

      // 7. Enviar todas as entregas como array para /v1/delivery/create
      if (deliveriesArray.length > 0) {
        console.log('🚀 ENVIANDO DADOS PARA API');
        console.log(`📦 Total de entregas para sincronizar: ${deliveriesArray.length}`);
        console.log(`📍 Endpoint: ${API_BASE_URL}/v1/delivery/create`);
        console.log(`📦 Payload completo (array):`, JSON.stringify(deliveriesArray, null, 2));
        
        try {
          // Validar estrutura do payload antes de enviar
          deliveriesArray.forEach((delivery, index) => {
            console.log(`✅ Validação entrega ${index + 1}:`, {
              outId: delivery.outId,
              transactionId: delivery.transactionId,
              userId: delivery.userId,
              deliveryImages: delivery.deliveryImages?.length || 0,
              lat: delivery.lat,
              lng: delivery.lng,
              devolution: delivery.devolution,
              reasonDevolution: delivery.reasonDevolution
            });
          });

          // Enviar todas as entregas como array usando createMultipleDeliveries
          console.log(`📤 Enviando ${deliveriesArray.length} entrega(s) para API...`);
          await api.createMultipleDeliveries(deliveriesArray);
          
          console.log(`✅ ${deliveriesArray.length} entrega(s) enviada(s) com sucesso!`);
          
          // Marcar todas as entregas enviadas como sincronizadas
          // Usar o invoiceMap para garantir que marcamos apenas as que foram enviadas
          for (const [invoiceId, invoice] of invoiceMap.entries()) {
            try {
              await markDeliveryInvoiceAsSynced(invoiceId);
              result.syncedRecords++;
              console.log(`✅ Entrega ${invoiceId} marcada como sincronizada`);
            } catch (markError: any) {
              console.error(`⚠️ Erro ao marcar entrega ${invoiceId} como sincronizada:`, markError.message);
              result.failedRecords++;
              result.errors.push({
                recordId: invoiceId,
                error: `Erro ao marcar como sincronizada: ${markError.message}`
              });
            }
          }
          
        } catch (error: any) {
          console.error(`❌ Erro ao enviar array de entregas:`, error.message);
          console.error(`❌ Stack trace:`, error.stack);
          result.failedRecords += deliveriesArray.length;
          result.errors.push({
            recordId: 'batch_sync',
            error: error.message || 'Erro ao enviar array de entregas para API'
          });
        }
      }

      result.success = result.failedRecords === 0;
      result.duration = Date.now() - startTime;
      
      console.log('📊 RESULTADO DA SINCRONIZAÇÃO:');
      console.log(`   Total: ${result.totalRecords} | Sincronizadas: ${result.syncedRecords} | Falhas: ${result.failedRecords}`);

      return result;

    } catch (error: any) {
      console.error('❌ Erro geral na sincronização:', error.message);
      result.duration = Date.now() - startTime;
      throw error;
    }
  }

  // Verificar se dados iniciais foram carregados
  async isInitialDataLoaded(): Promise<boolean> {
    try {
      const result = await getSetting('initial_data_loaded');
      return result === 'true';
    } catch (error) {
      return false;
    }
  }

  // Resetar dados iniciais - LIMPEZA COMPLETA SEMPRE
  async resetInitialData(): Promise<void> {
    try {
      // Resetar configurações IMEDIATAMENTE
      await saveSetting('initial_data_loaded', 'false');
      await saveSetting('last_data_load', '0');
      await saveSetting('last_sync_time', '0');
      await saveSetting('force_initial_load', 'true');
      
      // Verificar se SQLite está disponível antes de limpar dados
      const { usingSQLite, executeQuery } = await import('../services/database');
      
      if (usingSQLite) {
        // Lista completa de todas as tabelas para limpar
        const tablesToClean = [
          'deliveries',
          'customers', 
          'customer_invoices',
          'delivery_images',
          'sync_queue',
          'photo_uploads',
          'sync_log',
          'sync_conflicts',
          'settings' // Limpar também as configurações
        ];
        
        // Limpar cada tabela individualmente
        for (const table of tablesToClean) {
          try {
            await executeQuery(`DELETE FROM ${table}`);
          } catch (tableError) {
            // Continuar mesmo se uma tabela falhar
          }
        }
      }
      
    } catch (error) {
      throw error;
    }
  }

  // Verificar se está em modo offline
  isOfflineMode(): boolean {
    return !this.isOnline;
  }

  // Verificar se sincronização está em progresso
  isSyncInProgress(): boolean {
    return this.syncInProgress;
  }

  /**
   * Adiciona fotos à fila de upload
   */
  async addPhotosToUpload(
    deliveryId: string,
    transactionId: number,
    photoPaths: string[]
  ): Promise<string[]> {
    try {
      const uploadIds: string[] = [];
      
      for (const photoPath of photoPaths) {
        const uploadId = await photoUploadService.addPhotoToUpload(
          deliveryId,
          transactionId,
          photoPath
        );
        uploadIds.push(uploadId);
      }
      
      return uploadIds;
    } catch (error) {
      return [];
    }
  }

  /**
   * Obtém estatísticas de upload de fotos
   */
  async getPhotoUploadStats(): Promise<{
    pending: number;
    uploading: number;
    completed: number;
    failed: number;
    total: number;
  }> {
    try {
      return await photoUploadService.getUploadStats();
    } catch (error) {
      return {
        pending: 0,
        uploading: 0,
        completed: 0,
        failed: 0,
        total: 0
      };
    }
  }

  /**
   * Retry uploads falhados
   */
  async retryFailedPhotoUploads(): Promise<void> {
    try {
      await photoUploadService.retryFailedUploads();
    } catch (error) {
      // Ignorar erro
    }
  }

  /**
   * Processa upload de fotos pendentes
   */
  async processPhotoUploads(): Promise<void> {
    try {
      await photoUploadService.checkConnectivityAndProcessQueue();
    } catch (error) {
      // Ignorar erro
    }
  }
}

export const offlineSyncService = new OfflineSyncService();
