import { useState, useEffect, useCallback, useMemo } from 'react';
import { extratoService } from '@/services/extratoService';
import { formatDateForChart } from '../utils/dateUtils';
import { boletosService } from '@/services/boletosService';
import { workspaceDespesasService } from '@/services/workspaceDespesasService';
import { workspaceSaldoService } from '@/services/workspaceSaldoService';
import { parseDateInfo } from '@/utils/dateUtils';


/**
 * Hook para gerenciar dados do Dashboard
 * Implementa a lógica do dashboard adaptada para React com suporte a projeções
 */
export const useDashboard = () => {
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  // Dados brutos da API
  const [data, setData] = useState({
    saldo: { disponivel: 0 },
    saldoArmazenado: [],
    extrato: [],
    fluxo: { mensal: [], anual: [], diario: [] },
    boletos: { cobrancas: [] },
    empresas: [],
    contasAPagar: [],
    categorias: [],
    // New states for modals (optional, or fetch on demand)
    entradasMes: [],
    saidasMes: [],
    transacoesNaoConciliadas: [],
    boletosAbertos: []
  });

  // Estado para filtros de gráfico
  const [jurosFilter, setJurosFilter] = useState('mensal'); // 'mensal' | 'anual'
  const [fluxoPeriodo, setFluxoPeriodo] = useState('0'); // 0 = atual, 1 = 1 mês atrás, etc.
  const [jurosData, setJurosData] = useState([]);

  // Dados calculados para exibição
  const [resumo, setResumo] = useState({
    saldoTotal: 0,
    entrada: 0,
    saida: 0,
    transacoesPendentes: 0,
    emPendencia: { quantidade: 0, valor: 0 },
    faturamento: 0
  });

  // Função auxiliar para formatar data no formato "YYYY-MM"
  const formatMesAno = (dateOrStr) => {
    if (!dateOrStr) return '';
    let ano, mes;
    if (typeof dateOrStr === 'string' && dateOrStr.trim().length > 0) {
        const { year, month } = parseDateInfo(dateOrStr);
        if (!year) return '';
        ano = year;
        mes = String(month).padStart(2, '0');
    } else {
        const d = dateOrStr instanceof Date ? dateOrStr : new Date(dateOrStr);
        if (isNaN(d.getTime())) return '';
        ano = d.getFullYear();
        mes = String(d.getMonth() + 1).padStart(2, '0');
    }
    return `${ano}-${mes}`;
  };

  // Helper function to safely convert value to Number or 0
  const safeNumber = (val) => {
    const n = Number(val);
    return isNaN(n) ? 0 : n;
  };

  // Função para obter último saldo do mês anterior
  const getUltimoSaldoMesAnterior = (saldos) => {
    const hoje = new Date();
    const anoAtual = hoje.getFullYear();
    const mesAtual = hoje.getMonth();

    const anteriores = saldos
      .map(item => ({
        ...item,
        data: item.data_saldo ? new Date(item.data_saldo) : (item.data ? new Date(item.data) : null)
      }))
      .filter(item => {
        if (!item.data) return false;
        const itemAno = item.data.getFullYear();
        const itemMes = item.data.getMonth();
        return itemAno < anoAtual || (itemAno === anoAtual && itemMes < mesAtual);
      });

    if (!anteriores.length) return null;
    anteriores.sort((a, b) => b.data - a.data);
    return anteriores[0];
  };

  const loadData = useCallback(async () => {
    try {
      setLoading(true);
      setError(null);

      const [
        saldo,
        saldoArmazenado,
        extrato,
        fluxo,
        boletosData,
        empresas,
        contasAPagar,
        categorias,
        saldoConsolidado
      ] = await Promise.all([
        extratoService.fetchSaldo().catch(() => ({ disponivel: 0 })),
        extratoService.fetchSaldoArmazenado().catch(() => []),
        extratoService.fetchExtrato().catch(() => []),
        extratoService.fetchFluxo().catch(() => ({ mensal: [], anual: [], diario: [] })),
        boletosService.fetchBoletosStatus().catch(() => ({ cobrancas: [] })),
        extratoService.fetchEmpresas().catch(() => []),
        workspaceDespesasService.fetchContasAPagar().catch(() => []),
        extratoService.fetchCategorias().catch(() => []),
        extratoService.fetchSaldoConsolidado({ 
          mes: new Date().getMonth() + 1, 
          ano: new Date().getFullYear() 
        }).catch(() => null)
      ]);

      setData({
        saldo,
        saldoArmazenado,
        extrato,
        fluxo,
        boletos: boletosData,
        empresas,
        contasAPagar,
        categorias,
        saldoConsolidado: saldoConsolidado || { entradas: 0, saidas: 0, saldo_anterior: 0, saldo_atual: 0 }
      });

      // --- CÁLCULOS DE RESUMO (Integrado com lógica do FluxoCaixa) ---
      const hoje = new Date();
      const mesAtualStr = formatMesAno(hoje);

      // Calcular receitas e despesas totais do extrato (todos os períodos)
      let receitasTotal = 0;
      let despesasTotal = 0;
      
      // Acumuladores do Mês Atual
      let receitasMes = 0;
      let despesasMes = 0;
      
      let transacoesPendentesCnt = 0;

      extrato.forEach((item) => {
        const itemMes = formatMesAno(item.dataEntrada);
        
        // Pendentes de conciliação do Mês
        if ((!item.categoria || item.categoria == 0) && itemMes === mesAtualStr) {
          transacoesPendentesCnt++;
        }

        const valor = safeNumber(item.valor);
        
        // Filtrar Receitas e Despesas apenas do mês atual para os cards "Planejadas" e "Despesas"
        // NOTA: Para Saldo em Conta, precisamos do acumulado total (receitasTotal/despesasTotal globais da lógica anterior)
        //       Mas a array 'extrato' traz tudo? Sim.
        //       Vou criar variáveis separadas para o mês.
        
        // Acumulado Global (para Saldo em Conta)
        if (item.tipoOperacao === 'C') receitasTotal += valor;
        if (item.tipoOperacao === 'D') despesasTotal += valor;
        
        // Acumulado Mensal (para Cards de Entradas/Planejadas e Saídas/Despesas)
        if (itemMes === mesAtualStr) {
          if (item.tipoOperacao === 'C') receitasMes += valor;
          if (item.tipoOperacao === 'D') despesasMes += valor;
        }
      });

      // Obter último saldo armazenado (mês anterior)
      const saldoAnterior = getUltimoSaldoMesAnterior(saldoArmazenado);
      const ultimoSaldo = saldoAnterior?.saldo_disponivel ?? saldoAnterior?.saldo ?? 0;

      // Cálculo do saldo em conta (lógica do FluxoCaixa - Global)
      const saldoEmConta = Number(ultimoSaldo) + receitasTotal - despesasTotal;

      // Card Planejadas (Entradas): ultimoSaldo + receitas DO MÊS?
      // "Planejadas" geralmente é previsão. Se for "Entradas do Mês", é receitasMes.
      // O usuário pediu: "o saldo em conta o planejamento e despesas precisam ser do mesm vigente"
      // Se "Planejadas" = Receitas do Mês:
      const entradasPlanejadas = receitasMes; 
      // OBS: Se for "Planejadas" no sentido de Fluxo Futuro, seria Boletos a Receber.
      // Mas o card antigo chamava "Entradas" e usava (ultimoSaldo + receitas).
      // Vou assumir que ele quer ver o quanto entrou ESSE MÊS + o que tem pra entrar?
      // Ele disse: "o planejamento... do mesm vigente".
      // Vou colocar Receitas do Mês (Realizado) + Pendências do Mês (Futuro)?
      // Ou apenas Receitas do Mês (Como 'Extrato (Entradas)' já faz)?
      // O card "Planejadas" subtituiu "Entradas".
      // Vou configurar como: Receitas Realizadas do Mês + Boletos A Receber do Mês.
      
      // Card Despesas: Saídas do Mês
      const saidasMes = despesasMes;

      // Pendências de Boletos (A Receber) do Mês
      let valorPendencia = 0;
      let qtdPendencia = 0;
      const statusesPendentes = ['ATRASADO', 'A_RECEBER'];

      boletosData.cobrancas?.forEach((item) => {
        const cobranca = item.cobranca || item;
        if (!cobranca.dataVencimento) return;
        
        const vencMes = formatMesAno(cobranca.dataVencimento);
        if (vencMes === mesAtualStr && statusesPendentes.includes(cobranca.situacao)) {
          qtdPendencia++;
          const valTotal = safeNumber(cobranca.valorTotalRecebido);
          const valNominal = safeNumber(cobranca.valorNominal);
          valorPendencia += (valTotal || valNominal);
        }
      });

      // Recalcular Planejadas: Receitas do Mês + A Receber do Mês (Total previsto de entrada no mês)
      const totalPlanejadoEntrada = receitasMes + valorPendencia;

      // Calcular entradas do mês atual para Faturamento (Realizado apenas)
      // Já tenho em receitasMes.

      // --- CUSTO/RECEITA DOS CARDS (Sincronizado com nova estrutura de entradas_vs_saidas) ---
      // Objeto esperado: { entradas_vs_saidas: { diferenca, total_entradas, total_saidas } }
      const evs = saldoConsolidado?.entradas_vs_saidas;
      
      const finalSaldo = evs ? safeNumber(evs.diferenca) : saldoCalculado;
      const finalEntrada = evs ? safeNumber(evs.total_entradas) : (Number(ultimoSaldo) + receitasMes);
      const finalSaida = evs ? safeNumber(evs.total_saidas) : saidasMes;

      setResumo({
        saldoTotal: finalSaldo,
        entrada: finalEntrada,
        saida: finalSaida,
        transacoesPendentes: transacoesPendentesCnt,
        emPendencia: { quantidade: qtdPendencia, valor: valorPendencia },
        faturamento: evs ? safeNumber(evs.total_entradas) : receitasMes,
        saldoDisponivel: saldo.disponivel || 0
      });

    } catch (err) {
      console.error('[useDashboard] Erro fatal:', err);
      setError('Erro ao carregar dados do dashboard');
    } finally {
      setLoading(false);
    }
  }, []);

  useEffect(() => {
    loadData();
  }, [loadData]);

  // --- PREPARAÇÃO DE DADOS PARA GRÁFICOS ---

  const getFluxoBarData = () => {
    // Usar dados do endpoint /extrato/fluxo -> diario
    const diario = data.fluxo?.diario || [];
    const fluxoPorDia = {};
    const hoje = new Date();
    
    // Calcular qual mês mostrar com base no fluxoPeriodo
    const dataAlvo = new Date(hoje.getFullYear(), hoje.getMonth() - Number(fluxoPeriodo), 1);
    const mesAlvoStr = `${dataAlvo.getFullYear()}-${String(dataAlvo.getMonth() + 1).padStart(2, '0')}`;

    diario.forEach((item) => {
      if (!item.data) return;
      
      // Filtrar pelo mês alvo
      if (!item.data.startsWith(mesAlvoStr)) return;

      const diaFormatado = formatDateForChart(item.data);

      if (!fluxoPorDia[diaFormatado]) {
        fluxoPorDia[diaFormatado] = { name: diaFormatado, entradas: 0, saidas: 0, rawDate: item.data };
      }

      const valor = safeNumber(item.total);
      if (item.tipoOperacao === 'C') {
        fluxoPorDia[diaFormatado].entradas += valor;
      } else if (item.tipoOperacao === 'D') {
        fluxoPorDia[diaFormatado].saidas += valor;
      }
    });

    // Converter para array e ordenar cronologicamente pela data bruta
    return Object.values(fluxoPorDia)
      .sort((a, b) => a.rawDate.localeCompare(b.rawDate));
  };

  const getBoletosPieData = () => {
    const values = {};
    const counts = {};
    const mesAtual = formatMesAno(new Date());

    data.boletos.cobrancas?.forEach((item) => {
      const c = item.cobranca || item;
      if (formatMesAno(c.dataVencimento) !== mesAtual) return;
      
      const st = c.situacao || 'OUTROS';
      const valor = safeNumber(c.valorNominal);
      values[st] = (values[st] || 0) + valor;
      counts[st] = (counts[st] || 0) + 1;
    });

    const colors = {
      'PAGO': '#10b981', 'RECEBIDO': '#10b981', 'MARCADO_RECEBIDO': '#f59e0b',
      'A_RECEBER': '#3b82f6',
      'ATRASADO': '#f43f5e',
      'CANCELADO': '#64748b',
      'OUTROS': '#94a3b8'
    };

    return Object.entries(values).map(([name, value]) => ({
      name,
      value,
      count: counts[name] || 0,
      color: colors[name] || colors['OUTROS']
    }));
  };

  // ... (previous code)

  // ... (previous code)

  // Fetch Juros Data
  useEffect(() => {
    const fetchJuros = async () => {
      try {
        const apiData = await extratoService.fetchJuros();
        const rawMensal = apiData?.mensal || [];
        const rawAnual = apiData?.anual || [];
        
        // Formatar dados para o gráfico baseado no filtro
        let formattedData = [];
        
        if (jurosFilter === 'mensal') {
          // Ordenar cronologicamente
          formattedData = rawMensal
            .sort((a, b) => {
              if (a.ano !== b.ano) return a.ano - b.ano;
              return a.mes - b.mes;
            })
            .map(item => ({
              name: `${item.ano}-${String(item.mes).padStart(2, '0')}`,
              valor: safeNumber(item.total)
            }))
            .slice(-12); // Pega apenas os últimos 12 registros se houver muitos
        } else {
          // Anual
          formattedData = rawAnual
            .sort((a, b) => a.ano - b.ano)
            .map(item => ({
              name: String(item.ano),
              valor: safeNumber(item.total)
            }));
        }

        setJurosData(formattedData);

      } catch (error) {
        console.error("Erro ao buscar dados de juros:", error);
      }
    };

    fetchJuros();
  }, [jurosFilter]);


  const getJurosData = () => {
      return jurosData;
  };
  
  // ... (remove getProjectionData)

  const getUltimasTransacoes = (limit = 10) => {
    const hoje = new Date();
    // Definir data limite: 7 dias atrás (incluindo hoje = 6 dias atrás a partir de hoje?)
    // "exatos 7 dias contanto com o dia atual" -> Hoje + 6 dias para trás.
    const dataLimite = new Date();
    dataLimite.setDate(hoje.getDate() - 6);
    dataLimite.setHours(0, 0, 0, 0);

    return [...data.extrato]
      .filter(item => {
        if (!item.dataEntrada) return false;
        
        const { day, month, year } = parseDateInfo(item.dataEntrada);
        if (!year) return false;
        
        const dataItemSemHora = new Date(year, month - 1, day);
        dataItemSemHora.setHours(0, 0, 0, 0);
        
        return dataItemSemHora >= dataLimite && dataItemSemHora <= hoje;
      })
      .sort((a, b) => {
          const pA = parseDateInfo(a.dataEntrada);
          const pB = parseDateInfo(b.dataEntrada);
          return new Date(pB.year, pB.month - 1, pB.day) - new Date(pA.year, pA.month - 1, pA.day);
      })
      .slice(0, limit)
      .map(item => {
          // Enriquecer com nome da categoria
          const categoriaObj = data.categorias?.find(c => c.id == item.categoria);
          return {
              ...item,
              categoriaNome: categoriaObj ? categoriaObj.nome : null
          };
      });
  };

  return {
    loading,
    error,
    resumo,
    getFluxoBarData,
    getBoletosPieData,
    getJurosData,
    jurosFilter,
    setJurosFilter,
    fluxoPeriodo,
    setFluxoPeriodo,
    getUltimasTransacoes,
    fetchEntradasMes: async (mes, ano) => {
      try {
        const allExtrato = await extratoService.fetchExtrato();
        return allExtrato.filter(item => {
          if (!item.dataEntrada) return false;
          const { month: m, year: y } = parseDateInfo(item.dataEntrada);
          return m === mes && y === ano && item.tipoOperacao === 'C';
        });
      } catch (err) {
        console.error('Error fetching entradas mes from extrato:', err);
        return [];
      }
    },
    fetchSaidasPeriodo: async (mes, ano) => {
      try {
        const allExtrato = await extratoService.fetchExtrato();
        return allExtrato.filter(item => {
          if (!item.dataEntrada) return false;
          const { month: m, year: y } = parseDateInfo(item.dataEntrada);
          return m === mes && y === ano && item.tipoOperacao === 'D';
        });
      } catch (err) {
        console.error('Error fetching saidas periodo from extrato:', err);
        return [];
      }
    },
    fetchTransacoesNaoConciliadas: async (mes, ano) => {
      try {
        const allExtrato = await extratoService.fetchExtrato({ mes, ano });
        return allExtrato.filter(item => !item.categoria || item.categoria == 0);
      } catch (err) {
        return [];
      }
    },
    fetchBoletosAbertos: async () => {
      try {
        const result = await boletosService.fetchBoletosStatus();
        return (result.cobrancas || []).filter(item => {
          const c = item.cobranca || item;
          return c.situacao === 'A_RECEBER' || c.situacao === 'ATRASADO';
        });
      } catch (err) {
        return [];
      }
    },
    fetchJurosAdicionados: async (mes, ano) => {
      try {
        return await extratoService.fetchJurosAdicionados({ mes, ano });
      } catch (err) {
        console.error('Error fetching juros adicionados:', err);
        return { dados: [], total_adicionado: 0, total_registros: 0 };
      }
    },
    reload: loadData
  };
};

