import { supabase } from "@/integrations/supabase/client"; import { CategorySummary, MonthlyData, ResumoFinanceiro } from "@/types/financialTypes"; import { getUserEmail, getUserGroups } from "./baseService"; /** * Get transaction summary (total income, expenses, balance) * @returns Promise with transaction summary */ export async function getTransactionSummary(): Promise<{ totalReceitas: number; totalDespesas: number; saldo: number }> { console.log("📊 [getTransactionSummary] Calculando resumo de transações..."); const normalizedEmail = getUserEmail(); if (!normalizedEmail) { console.error("❌ [getTransactionSummary] Email não encontrado"); return { totalReceitas: 0, totalDespesas: 0, saldo: 0 }; } try { const groupIds = await getUserGroups(normalizedEmail); let query = supabase.from('transacoes').select('tipo, valor'); if (groupIds.length > 0) { const orFilter = `login.eq.${normalizedEmail},grupo_id.in.(${groupIds.map(id => `"${id}"`).join(',')})`; query = query.or(orFilter); } else { query = query.eq('login', normalizedEmail); } const { data, error } = await query; if (error) { console.error('❌ [getTransactionSummary] Erro:', error); return { totalReceitas: 0, totalDespesas: 0, saldo: 0 }; } const receitas = data .filter(t => t.tipo?.toLowerCase() === 'receita') .reduce((sum, t) => sum + Number(t.valor || 0), 0); const despesas = data .filter(t => t.tipo?.toLowerCase() === 'despesa') .reduce((sum, t) => sum + Number(t.valor || 0), 0); const saldo = receitas - despesas; console.log(`📊 [getTransactionSummary] Receitas: ${receitas}, Despesas: ${despesas}, Saldo: ${saldo}`); return { totalReceitas: receitas, totalDespesas: despesas, saldo }; } catch (error) { console.error('💥 [getTransactionSummary] Erro geral:', error); return { totalReceitas: 0, totalDespesas: 0, saldo: 0 }; } } /** * Get financial summary including credit cards * @returns Promise with complete financial summary */ export async function getResumoFinanceiro(): Promise { console.log("📊 [getResumoFinanceiro] Calculando resumo financeiro completo..."); const normalizedEmail = getUserEmail(); if (!normalizedEmail) { console.error("❌ [getResumoFinanceiro] Email não encontrado"); return { totalReceitas: 0, totalDespesas: 0, totalCartoes: 0, saldo: 0 }; } try { const groupIds = await getUserGroups(normalizedEmail); let query = supabase.from('transacoes').select('tipo, valor'); if (groupIds.length > 0) { const orFilter = `login.eq.${normalizedEmail},grupo_id.in.(${groupIds.map(id => `"${id}"`).join(',')})`; query = query.or(orFilter); } else { query = query.eq('login', normalizedEmail); } const { data, error } = await query; if (error) { console.error('❌ [getResumoFinanceiro] Erro:', error); return { totalReceitas: 0, totalDespesas: 0, totalCartoes: 0, saldo: 0 }; } const receitas = data .filter(t => t.tipo?.toLowerCase() === 'receita') .reduce((sum, t) => sum + Number(t.valor || 0), 0); const despesas = data .filter(t => t.tipo?.toLowerCase() === 'despesa') .reduce((sum, t) => sum + Number(t.valor || 0), 0); // Get credit card expenses const { data: cartaoData, error: cartaoError } = await supabase .from('despesas_cartao') .select('valor') .eq('login', normalizedEmail); const totalCartoes = cartaoError ? 0 : (cartaoData || []).reduce((sum, despesa) => sum + Number(despesa.valor || 0), 0); const saldo = receitas - despesas - totalCartoes; console.log(`📊 [getResumoFinanceiro] Receitas: ${receitas}, Despesas: ${despesas}, Cartões: ${totalCartoes}, Saldo: ${saldo}`); return { totalReceitas: receitas, totalDespesas: despesas, totalCartoes, saldo }; } catch (error) { console.error('💥 [getResumoFinanceiro] Erro geral:', error); return { totalReceitas: 0, totalDespesas: 0, totalCartoes: 0, saldo: 0 }; } } /** * Get category summary for expenses or income * @param tipo - Transaction type filter ('despesa', 'receita', 'all') * @returns Promise with array of category summaries */ export async function getCategorySummary(tipo: string = 'despesa'): Promise { console.log(`📋 [getCategorySummary] Obtendo resumo por categoria para tipo: ${tipo}`); const normalizedEmail = getUserEmail(); if (!normalizedEmail) { console.error("❌ [getCategorySummary] Email não encontrado"); return []; } try { const groupIds = await getUserGroups(normalizedEmail); let query = supabase.from('transacoes').select('categoria, valor, tipo'); if (groupIds.length > 0) { const orFilter = `login.eq.${normalizedEmail},grupo_id.in.(${groupIds.map(id => `"${id}"`).join(',')})`; query = query.or(orFilter); } else { query = query.eq('login', normalizedEmail); } // Apply type filter if not 'all' if (tipo !== 'all') { query = query.eq('tipo', tipo); } const { data, error } = await query; if (error) { console.error('❌ [getCategorySummary] Erro:', error); return []; } if (!data || data.length === 0) { console.warn(`⚠️ [getCategorySummary] Nenhuma transação encontrada para tipo: ${tipo}`); return []; } console.log(`📋 [getCategorySummary] Dados recebidos:`, data.map(d => ({ categoria: d.categoria, valor: d.valor, tipo: d.tipo }))); // Group by category and sum values const categoryMap: { [key: string]: number } = {}; let total = 0; data.forEach((transaction) => { // Usar a categoria exata ou 'Outros' se for null/undefined/vazia const categoria = transaction.categoria && transaction.categoria.trim() !== '' ? transaction.categoria.trim() : 'Outros'; const valor = Math.abs(Number(transaction.valor || 0)); console.log(`📋 [getCategorySummary] Processando: categoria='${categoria}', valor=${valor}`); categoryMap[categoria] = (categoryMap[categoria] || 0) + valor; total += valor; }); console.log(`📋 [getCategorySummary] Mapeamento final de categorias:`, categoryMap); console.log(`📋 [getCategorySummary] Total geral: ${total}`); // Enhanced color palette with more distinct colors - avoiding white/light colors const colors = [ '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7', '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9', '#F8C471', '#82E0AA', '#F1948A', '#85C1E9', '#D7BDE2', '#A3E4D7', '#FAD7A0', '#D5A6BD', '#AED6F1', '#A9DFBF', '#FF8A80', '#80CBC4', '#81C784', '#FFB74D', '#F48FB1', '#CE93D8', '#90CAF9', '#A5D6A7', '#FFCC02', '#FFAB40' ]; // Convert to CategorySummary array with colors const categoryArray = Object.entries(categoryMap) .map(([categoria, valor], index) => ({ categoria, valor, percentage: total > 0 ? valor / total : 0, color: colors[index % colors.length] })) .sort((a, b) => b.valor - a.valor); console.log(`📋 [getCategorySummary] ${categoryArray.length} categorias processadas:`, categoryArray); return categoryArray; } catch (error) { console.error('💥 [getCategorySummary] Erro geral:', error); return []; } } /** * Get monthly data for charts - full year * @returns Promise with array of monthly data */ export async function getMonthlyData(): Promise { console.log("📈 [getMonthlyData] Obtendo dados mensais do ano completo..."); const normalizedEmail = getUserEmail(); if (!normalizedEmail) { console.error("❌ [getMonthlyData] Email não encontrado"); return []; } try { const groupIds = await getUserGroups(normalizedEmail); let query = supabase.from('transacoes').select('quando, tipo, valor'); if (groupIds.length > 0) { const orFilter = `login.eq.${normalizedEmail},grupo_id.in.(${groupIds.map(id => `"${id}"`).join(',')})`; query = query.or(orFilter); } else { query = query.eq('login', normalizedEmail); } // Get full current year const currentYear = new Date().getFullYear(); const startDate = new Date(currentYear, 0, 1); // January 1st const endDate = new Date(currentYear, 11, 31); // December 31st query = query .gte('quando', startDate.toISOString().split('T')[0]) .lte('quando', endDate.toISOString().split('T')[0]); const { data, error } = await query; if (error) { console.error('❌ [getMonthlyData] Erro:', error); return []; } // Group by month const monthlyMap: { [key: string]: { receitas: number; despesas: number } } = {}; data?.forEach((transaction) => { const date = new Date(transaction.quando); const monthKey = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}`; if (!monthlyMap[monthKey]) { monthlyMap[monthKey] = { receitas: 0, despesas: 0 }; } const valor = Math.abs(Number(transaction.valor || 0)); if (transaction.tipo?.toLowerCase() === 'receita') { monthlyMap[monthKey].receitas += valor; } else { monthlyMap[monthKey].despesas += valor; } }); // Convert to array and sort const monthlyArray = Object.entries(monthlyMap) .map(([month, data]) => ({ month, receitas: data.receitas, despesas: data.despesas })) .sort((a, b) => a.month.localeCompare(b.month)); console.log(`📈 [getMonthlyData] ${monthlyArray.length} meses processados`); return monthlyArray; } catch (error) { console.error('💥 [getMonthlyData] Erro geral:', error); return []; } }