import api from './api';
import { handleRequest, simulateLatency } from './serviceUtils';

/**
 * Service de Extrato para financeiro-v2
 * Alimenta as telas de cruzamento (receitas e despesas) com /api/extrato/apresentar.
 * tipoOperacao: "C" = receitas (entradas), "D" = despesas (saídas).
 */
export const extratoService = {
  /**
   * Busca extrato bancário
   * Rota: GET /extrato/apresentar
   * Retorna array bruto; o consumidor filtra por tipoOperacao (C/D).
   * @param {Object} params - Opcional { mes, ano }
   * @returns {Promise<Array<{idextrato, dataEntrada, descricao, valor, tipoOperacao, categoria, beneficiario_pagador, ...}>>}
   */
  fetchExtrato: (params) => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/extrato/apresentar', { params });
      const raw = response?.data ?? response;
      
      // Lógica robusta de extração (igual ao workspaceConciliacaoService)
      // Prioridade: dados -> Base_Dados_API -> raw (se array) -> Object.values(raw)
      let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      
      if (!Array.isArray(data)) {
        // Se for objeto (ex: { '0': {...}, '1': {...} }), converte para array
        data = Object.values(data || {});
      }
      
      return Array.isArray(data) ? data : [];
    }
  }),

  /**
   * Categorias (opcional, para labels)
   * Rota: GET /categorias/apresentar
   */
  fetchCategorias: () => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/categorias/apresentar');
      const raw = response?.data ?? response;
      let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      
      if (!Array.isArray(data)) {
        data = Object.values(data || {});
      }
      return Array.isArray(data) ? data : [];
    }
  }),

  /**
   * Caixinhas (opcional, para labels)
   * Rota: GET /caixinhas/apresentar
   */
  fetchCaixinhas: () => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/caixinhas/apresentar');
      const raw = response?.data ?? response;
      let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      
      if (!Array.isArray(data)) {
        data = Object.values(data || {});
      }
      return Array.isArray(data) ? data : [];
    }
  }),

  /**
   * Saldo atual da conta
   * Rota: GET /saldo
   * Resposta: { bloqueado?, disponivel, total? }
   * @returns {Promise<{ disponivel: number, bloqueado?: number, total?: number }>}
   */
  fetchSaldo: () => handleRequest({
    mockFn: () => simulateLatency({ disponivel: 0, bloqueado: null, total: null }),
    apiFn: async () => {
      const response = await api.get('/saldo');
      // Tenta extrair de varias formas, pois saldo costuma variar a estrutura
      const raw = response?.data ?? response;
      const data = raw?.dados ?? raw?.Base_Dados_API ?? raw ?? {};
      
      const num = (v) => (v != null && v !== '' ? Number(v) : null);
      
      // Procura propriedade disponivel/saldo/valor em data ou no raw
      const disponivel = num(data.disponivel) ?? num(data.saldo) ?? num(data.valor) ?? 
                         num(raw.disponivel) ?? num(raw.saldo) ?? num(raw.valor) ?? 
                         (typeof data === 'number' ? data : 0);
                         
      return {
        disponivel: Number(disponivel) || 0,
        bloqueado: num(data.bloqueado ?? raw.bloqueado),
        total: num(data.total ?? raw.total)
      };
    }
  }),

  /**
   * Saldos armazenados (histórico)
   * Rota: GET /saldo/armazenado/apresentar
   * Pode retornar array ou objeto único { data_saldo, saldo_disponivel, ... }.
   * Usado para obter último saldo do mês passado (cruzamento fluxo de caixa).
   * @returns {Promise<Array<{ data?: string, data_saldo?: string, mes?: number, ano?: number, saldo?: number, saldo_disponivel?: string, ... }>>}
   */
  fetchSaldoArmazenado: () => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/saldo/armazenado/apresentar');
      const raw = response?.data ?? response;
      let list = raw?.dados ?? raw?.Base_Dados_API ?? raw;

      if (!Array.isArray(list)) {
        if (list && typeof list === 'object' && list !== null) {
          const keys = Object.keys(list);
          const isSingleRecord = keys.some(k => k === 'data_saldo' || k === 'saldo_disponivel' || k === 'idsaldos_mensais');
          if (isSingleRecord) {
            list = [list];
          } else {
            // Tenta converter objeto indexado em array
            list = Object.values(list).map(v => typeof v === 'object' ? v : { saldo: v });
          }
        } else {
          list = [];
        }
      }
      
      return list.map((item) => {
        const data = item.data ?? item.dataSaldo ?? item.data_saldo ?? item.data_armazenado;
        const d = data ? new Date(data) : null;
        const valid = d && !Number.isNaN(d.getTime());
        const saldoVal = item.saldo_disponivel ?? item.saldo ?? item.valor;
        const saldo = typeof saldoVal === 'string' ? Number(saldoVal.replace(',', '.')) : Number(saldoVal ?? 0);
        
        return {
          ...item,
          data: data ?? null,
          data_saldo: item.data_saldo ?? data,
          mes: item.mes ?? (valid ? d.getMonth() + 1 : null),
          ano: item.ano ?? (valid ? d.getFullYear() : null),
          saldo: Number.isFinite(saldo) ? saldo : 0
        };
      });
    }
  }),

  /**
   * Fluxo de entrada e saída mensal
   * Rota: GET /extrato/fluxo
   * Retorna dados mensais de entrada e saída
   * @param {Object} params - Opcional { mes, ano }
   * @returns {Promise<{ mensal: Array<{ mes, ano, entrada, saida, ... }> }>}
   */
  fetchFluxo: (params) => handleRequest({
    mockFn: () => simulateLatency({ mensal: [], anual: [], diario: [] }),
    apiFn: async () => {
      const response = await api.get('/extrato/fluxo', { params });
      const raw = response?.data ?? response;
      const data = raw?.dados ?? raw?.Base_Dados_API ?? raw ?? {};
      
      const mensal = data.mensal ?? raw.mensal ?? [];
      const anual = data.anual ?? raw.anual ?? [];
      const diario = data.diario ?? raw.diario ?? [];
      
      const toArray = (obj) => Array.isArray(obj) ? obj : (obj ? Object.values(obj) : []);

      return {
        mensal: toArray(mensal),
        anual: toArray(anual),
        diario: toArray(diario)
      };
    }
  }),

  /**
   * Busca soma por categoria
   * Rota: GET /extrato/soma_por_categoria
   * @param {Object} params - { mes, ano, tipoOperacao }
   */
  getSomaPorCategoria: (params) => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/extrato/soma_por_categoria', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Exporta extrato em PDF
   * Rota: GET /extrato/pdf
   */
  exportPDF: () => handleRequest({
    mockFn: () => simulateLatency(new Blob(['PDF mock'], { type: 'application/pdf' })),
    apiFn: async () => {
      const response = await api.get('/extrato/pdf', {
        responseType: 'blob'
      });
      return response.data;
    }
  }),

  /**
   * Busca navegação hierárquica detalhada por caixinha
   * Rota: GET /extrato/apresentar/caixinha/detalhado
   * @param {Object} params - { caixinha, mes, ano }
   */
  getCaixinhaDetalhada: (params) => handleRequest({
    mockFn: () => simulateLatency({}),
    apiFn: async () => {
      const response = await api.get('/extrato/apresentar/caixinha/detalhado', {
        params
      });
      return response.data;
    }
  }),

  /**
   * Busca saldo consolidado com entradas e saídas do mês vigente e saldo anterior
   * Rota: GET /saldo/entradas_mes_mais_ultimo_saldo
   * @param {Object} params - { mes, ano }
   */
  fetchSaldoConsolidado: (params) => handleRequest({
    mockFn: () => simulateLatency({ entradas: 0, saidas: 0, saldo_anterior: 0, saldo_atual: 0, lista_entradas: [] }),
    apiFn: async () => {
      const response = await api.get('/saldo/entradas_mes_mais_ultimo_saldo', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Busca empresas/clientes financeiros
   * Rota: GET /empresas_financeiro
   * @returns {Promise<Array>}
   */
  fetchEmpresas: () => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/empresas_financeiro');
      const raw = response?.data ?? response;
      let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      
      if (!Array.isArray(data)) {
        data = Object.values(data || {});
      }
      return Array.isArray(data) ? data : [];
    }
  }),
  
  /**
   * Busca dados de recebimento de juros (mensal e anual)
   * Rota: GET /extrato/mensal_anual
   * @returns {Promise<{ mensal: Array, anual: Array }>}
   */
  fetchJuros: () => handleRequest({
    mockFn: () => simulateLatency({ mensal: [], anual: [] }),
    apiFn: async () => {
      const response = await api.get('/extrato/mensal_anual');
      return response?.data ?? response;
    }
  }),

  /**
   * Busca soma de recebimentos via PIX para o painel
   * Rota: GET /extrato/pix
   */
  fetchPixSoma: () => handleRequest({
    mockFn: () => simulateLatency({ total: 0, quantidade: 0 }),
    apiFn: async () => {
      const response = await api.get('/extrato/pix');
      return response?.data ?? response;
    }
  }),

  /**
   * Busca lista de itens recebidos via PIX para apresentar
   * Rota: GET /extrato/pix/apresentar
   */
  fetchPixApresentar: () => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/extrato/pix/apresentar');
      const raw = response?.data ?? response;
      let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      if (!Array.isArray(data)) {
        data = Object.values(data || {});
      }
      return Array.isArray(data) ? data : [];
    }
  }),

  /**
   * Busca dados detalhados de PIX por empresa
   * Rota: GET /extrato/pix/empresas
   * @param {Object} params - { mes, ano } (opcional)
   * @returns {Promise<Array>}
   */
  fetchPixEmpresas: (params) => handleRequest({
    mockFn: () => simulateLatency([]),
    apiFn: async () => {
      const response = await api.get('/extrato/pix/empresas', { params });
      const raw = response?.data ?? response;
      let data = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      if (!Array.isArray(data)) {
        data = Object.values(data || {});
      }
      return Array.isArray(data) ? data : [];
    }
  }),

  /**
   * Busca totais de entradas planejadas para o painel de cruzamento
   * Rota: GET /financeiro/resumo_mes
   * @param {Object} params - { mes, ano }
   */
  fetchEntradasPlanejadasTotal: (params) => handleRequest({
    mockFn: () => simulateLatency({
      mes: Number(params.mes),
      ano: Number(params.ano),
      total_planejado: 0,
      total_boletos_a_receber: 0,
      total_planejado_geral: 0,
      total_realizado: 0,
      diferenca: 0
    }),
    apiFn: async () => {
      const response = await api.get('/financeiro/resumo_mes', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Busca dados para o gráfico de planejado vs executado (Receitas)
   * Rota: GET /extrato/planejado/grafico
   * @param {Object} params - { dia, mes, ano }
   */
  fetchPlanejadoGrafico: (params) => handleRequest({
    mockFn: () => simulateLatency({ filtro: params, grafico: [] }),
    apiFn: async () => {
      const response = await api.get('/extrato/planejado/grafico', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Busca totais de despesas planejadas para o painel de cruzamento
   * Rota: GET /financeiro/despesas_mes
   * @param {Object} params - { mes, ano }
   */
  fetchDespesasResumo: (params) => handleRequest({
    mockFn: () => simulateLatency({
      mes: Number(params.mes),
      ano: Number(params.ano),
      total_planejado: 0,
      total_realizado: 0,
      diferenca: 0
    }),
    apiFn: async () => {
      const response = await api.get('/financeiro/despesas_mes', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Busca dados para o gráfico de planejado vs executado (Despesas)
   * Rota: GET /extrato/despesas/grafico
   * @param {Object} params - { dia, mes, ano }
   */
  fetchDespesasGrafico: (params) => handleRequest({
    mockFn: () => simulateLatency({ filtro: params, grafico: [] }),
    apiFn: async () => {
      const response = await api.get('/extrato/despesas/grafico', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Busca detalhamento de juros adicionados
   * Rota: GET /extrato/adicionado
   * @param {Object} params - { mes, ano }
   */
  fetchJurosAdicionados: (params) => handleRequest({
    mockFn: () => simulateLatency({ adicionado: [], total_adicionado: 0, total_registros: 0 }),
    apiFn: async () => {
      const response = await api.get('/extrato/adicionado', { params });
      return response?.data ?? response;
    }
  }),

  /**
   * Busca transações de um beneficiário específico
   * Rota: POST /beneficiario_aplicado
   * Resposta esperada: { "categoria": "NOME DO CLIENTE", "linha_tempo": [...] }
   * Retorna: { categoria: string, linhaTemp: Array }
   * @param {Object} data - { beneficiario_pagador, seuNumero }
   */
  fetchBeneficiarioAplicado: (data) => handleRequest({
    mockFn: () => simulateLatency({ categoria: '', linha_tempo: [] }),
    apiFn: async () => {
      const response = await api.post('/beneficiario_aplicado', { 
        beneficiario_pagador: data?.beneficiario_pagador,
        seuNumero: data?.seuNumero
      });
      const raw = response?.data ?? response;
      // A resposta é um objeto com "categoria" e "linha_tempo"
      const root = raw?.dados ?? raw?.Base_Dados_API ?? raw;
      const categoria = root?.categoria ?? '';
      const linhaTemp = root?.linha_tempo ?? [];
      return {
        categoria,
        linha_tempo: Array.isArray(linhaTemp) ? linhaTemp : []
      };
    }
  })
};

