"use client"

import React, { createContext, useContext, useState, useCallback, useRef, useEffect } from 'react'
import { api, sortDeliveriesBySequence, optimizeRouteWithTSP } from '../services/api'
import { Delivery } from '../types'
import { useOfflineMode } from './OfflineModeContext'
import { getDeliveriesFromLocal, getNextDeliveryFromLocal } from '../services/database'

// Interface para o contexto
interface DeliveriesContextData {
  deliveries: Delivery[]
  loading: boolean
  error: string | null
  hasNoDeliveries: boolean
  refreshDeliveries: () => Promise<void>
  forceRefresh: () => Promise<void>
  lastRefreshTime: number | null
  isRefreshing: boolean
  updateDeliveriesWithRandomSeq: (deliveries: Delivery[]) => void
  getNextDelivery: () => Delivery | null
}

// Criar o contexto
const DeliveriesContext = createContext<DeliveriesContextData>({} as DeliveriesContextData)

// Hook para usar o contexto
export const useDeliveries = () => useContext(DeliveriesContext)

// Provedor do contexto
export const DeliveriesProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [deliveries, setDeliveries] = useState<Delivery[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  const [hasNoDeliveries, setHasNoDeliveries] = useState(false)
  const [lastRefreshTime, setLastRefreshTime] = useState<number | null>(null)
  const [isRefreshing, setIsRefreshing] = useState(false)
  const isRefreshingRef = useRef(false) // Ref para evitar loop
  const hasInitializedRef = useRef(false) // Ref para controlar carregamento inicial
  
  // Integração com sistema offline
  const { isInitialDataLoaded, isOfflineMode, registerDeliveryStatusCallback } = useOfflineMode()

  // Carregar dados automaticamente quando sistema offline estiver pronto
  useEffect(() => {
    if (isInitialDataLoaded) {
      hasInitializedRef.current = true
      
      // Adicionar um pequeno delay para garantir que o contexto esteja totalmente atualizado
      setTimeout(() => {
        loadDeliveries(false)
      }, 100)
    }
  }, [isInitialDataLoaded])

  // Função para carregar entregas com roteamento automático
  const loadDeliveries = useCallback(async (forceRefresh = false) => {
    // Evitar múltiplas chamadas simultâneas usando ref para evitar loop
    if (isRefreshingRef.current && !forceRefresh) {
      return
    }

    try {
      isRefreshingRef.current = true
      setIsRefreshing(true)
      setLoading(true)
      setError(null)

      let data: Delivery[] = []

      // SEMPRE tentar dados locais primeiro, independente do estado
      try {
        data = await getDeliveriesFromLocal()
        if (data && data.length > 0) {
          // Usando dados locais
        } else {
          data = await api.getDeliveries()
        }
      } catch (error) {
        data = await api.getDeliveries()
      }

      // Verificar se a API retornou uma lista vazia
      if (data.length === 0) {
        // console.log("=== API RETORNOU LISTA VAZIA - NÃO EXISTEM ENTREGAS ===")
        setDeliveries([])
        setHasNoDeliveries(true)
        setError("Não existem entregas disponíveis no momento.")
        setLastRefreshTime(Date.now())
        return
      }

      // Verificar se há entregas que precisam de roteamento (routing !== 0)
      // SÓ EXECUTAR ROTEAMENTO SE ESTIVER ONLINE E NÃO FOR DADOS LOCAIS
      const deliveriesNeedingRouting = data.filter(delivery => delivery.routing && delivery.routing !== 0)
      
      // NÃO EXECUTAR ROTEAMENTO SE ESTIVER USANDO DADOS LOCAIS
      if (deliveriesNeedingRouting.length > 0 && !isOfflineMode && isInitialDataLoaded && forceRefresh) {
        // console.log("=== ENCONTRADAS ENTREGAS QUE PRECISAM DE ROTEAMENTO ===")
        // console.log("Total de entregas para roteamento:", deliveriesNeedingRouting.length)
        
        try {
          // SOLUÇÃO DEFINITIVA: OTIMIZAR ROTA ANTES DE ENVIAR PARA API
          // console.log("🎯 OTIMIZANDO ROTA COM ALGORITMO TSP ANTES DO ENVIO...")
          const optimizedDeliveries = await optimizeRouteWithTSP(deliveriesNeedingRouting)
          
          if (optimizedDeliveries.length > 0) {
            // console.log("✅ Rota otimizada com sucesso, enviando sequência otimizada para API...")
            
            // Preparar dados OTIMIZADOS para roteirização
            const optimizedRoutingData = optimizedDeliveries.map((delivery: Delivery) => ({
              outId: delivery.outId,
              customerId: delivery.customerId,
              deliverySeq: delivery.deliverySeq, // JÁ OTIMIZADO (1, 2, 3, ...)
              lat: normalizeCoordinate(delivery.lat || delivery.coordinates?.latitude),
              lng: normalizeCoordinate(delivery.lng || delivery.coordinates?.longitude)
            }))
            
            // console.log("Dados de roteamento OTIMIZADOS:", optimizedRoutingData)
            
            // Executar sendRoutingOrder com dados OTIMIZADOS
            const routingResult = await api.sendRoutingOrder(optimizedRoutingData)
            // console.log("=== ROTEAMENTO OTIMIZADO EXECUTADO COM SUCESSO ===")
            // console.log("Resultado:", routingResult)
            
            // Recarregar entregas após roteamento para obter dados atualizados
            // console.log("Recarregando entregas após roteamento...")
            const updatedData = await api.getDeliveries()
            // console.log("Dados atualizados após roteamento:", updatedData)
            
            // Ordenar entregas atualizadas
            const sortedUpdatedData = await sortDeliveriesBySequence(updatedData)
            setDeliveries(sortedUpdatedData)
            setHasNoDeliveries(false)
            setError(null)
            setLastRefreshTime(Date.now())
            // console.log("Estado atualizado com entregas após roteamento")
            // console.log("Próxima entrega:", sortedUpdatedData[0]?.customerName || "Nenhuma")
            
            // Notificar todos os componentes sobre a atualização
            // console.log("=== NOTIFICANDO TODOS OS COMPONENTES SOBRE ATUALIZAÇÃO ===")
          } else {
            // console.error("❌ Falha na otimização da rota")
            throw new Error("Falha na otimização da rota")
          }
          
        } catch (routingError) {
          // console.error("=== ERRO AO EXECUTAR ROTEAMENTO ===")
          // console.error("Erro:", routingError)
          
          // Mesmo com erro no roteamento, continuar com os dados originais
          // console.log("Continuando com dados originais devido ao erro no roteamento")
          const sortedData = await sortDeliveriesBySequence(data)
          setDeliveries(sortedData)
          setHasNoDeliveries(false)
          setError(null)
          setLastRefreshTime(Date.now())
          // console.log("Estado atualizado com as entregas ordenadas (sem roteamento)")
          // console.log("Próxima entrega:", sortedData[0]?.customerName || "Nenhuma")
        }
      } else {
        // Verificar se está usando dados locais
        if (isInitialDataLoaded && !forceRefresh) {
          // console.log("=== USANDO DADOS LOCAIS - SEM ROTEAMENTO NECESSÁRIO ===")
          // console.log("📦 Total de entregas locais:", data.length)
        } else {
          // console.log("=== NENHUMA ENTREGA PRECISA DE ROTEAMENTO ===")
        }
        
        // Ordenar entregas por sequência (deliverySeq)
        const sortedData = await sortDeliveriesBySequence(data)
        setDeliveries(sortedData)
        setHasNoDeliveries(false)
        setError(null)
        setLastRefreshTime(Date.now())
        // console.log("✅ Estado atualizado com as entregas ordenadas")
        // console.log("📊 Total de entregas no estado:", sortedData.length)
        // console.log("🎯 Próxima entrega:", sortedData[0]?.customerName || "Nenhuma")
        // console.log("📋 Fonte dos dados:", isInitialDataLoaded && !forceRefresh ? "LOCAL (SQLite)" : "API")
      }
    } catch (err) {
      // console.error("Erro ao carregar entregas da API:", err)
      
      // NUNCA usar dados de fallback - sempre mostrar que não existem entregas
      // console.log("Erro na API - mostrando que não existem entregas")
      setDeliveries([])
      setHasNoDeliveries(true)
      setError("Não existem entregas disponíveis no momento.")
      setLastRefreshTime(Date.now())
      // console.log("Estado atualizado: não existem entregas")
    } finally {
      setLoading(false)
      setIsRefreshing(false)
      isRefreshingRef.current = false
      // console.log("=== CARREGAMENTO FINALIZADO ===")
    }
  }, []) // Removida dependência isRefreshing para evitar loop

  // Função estável para lidar com mudanças de status
  const handleDeliveryStatusChange = useCallback(() => {
    // Recarregar dados locais para refletir mudanças no status
    loadDeliveries(false)
  }, [])

  // Registrar callback para atualização automática quando status de entrega mudar
  useEffect(() => {
    // Registrar o callback no OfflineModeContext
    registerDeliveryStatusCallback(handleDeliveryStatusChange)
    
    // Cleanup: não é necessário pois o callback será substituído quando necessário
  }, [handleDeliveryStatusChange, registerDeliveryStatusCallback])

  // Função para refresh normal (sem force)
  const refreshDeliveries = useCallback(async () => {
    // Evitar chamadas muito frequentes
    if (isRefreshingRef.current) {
      return
    }
    
    await loadDeliveries(false)
  }, [])

  // Função para force refresh (ignora se já está carregando)
  const forceRefresh = useCallback(async () => {
    await loadDeliveries(true)
  }, [])

  // Função para atualizar entregas com deliverySeq aleatória
  const updateDeliveriesWithRandomSeq = useCallback((updatedDeliveries: Delivery[]) => {
    // Ordenar as entregas atualizadas por sequência
    const sortedDeliveries = updatedDeliveries.sort((a, b) => {
      // Primeiro por deliverySeq, depois por status
      if (a.deliverySeq !== b.deliverySeq) {
        return a.deliverySeq - b.deliverySeq
      }
      
      const getStatusOrder = (status: Delivery["status"]): number => {
        switch (status) {
          case "in_progress": return 0
          case "pending": return 1
          case "delivered": return 2
          case "failed": return 3
          default: return 4
        }
      }
      
      return getStatusOrder(a.status) - getStatusOrder(b.status)
    })
    
    setDeliveries(sortedDeliveries)
    setLastRefreshTime(Date.now())
  }, [])

  // Função para normalizar coordenadas (converter vírgula para ponto e garantir número)
  const normalizeCoordinate = (coord: any): number => {
    if (coord === null || coord === undefined || coord === '') {
      return 0;
    }
    
    // Se já é número, retorna como está
    if (typeof coord === 'number') {
      return coord;
    }
    
    // Se é string, converte vírgula para ponto e converte para número
    if (typeof coord === 'string') {
      // Remove espaços e converte vírgula para ponto
      const normalized = coord.trim().replace(',', '.');
      const parsed = parseFloat(normalized);
      
      if (isNaN(parsed)) {
        // console.warn(`⚠️ Coordenada inválida: ${coord}, usando 0`);
        return 0;
      }
      
      return parsed;
    }
    
    // console.warn(`⚠️ Tipo de coordenada não suportado: ${typeof coord}, valor: ${coord}, usando 0`);
    return 0;
  };

  // Função para obter a próxima entrega
  const getNextDelivery = useCallback((): Delivery | null => {
    if (deliveries.length === 0) {
      return null
    }
    
    // Filtrar entregas válidas para próxima entrega
    const validDeliveries = deliveries.filter((delivery) => {
      // Considerar entregas com deliverySeq > 0 OU routing = 0 (que serão ordenadas por posição)
      const isValid = (delivery.deliverySeq > 0 || delivery.routing === 0) && delivery.status !== "delivered"
      return isValid
    })
    
    // Ordenar por deliverySeq primeiro, depois por posição na lista original para routing=0
    const sortedValidDeliveries = validDeliveries.sort((a, b) => {
      // Se ambos têm deliverySeq > 0, ordenar por deliverySeq
      if (a.deliverySeq > 0 && b.deliverySeq > 0) {
        return a.deliverySeq - b.deliverySeq
      }
      
      // Se apenas um tem deliverySeq > 0, ele vem primeiro
      if (a.deliverySeq > 0 && b.deliverySeq === 0) {
        return -1
      }
      if (a.deliverySeq === 0 && b.deliverySeq > 0) {
        return 1
      }
      
      // Se ambos têm deliverySeq = 0 (routing = 0), manter ordem original
      return 0
    })
    
    const nextDelivery = sortedValidDeliveries[0]
    
    return nextDelivery || null
  }, [deliveries])

  // Removido useEffect duplicado que causava conflito

  return (
    <DeliveriesContext.Provider
      value={{
        deliveries,
        loading,
        error,
        hasNoDeliveries,
        refreshDeliveries,
        forceRefresh,
        lastRefreshTime,
        isRefreshing,
        updateDeliveriesWithRandomSeq,
        getNextDelivery
      }}
    >
      {children}
    </DeliveriesContext.Provider>
  )
} 