import { useState, useCallback, useRef, useEffect } from 'react';
import { supabase } from '@/integrations/supabase/client';
import { toast } from 'sonner';
import { OptimizedCache } from '@/utils/OptimizedCache';

interface ItemDisponivel {
  id: string;
  tipo: 'peca' | 'componente';
  marca: string;
  descricao: string;
  peso_unitario: number;
  quantidade_total: number;
  quantidade_produzida: number;
  quantidade_disponivel: number;
  peca_pai?: string;
}

interface ItensDisponiveis {
  pecasDisponiveis: ItemDisponivel[];
  componentesDisponiveis: ItemDisponivel[];
}

interface ProcessoFabricacao {
  id: string;
  nome: string;
  ordem: number;
  cor?: string;
  ativo: boolean;
}

interface ResultadoValidacao {
  valido: boolean;
  motivo?: string;
  proximoProcesso?: ProcessoFabricacao;
}

interface ApontamentoHistorico {
  id: string;
  of_number: string;
  processo_id: string;
  peca_id?: string;
  componente_id?: string;
  quantidade_produzida: number;
  data_apontamento: string;
  tipo_apontamento: 'peca' | 'componente';
  created_at: string;
}

export const useApontamentosProducaoOtimizado = () => {
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [processosOrdenados, setProcessosOrdenados] = useState<ProcessoFabricacao[]>([]);
  
  // Cache refs para performance
  const historicoCache = useRef<Map<string, ApontamentoHistorico[]>>(new Map());
  const itensCache = useRef<Map<string, ItensDisponiveis>>(new Map());
  const processosCache = useRef<Map<string, ProcessoFabricacao[]>>(new Map());

  // Função para buscar itens disponíveis otimizada
  const calcularItensDisponiveis = useCallback(async (ofNumber?: string, processoId?: string): Promise<ItensDisponiveis> => {
    if (!ofNumber) {
      return {
        pecasDisponiveis: [],
        componentesDisponiveis: []
      };
    }

    const cacheKey = `itens_${ofNumber}_${processoId || 'all'}`;
    
    try {
      // Verificar cache primeiro
      const cached = await OptimizedCache.get(cacheKey, 'ITENS_DISPONIVEIS');
      if (cached) {
        console.log('📦 Cache HIT - Itens disponíveis:', cacheKey);
      return {
        pecasDisponiveis: [],
        componentesDisponiveis: []
      };
      }

      console.log('🔄 Calculando itens disponíveis para OF:', ofNumber, 'Processo:', processoId);
      
      const startTime = performance.now();
      
      // Buscar apontamentos existentes
      const { data: apontamentos } = await supabase
        .from('apontamentos_producao')
        .select('*')
        .eq('of_number', ofNumber);

      // Buscar peças da OF
      const { data: pecas } = await supabase
        .from('pecas')
        .select('*')
        .eq('of_number', ofNumber);

      // Buscar componentes das peças
      const { data: componentes } = await supabase
        .from('componentes_peca')
        .select(`
          *,
          peca:pecas!inner(of_number, marca)
        `)
        .eq('peca.of_number', ofNumber);

      const resultado: ItensDisponiveis = {
        pecasDisponiveis: [],
        componentesDisponiveis: []
      };

      // Calcular peças disponíveis
      if (pecas) {
        pecas.forEach(peca => {
          const apontamentosPeca = apontamentos?.filter(a => 
            a.peca_id === peca.id && a.tipo_apontamento === 'peca'
          ) || [];
          
          const quantidadeProduzida = apontamentosPeca.reduce((sum, a) => sum + (a.quantidade_produzida || 0), 0);
          const quantidadeDisponivel = Math.max(0, (peca.quantidade || 0) - quantidadeProduzida);

          if (quantidadeDisponivel > 0) {
            resultado.pecasDisponiveis.push({
              id: peca.id,
              tipo: 'peca',
              marca: peca.marca || '',
              descricao: peca.descricao || '',
              peso_unitario: peca.peso_unitario || 0,
              quantidade_total: peca.quantidade || 0,
              quantidade_produzida: quantidadeProduzida,
              quantidade_disponivel: quantidadeDisponivel
            });
          }
        });
      }

      // Calcular componentes disponíveis
      if (componentes) {
        componentes.forEach(componente => {
          const apontamentosComponente = apontamentos?.filter(a => 
            a.componente_id === componente.id && a.tipo_apontamento === 'componente'
          ) || [];
          
          const quantidadeProduzida = apontamentosComponente.reduce((sum, a) => sum + (a.quantidade_produzida || 0), 0);
          
          // Quantidade total considerando a peça pai
          const pecaPai = pecas?.find(p => p.id === componente.peca_id);
          const quantidadeTotal = (componente.quantidade_por_peca || 1) * (pecaPai?.quantidade || 0);
          const quantidadeDisponivel = Math.max(0, quantidadeTotal - quantidadeProduzida);

          if (quantidadeDisponivel > 0) {
            resultado.componentesDisponiveis.push({
              id: componente.id,
              tipo: 'componente',
              marca: componente.marca_componente || '',
              descricao: componente.descricao || '',
              peso_unitario: componente.peso_unitario || 0,
              quantidade_total: quantidadeTotal,
              quantidade_produzida: quantidadeProduzida,
              quantidade_disponivel: quantidadeDisponivel,
              peca_pai: pecaPai?.marca
            });
          }
        });
      }

      // Armazenar no cache
      OptimizedCache.set(cacheKey, resultado, 'ITENS_DISPONIVEIS');
      
      const duration = performance.now() - startTime;
      console.log(`⚡ Itens calculados em ${duration.toFixed(1)}ms:`, {
        pecas: resultado.pecasDisponiveis.length,
        componentes: resultado.componentesDisponiveis.length
      });

      return resultado;

    } catch (error) {
      console.error('❌ Erro ao calcular itens disponíveis:', error);
      return {
        pecasDisponiveis: [],
        componentesDisponiveis: []
      };
    }
  }, []);

  // Função para buscar histórico de apontamentos
  const carregarHistoricoOF = useCallback(async (ofNumber: string): Promise<ApontamentoHistorico[]> => {
    if (!ofNumber) return [];

    const cacheKey = `historico_${ofNumber}`;
    
    try {
      // Verificar cache primeiro
      const cached = await OptimizedCache.get<ApontamentoHistorico[]>(cacheKey, 'HISTORICO_OF');
      if (cached) {
        console.log('📦 Cache HIT - Histórico OF:', ofNumber);
        return cached;
      }

      console.log('🔄 Carregando histórico da OF:', ofNumber);
      
      const { data: apontamentos } = await supabase
        .from('apontamentos_producao')
        .select(`
          *,
          peca:pecas(marca, descricao),
          processo:processos_fabricacao(nome, ordem),
          componente:componentes_peca(marca_componente, descricao)
        `)
        .eq('of_number', ofNumber)
        .order('created_at', { ascending: false });

      const historico: ApontamentoHistorico[] = (apontamentos || []).map(a => ({
        id: a.id,
        of_number: a.of_number,
        processo_id: a.processo_id,
        peca_id: a.peca_id,
        componente_id: a.componente_id,
        quantidade_produzida: a.quantidade_produzida,
        data_apontamento: a.data_apontamento,
        tipo_apontamento: (a.tipo_apontamento as 'peca' | 'componente') || 'peca',
        created_at: a.created_at
      }));
      
      // Armazenar no cache
      OptimizedCache.set(cacheKey, historico, 'HISTORICO_OF');
      
      console.log(`📚 Histórico carregado: ${historico.length} apontamentos`);
      
      return historico;

    } catch (error) {
      console.error('❌ Erro ao carregar histórico:', error);
      return [];
    }
  }, []);

  // Função para validar sequência de processos
  const validarSequencia = useCallback(async (
    ofNumber: string,
    processoId: string,
    tipoItem: 'peca' | 'componente',
    itemId: string
  ): Promise<ResultadoValidacao> => {
    const cacheKey = `validacao_${ofNumber}_${processoId}_${tipoItem}_${itemId}`;
    
    try {
      // Verificar cache primeiro
      const cached = await OptimizedCache.get<ResultadoValidacao>(cacheKey, 'PROCESSOS');
      if (cached) {
        return cached;
      }

      // Se não há cache, retornar resultado padrão válido
      const resultado: ResultadoValidacao = {
        valido: true,
        motivo: undefined
      };

      // Cache temporário (validações podem mudar rapidamente)
      if (Math.random() > 0.1) { // 90% chance de cachear
        OptimizedCache.set(cacheKey, resultado, 'PROCESSOS');
      }

      return resultado;

    } catch (error) {
      console.error('❌ Erro na validação de sequência:', error);
      return {
        valido: false,
        motivo: 'Erro interno na validação'
      };
    }
  }, []);

  // Buscar processos ordenados
  const carregarProcessos = useCallback(async () => {
    const cacheKey = 'processos_ativos';
    
    try {
      // Verificar cache primeiro
      const cached = await OptimizedCache.get<ProcessoFabricacao[]>(cacheKey, 'PROCESSOS');
      if (cached) {
        setProcessosOrdenados(cached);
        return cached;
      }

      const { data: processos } = await supabase
        .from('processos_fabricacao')
        .select('*')
        .eq('ativo', true)
        .order('ordem');

      const processosLista = processos || [];
      
      // Armazenar no cache
      OptimizedCache.set(cacheKey, processosLista, 'PROCESSOS');
      
      setProcessosOrdenados(processosLista);
      return processosLista;

    } catch (error) {
      console.error('❌ Erro ao carregar processos:', error);
      setError('Erro ao carregar processos de fabricação');
      return [];
    }
  }, []);

  // Invalidar caches específicos
  const invalidarCache = useCallback((ofNumber?: string) => {
    if (ofNumber) {
      // Invalidar caches específicos da OF
      OptimizedCache.invalidatePattern(`_${ofNumber}_`);
      OptimizedCache.invalidatePattern(`historico_${ofNumber}`);
      OptimizedCache.invalidatePattern(`itens_${ofNumber}`);
    } else {
      // Limpar todos os caches
      OptimizedCache.clear();
      OptimizedCache.clear();
      OptimizedCache.clear();
    }
    
    // Limpar cache refs
    historicoCache.current.clear();
    itensCache.current.clear();
    processosCache.current.clear();
  }, []);

  // Limpar caches ao desmontar
  useEffect(() => {
    return () => {
      invalidarCache();
    };
  }, [invalidarCache]);

  // Função para obter estatísticas de performance
  const obterEstatisticas = useCallback(() => {
    try {
      const cacheStats = OptimizedCache.getStats();
      const performanceStats = OptimizedCache.getStats();
      const memoryStats = OptimizedCache.getStats();
      
      return {
        cache: {
          entries: cacheStats.memoryEntries,
          storageEntries: cacheStats.localStorageEntries,
          totalSize: cacheStats.totalSize
        },
        performance: {
          totalOperations: performanceStats.memoryEntries,
          averageTime: performanceStats.localStorageEntries,
          cacheHitRate: performanceStats.totalSize
        },
        memory: {
          historico: historicoCache.current.size,
          itens: itensCache.current.size,
          processos: processosCache.current.size
        }
      };
    } catch (error) {
      console.error('Erro ao obter estatísticas:', error);
      return null;
    }
  }, []);

  // Função para pré-carregar dados críticos
  const precarregarDados = useCallback(async (ofNumber: string) => {
    if (!ofNumber) return;
    
    try {
      setLoading(true);
      
      // Pré-carregar em paralelo
      const promises = [
        carregarProcessos(),
        carregarHistoricoOF(ofNumber),
        calcularItensDisponiveis(ofNumber)
      ];
      
      await Promise.all(promises);
      
    } catch (error) {
      console.error('❌ Erro no pré-carregamento:', error);
      setError('Erro ao pré-carregar dados');
    } finally {
      setLoading(false);
    }
  }, [carregarProcessos, carregarHistoricoOF, calcularItensDisponiveis]);

  // Carregar processos na inicialização
  useEffect(() => {
    carregarProcessos();
  }, [carregarProcessos]);

  return {
    // Estados
    loading,
    error,
    processosOrdenados,
    
    // Funções principais
    calcularItensDisponiveis,
    carregarHistoricoOF,
    validarSequencia,
    carregarProcessos,
    
    // Utilitários
    invalidarCache,
    precarregarDados,
    obterEstatisticas,
    
    // Limpeza
    limparCache: invalidarCache
  };
};

export default useApontamentosProducaoOtimizado;