import { useState, useEffect, useMemo, useCallback } from 'react';
import { boletosService } from '@/services/boletosService';
import { extratoService } from '@/services/extratoService';
import { toast } from 'sonner';

/**
 * Formata data para mês (YYYY-MM)
 * @param {Date} date
 * @returns {string}
 */
const formatMonth = (date) => {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, '0');
  return `${year}-${month}`;
};

/**
 * Extrai mês de uma data string (YYYY-MM-DD ou similar)
 * @param {string} dateStr
 * @returns {string}
 */
const extractMonth = (dateStr) => {
  if (!dateStr) return '';
  const date = new Date(dateStr);
  if (isNaN(date.getTime())) return '';
  return formatMonth(date);
};

/** Prefixo para logs de somas/boletos (facilita filtrar no console) */
const LOG_PREFIX = '[Boletos/Somas]';

/**
 * Hook para gerenciar a lógica de Boletos do Inter
 * Implementa lógica de cruzamento entre boletos e extrato (baseado na lógica antiga)
 */
export const useBoletos = () => {
  // Estados de dados brutos
  const [boletosRaw, setBoletosRaw] = useState([]);
  const [boletosSummary, setBoletosSummary] = useState([]); // resumoValorPorSituacaoMesAno
  const [extratoRaw, setExtratoRaw] = useState([]);
  const [pixSoma, setPixSoma] = useState({ total: 0, quantidade: 0 });
  const [pixApresentar, setPixApresentar] = useState([]);
  
  // Estados de loading e erro
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);
  
  // Filtros
  const [filterMonth, setFilterMonth] = useState(() => {
    const now = new Date();
    return formatMonth(now);
  });

  // Empresas para o formulário de criação
  const [empresas, setEmpresas] = useState([]);
  const [isCreating, setIsCreating] = useState(false);

  /**
   * Carrega boletos e extrato (para cruzamento)
   */
  const loadBoletos = useCallback(async () => {
    setIsLoading(true);
    setError(null);
    
    try {
      // Busca dados de apresentação (Lista e Resumo) na mesma rota conforme solicitado
      const data = await boletosService.fetchBoletosStatus();
      
      const cobrancas = data?.cobrancas || [];
      const summary = data?.resumoValorPorSituacaoMesAno || [];
      
      setBoletosRaw(cobrancas);
      setBoletosSummary(summary);
      
      // Busca extrato para cruzamento
      try {
        // Extrai mês e ano do filterMonth para passar aos endpoints
        const [yearStr, monthStr] = filterMonth.split('-');
        const mes = parseInt(monthStr, 10);
        const ano = parseInt(yearStr, 10);
        
        const [extratoData, pixSomaData, pixListData] = await Promise.all([
          boletosService.fetchExtrato(),
          extratoService.fetchPixSoma(),
          extratoService.fetchPixEmpresas({ mes, ano })
        ]);
        setExtratoRaw(Array.isArray(extratoData) ? extratoData : []);
        setPixSoma(pixSomaData || { total: 0, quantidade: 0 });
        setPixApresentar(pixListData || []);
      } catch (extratoErr) {
        console.warn('Erro ao carregar dados complementares (extrato/pix):', extratoErr);
        setExtratoRaw([]);
      }
    } catch (err) {
      console.error('Erro ao carregar boletos:', err);
      setError(err.message || 'Erro ao carregar lista de boletos');
      toast.error('Erro ao carregar boletos');
      setBoletosRaw([]);
      setBoletosSummary([]); 
      setExtratoRaw([]);
    } finally {
      setIsLoading(false);
    }
  }, [filterMonth]);

  /**
   * Carrega empresas/clientes
   */
  const loadEmpresas = useCallback(async () => {
    try {
      const data = await boletosService.fetchEmpresas();
      setEmpresas(data);
    } catch (err) {
      console.error('Erro ao carregar empresas:', err);
    }
  }, []);

  /**
   * Carrega dados quando componente monta ou mês muda
   */
  useEffect(() => {
    loadBoletos();
    loadEmpresas();
  }, [loadBoletos, loadEmpresas, filterMonth]);

  /**
   * Helper para download de PDF
   */
  const downloadBlob = (blob, filename) => {
    if (!blob || blob.size === 0) {
      throw new Error("O arquivo retornado está vazio.");
    }
    const url = URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.href = url;
    link.download = filename;
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(url);
  };

  /**
   * Cria um novo boleto
   */
  const createBoleto = async (payload, mode) => {
    setIsCreating(true);
    console.log(LOG_PREFIX, 'createBoleto chamado:', { payload, mode });
    try {
      if (mode === 'AVULSO') {
        // Fluxo para Avulso: /servicos_financeiro/create -> find in list -> /boletos/avulsos -> PDF
        console.log(LOG_PREFIX, 'Iniciando criação de boleto AVULSO', payload);
        
        // 1. Cria o serviço
        await boletosService.createServicoFinanceiro(payload);
        
        // 2. Busca lista de serviços para encontrar o objeto criado
        const servicos = await boletosService.fetchServicosFinanceiro();
        
        // 3. Encontra o item pelo nome e valor (lógica antiga)
        const boletoGert = servicos.find(item => {
          const nameMatch = item.nome === payload.nome;
          const valorMatch = Number(item.valor_servico) === Number(payload.valor_servico);
          return nameMatch && valorMatch;
        });

        if (!boletoGert) {
          throw new Error('Serviço financeiro criado, mas não encontrado para geração do PDF.');
        }

        console.log(LOG_PREFIX, 'Serviço encontrado, gerando PDF:', boletoGert);

        // 4. Gera o PDF do boleto avulso
        /* 
        const pdfBlob = await boletosService.generateBoletoAvulsoPDF(boletoGert);
        
        // 5. Download do PDF
        downloadBlob(pdfBlob, `Boleto_Avulso_${payload.nome.replace(/\s+/g, '_')}.pdf`);
        */
        
        // toast.success('Boleto avulso gerado com sucesso!');
      } else {
        // Fluxo padrão (MENSAL ou outros)
        await boletosService.createBoleto(payload);
        toast.success('Boleto gerado com sucesso!');
      }
      
      await loadBoletos(); // Recarrega a lista
      return true;
    } catch (err) {
      console.error('Erro ao gerar boleto:', err);
      toast.error(err.message || 'Erro ao gerar boleto');
      return false;
    } finally {
      setIsCreating(false);
    }
  };

  /**
   * Processa e cruza dados de boletos com extrato
   * Baseado na lógica antiga: Construir_Interface
   */
  const processedData = useMemo(() => {
    const filterMonthStr = formatMonth(new Date(`${filterMonth}-01T00:00:00`));

    // 1. Filtra boletos por mês (vencimento)
    const boletosFiltrados = boletosRaw.filter(item => {
      const cobranca = item.cobranca || item;
      return extractMonth(cobranca.dataVencimento) === filterMonthStr;
    });

    // 2. Filtra extrato por mês e tipoOperacao === "C" (Crédito)
    const extratoFiltrado = extratoRaw.filter(item => {
      return extractMonth(item.dataEntrada) === filterMonthStr && item.tipoOperacao === 'C';
    });

    // 3. Cruzamento de dados (Lógica antiga: Identificar PIX que não são de boletos baixados)
    const listNot = ['CANCELADO', 'A_RECEBER', 'ATRASADO'];
    const pixRecebidosExtras = [];
    
    // Para cada item do extrato, verificamos se existe um boleto correspondente
    for (const extratoItem of extratoFiltrado) {
      const valorExtrato = Number(extratoItem.valor?.toString().replace(',', '.')) || 0;
      let boletoCorrespondente = false;

      for (const boletoItem of boletosFiltrados) {
        const cob = boletoItem.cobranca || boletoItem;
        
        // Se a situação for uma das que não conferem com extrato, pula
        if (listNot.includes(cob.situacao)) continue;

        const valorBoleto = Number(cob.valorTotalRecebido || cob.valorNominal || 0);

        // Se o valor bate, assumimos que esse PIX é a baixa deste boleto
        if (Math.abs(valorExtrato - valorBoleto) < 0.01) {
          boletoCorrespondente = true;
          break;
        }
      }

      if (!boletoCorrespondente) {
        pixRecebidosExtras.push(extratoItem);
      }
    }

    // 4. Agrupamento para os Cards (Seguindo a lógica do item.Recebimento === "PIX")
    const statusGroups = {};
    const addToGroup = (key, item, valor) => {
      if (!statusGroups[key]) {
        statusGroups[key] = { 
          status: key, 
          items: [], 
          quantidade: 0, 
          total: 0,
          origemRecebimento: key === 'PIX' ? 'PIX' : 'BOLETO'
        };
      }
      statusGroups[key].items.push(item);
      statusGroups[key].quantidade++;
      statusGroups[key].total += valor;
    };

    // Processa Boletos
    for (const item of boletosFiltrados) {
      const cob = item.cobranca || item;
      const valor = (cob.situacao === 'RECEBIDO' || cob.situacao === 'PAGO') 
        ? Number(cob.valorTotalRecebido || cob.valorNominal || 0)
        : Number(cob.valorTotalRecebido || 0);
      
      // Normalização de status
      let situacao = cob.situacao || 'A_RECEBER';
      if (situacao === 'PENDENTE') situacao = 'A_RECEBER';
      
      // Se for PIX (mesmo que seja boleto com QR Code PIX), vai para o grupo PIX
      // Caso contrário, vai para o grupo da sua situação (RECEBIDO, ATRASADO, etc)
      let groupKey = situacao;
      if (cob.origemRecebimento === 'PIX' || cob.tipoCobranca === 'PIX') {
        groupKey = 'PIX';
      }
      
      addToGroup(groupKey, cob, valor);
    }

    // Processa PIX Extras do extrato
    for (const pixIdx in pixRecebidosExtras) {
      const pix = pixRecebidosExtras[pixIdx];
      const valor = Number(pix.valor?.toString().replace(',', '.')) || 0;
      const virtualCobranca = {
        pagador: { nome: pix.descricao || 'PIX Recebido' },
        dataEmissao: pix.dataEntrada,
        dataVencimento: pix.dataEntrada,
        tipoCobranca: pix.titulo || 'PIX',
        valorNominal: '----',
        valorTotalRecebido: valor,
        origemRecebimento: 'PIX',
        situacao: 'PIX', // Identificador para a tabela
        idVirtual: `pix-extra-${pixIdx}`
      };
      addToGroup('PIX', virtualCobranca, valor);
    }

    // Tabela auxiliar de totais simplificada para os stats
    const totalByStatus = {};
    for (const key in statusGroups) {
      totalByStatus[key] = {
        quantidade: statusGroups[key].quantidade,
        total: statusGroups[key].total
      };
    }

    console.log(LOG_PREFIX, 'Dados Processados (Mês):', filterMonthStr, {
      boletosCount: boletosFiltrados.length,
      pixExtrasCount: pixRecebidosExtras.length,
      resumo: totalByStatus
    });

    return {
      boletosFiltrados,
      pixRecebidos: pixRecebidosExtras,
      statusGroups,
      totalByStatus
    };
  }, [boletosRaw, extratoRaw, filterMonth]);

  /**
   * Formata boletos para exibição na tabela (todos os boletos da API, sem filtro de mês).
   * O filtro de mês é aplicado na view para manter tabela e cards sincronizados.
   */
  const boletosFormatted = useMemo(() => {
    const allBoletos = [];
    
    // 1. Formata todos os boletos da API Inter
    for (const item of boletosRaw) {
      const cobranca = item.cobranca || item;
      const boleto = item.boleto || {};
      const pix = item.pix || {};
      
      const valorNominal = typeof cobranca.valorNominal === 'string' 
        ? Number(cobranca.valorNominal.replace(',', '.')) 
        : Number(cobranca.valorNominal || 0);

      let situacao = cobranca.situacao || 'A_RECEBER';
      if (situacao === 'PENDENTE') situacao = 'A_RECEBER';

      const status = (cobranca.origemRecebimento === 'PIX' || cobranca.tipoCobranca === 'PIX') ? 'PIX' : situacao;
      
      allBoletos.push({
        id: cobranca.codigoSolicitacao || `row-${allBoletos.length}`,
        numero: cobranca.seuNumero || cobranca.codigoSolicitacao || '',
        pagador: cobranca.nome || cobranca.pagador?.nome || '',
        cliente: cobranca.nome || cobranca.pagador?.nome || '',
        emitido: cobranca.dataEmissao || '',
        dataEmissao: cobranca.dataEmissao || '',
        vencimento: cobranca.dataVencimento || '',
        dataVencimento: cobranca.dataVencimento || '',
        tipoCobranca: cobranca.tipoCobranca || 'SIMPLES',
        tipo: cobranca.tipoCobranca || 'SIMPLES',
        valorNominal: valorNominal,
        valor: valorNominal,
        totalRecebido: Number(cobranca.valorTotalRecebido || 0),
        status: status,
        origemRecebimento: cobranca.origemRecebimento || 'BOLETO',
        situacao: cobranca.situacao || '',
        idempresa: cobranca.idempresa || cobranca.id_empresa || '',
        id_empresa: cobranca.id_empresa || cobranca.idempresa || '',
        codigoSolicitacao: cobranca.codigoSolicitacao || '',
        seuNumero: cobranca.seuNumero || '',
        dataSituacao: cobranca.dataSituacao || '',
        codigoBarras: boleto.codigoBarras || cobranca.codigoBarras || item.codigoBarras || '',
        linhaDigitavel: boleto.linhaDigitavel || cobranca.linhaDigitavel || item.linhaDigitavel || '',
        nossoNumero: boleto.nossoNumero || cobranca.nossoNumero || item.nossoNumero || '',
        pixCopiaECola: pix.pixCopiaECola || '',
        pixTxid: pix.txid || '',
        cpfCnpj: cobranca.cpfCnpj || '',
        idboletos: cobranca.idboletos || '',
        nome: cobranca.nome || '',
        txid: cobranca.txid || cobranca.pixTxid || ''
      });
    }



    /**
     * Helper para formatar data do PIX
     * A API pode retornar formato UTC string "Wed, 11 Feb 2026..."
     * Precisamos de YYYY-MM-DD para o filtro da lista funcionar
     */
    const formatPixDate = (dateStr) => {
      if (!dateStr) return '';
      try {
        const date = new Date(dateStr);
        if (isNaN(date.getTime())) return dateStr;
        
        const year = date.getFullYear();
        const month = String(date.getMonth() + 1).padStart(2, '0');
        const day = String(date.getDate()).padStart(2, '0');
        return `${year}-${month}-${day}`;
      } catch (e) {
        return dateStr;
      }
    };

    // 2. Adiciona PIX do novo endpoint de apresentação
    for (const pixIdx in pixApresentar) {
      const pixItem = pixApresentar[pixIdx];
      const valor = Number(pixItem.valor?.toString().replace(',', '.')) || 0;
      
      // Prioriza nome_exibicao, depois empresa, depois beneficiario_pagador, depois descricao
      const displayName = pixItem.nome_exibicao || pixItem.empresa || pixItem.beneficiario_pagador || pixItem.descricao || 'PIX Recebido';
      
      
      const dataFormatada = formatPixDate(pixItem.dataEntrada || pixItem.data_recebimento);
      
      allBoletos.push({
        id: `pix-new-${pixIdx}`,
        numero: pixItem.idTransacao || pixItem.txid || `PIX-${pixIdx}`,
        pagador: displayName,
        cliente: displayName,
        emitido: dataFormatada,
        dataEmissao: dataFormatada,
        vencimento: dataFormatada,
        dataVencimento: dataFormatada,
        tipoCobranca: 'PIX',
        tipo: 'PIX',
        valorNominal: valor,
        valor: valor,
        totalRecebido: valor,
        status: 'PIX',
        origemRecebimento: 'PIX',
        codigoSolicitacao: pixItem.idTransacao || pixItem.txid || '',
        seuNumero: '',
        dataSituacao: pixItem.dataEntrada || '',
        txid: pixItem.idTransacao || pixItem.txid || '',
        cpfCnpj: pixItem.cpfCnpj || '',
        idempresa: pixItem.idempresa || null,
        idextrato: pixItem.idextrato || null,
        descricao: pixItem.descricao || ''
      });
    }

    // 3. Adiciona PIX extras do extrato na visualização da tabela (Cruzamento Legado)
    for (const pixIdx in processedData.pixRecebidos) {
      const pixItem = processedData.pixRecebidos[pixIdx];
      const valor = Number(pixItem.valor?.toString().replace(',', '.')) || 0;
      allBoletos.push({
        id: `pix-extra-${pixIdx}`,
        numero: `EXTRATO-${pixItem.idextrato || pixIdx}`,
        pagador: pixItem.descricao || 'PIX Recebido (Extrato)',
        cliente: pixItem.descricao || 'PIX Recebido (Extrato)',
        emitido: pixItem.dataEntrada || '',
        dataEmissao: pixItem.dataEntrada || '',
        vencimento: pixItem.dataEntrada || '',
        dataVencimento: pixItem.dataEntrada || '',
        tipoCobranca: 'PIX',
        tipo: 'PIX',
        valorNominal: valor,
        valor: valor,
        totalRecebido: valor,
        status: 'PIX',
        origemRecebimento: 'PIX',
        codigoSolicitacao: '',
        seuNumero: '',
        dataSituacao: ''
      });
    }

    return allBoletos;
  }, [boletosRaw, processedData.pixRecebidos, pixApresentar]);

  /**
   * Estatísticas consolidada para os cards
   */
  const stats = useMemo(() => {
    const [yearStr, monthStr] = filterMonth.split('-');
    const year = parseInt(yearStr);
    const month = parseInt(monthStr);

    // Tenta usar dados do backend
    const monthStats = boletosSummary.filter(s => s.ano === year && s.mes === month);
    const hasBackendData = monthStats.length > 0;
    
    if (hasBackendData) {
      const getStatFromSummary = (situations) => {
        const filtered = monthStats.filter(s => situations.includes(s.situacao));
        return {
          valor: filtered.reduce((acc, curr) => acc + (Number(curr.totalValorNominal) || 0), 0),
          total: filtered.reduce((acc, curr) => acc + (Number(curr.quantidade) || 0), 0)
        };
      };

      const result = {
        atrasado: getStatFromSummary(['ATRASADO']),
        a_receber: getStatFromSummary(['A_RECEBER', 'PENDENTE']),
        cancelado: getStatFromSummary(['CANCELADO', 'EXPIRADO']),
        recebido: getStatFromSummary(['RECEBIDO']),
        marcadoRecebido: getStatFromSummary(['MARCADO_RECEBIDO']),
        pix: {
          valor: pixSoma?.total ?? (processedData.totalByStatus['PIX']?.total || 0),
          total: (pixApresentar && pixApresentar.length > 0) ? pixApresentar.length : (pixSoma?.quantidade ?? (processedData.totalByStatus['PIX']?.quantidade || 0))
        }
      };
      console.log(LOG_PREFIX, 'Stats Backend (Mês/Ano):', `${month}/${year}`, result);
      return result;
    } else {
      // Fallback para cálculo local (processedData)
      const { totalByStatus } = processedData;
      const getStat = (key) => ({
        valor: totalByStatus[key]?.total || 0,
        total: totalByStatus[key]?.quantidade || 0
      });

      const result = {
        atrasado: getStat('ATRASADO'),
        a_receber: getStat('A_RECEBER'),
        cancelado: getStat('CANCELADO'),
        recebido: getStat('RECEBIDO'),
        marcadoRecebido: getStat('MARCADO_RECEBIDO'),
        pix: getStat('PIX')
      };
      console.log(LOG_PREFIX, 'Stats Local (Fallback):', result);
      return result;
    }
  }, [boletosSummary, filterMonth, processedData.totalByStatus]);

  return {
    state: {
      boletos: boletosFormatted,
      stats,
      isLoading,
      error,
      filterMonth,
      statusGroups: processedData.statusGroups,
      totalByStatus: processedData.totalByStatus,
      empresas,
      isCreating,
      pixSoma,
      pixApresentar
    },
    actions: {
      setFilterMonth,
      loadBoletos,
      createBoleto,
      loadEmpresas,
      scheduleBoleto: async (payload) => {
        try {
          await boletosService.scheduleBoleto(payload);
          toast.success('Boleto agendado com sucesso!');
          await loadBoletos();
          return true;
        } catch (err) {
          console.error('Erro ao agendar boleto:', err);
          toast.error('Erro ao agendar boleto');
          return false;
        }
      },
      agendarBoletosGlobal: async (payload) => {
        setIsCreating(true);
        try {
          await boletosService.agendarBoletos(payload);
          toast.success('Boletos agendados com sucesso!');
          await loadBoletos();
          return true;
        } catch (err) {
          console.error('Erro ao agendar boletos (global):', err);
          toast.error('Erro ao agendar boletos');
          return false;
        } finally {
          setIsCreating(false);
        }
      }
    }
  };
};
