<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Transaction;
use App\Models\Category;
use App\Models\Account;
use App\Models\LiabilityAccount;
use App\Models\RecurringTemplate;
use App\Models\Budget;
use App\Models\FinancialGoal;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Carbon\Carbon;

class ReportController extends Controller
{
    /**
     * Resumen general de reportes
     */
    public function summary(Request $request)
    {
        $userId = Auth::id();
        $year = $request->get('year', now()->year);
        
        // Ingresos y gastos del año
        $yearData = Transaction::where('user_id', $userId)
            ->whereYear('effective_date', $year)
            ->selectRaw("
                SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) as income,
                SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) as expense
            ")
            ->first();
        
        // Comparar con año anterior
        $lastYearData = Transaction::where('user_id', $userId)
            ->whereYear('effective_date', $year - 1)
            ->selectRaw("
                SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) as income,
                SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) as expense
            ")
            ->first();
        
        return response()->json([
            'year' => $year,
            'current' => [
                'income' => $yearData->income ?? 0,
                'expense' => $yearData->expense ?? 0,
                'balance' => ($yearData->income ?? 0) - ($yearData->expense ?? 0),
            ],
            'previous' => [
                'income' => $lastYearData->income ?? 0,
                'expense' => $lastYearData->expense ?? 0,
                'balance' => ($lastYearData->income ?? 0) - ($lastYearData->expense ?? 0),
            ],
            'variation' => [
                'income' => $lastYearData->income > 0 
                    ? round((($yearData->income - $lastYearData->income) / $lastYearData->income) * 100, 1) 
                    : 0,
                'expense' => $lastYearData->expense > 0 
                    ? round((($yearData->expense - $lastYearData->expense) / $lastYearData->expense) * 100, 1) 
                    : 0,
            ],
        ]);
    }

    /**
     * Reporte por categorías
     */
    public function byCategory(Request $request)
    {
        $userId = Auth::id();
        $startDate = $request->get('start_date', now()->startOfYear()->format('Y-m-d'));
        $endDate = $request->get('end_date', now()->format('Y-m-d'));
        $type = $request->get('type', 'debit'); // debit o credit
        
        $data = Transaction::where('user_id', $userId)
            ->whereBetween('effective_date', [$startDate, $endDate])
            ->where('type', $type)
            ->whereNotNull('category_id')
            ->join('categories', 'transactions.category_id', '=', 'categories.id')
            ->selectRaw("
                COALESCE(categories.parent_id, categories.id) as category_group_id,
                SUM(ABS(transactions.amount)) as total
            ")
            ->groupBy('category_group_id')
            ->orderByDesc('total')
            ->get();
        
        // Obtener nombres de categorías
        $categoryIds = $data->pluck('category_group_id')->unique();
        $categories = Category::whereIn('id', $categoryIds)->get()->keyBy('id');
        
        $result = $data->map(function($item) use ($categories) {
            $category = $categories->get($item->category_group_id);
            return [
                'category_id' => $item->category_group_id,
                'category_name' => $category ? $category->name : 'Sin categoría',
                'icon' => $category ? $category->icon : 'bi-tag',
                'color' => $category ? $category->color : '#6b7280',
                'total' => round($item->total, 2),
            ];
        });
        
        $grandTotal = $result->sum('total');
        
        // Añadir porcentajes
        $result = $result->map(function($item) use ($grandTotal) {
            $item['percentage'] = $grandTotal > 0 ? round(($item['total'] / $grandTotal) * 100, 1) : 0;
            return $item;
        });
        
        return response()->json([
            'data' => $result->values(),
            'total' => $grandTotal,
            'period' => [
                'start' => $startDate,
                'end' => $endDate,
            ],
        ]);
    }

    /**
     * Reporte de evolución mensual
     */
    public function monthlyEvolution(Request $request)
    {
        $userId = Auth::id();
        $months = $request->get('months', 12);
        
        $data = Transaction::where('user_id', $userId)
            ->where('effective_date', '>=', now()->subMonths($months)->startOfMonth())
            ->selectRaw("
                DATE_FORMAT(effective_date, '%Y-%m') as month,
                SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) as income,
                SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) as expense
            ")
            ->groupBy('month')
            ->orderBy('month')
            ->get();
        
        // Calcular balance acumulado y tasa de ahorro
        $result = $data->map(function($item) {
            $balance = $item->income - $item->expense;
            $savingsRate = $item->income > 0 ? round(($balance / $item->income) * 100, 1) : 0;
            
            return [
                'month' => $item->month,
                'month_label' => Carbon::parse($item->month . '-01')->format('M Y'),
                'income' => round($item->income, 2),
                'expense' => round($item->expense, 2),
                'balance' => round($balance, 2),
                'savings_rate' => $savingsRate,
            ];
        });
        
        return response()->json([
            'data' => $result,
            'averages' => [
                'income' => round($result->avg('income'), 2),
                'expense' => round($result->avg('expense'), 2),
                'balance' => round($result->avg('balance'), 2),
                'savings_rate' => round($result->avg('savings_rate'), 1),
            ],
        ]);
    }

    /**
     * Reporte de gastos por día de la semana
     */
    public function byDayOfWeek(Request $request)
    {
        $userId = Auth::id();
        $months = $request->get('months', 6);
        
        $data = Transaction::where('user_id', $userId)
            ->where('type', 'debit')
            ->where('effective_date', '>=', now()->subMonths($months))
            ->selectRaw("
                DAYOFWEEK(effective_date) as day_num,
                COUNT(*) as count,
                SUM(ABS(amount)) as total,
                AVG(ABS(amount)) as average
            ")
            ->groupBy('day_num')
            ->orderBy('day_num')
            ->get();
        
        $days = ['Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'];
        
        $result = $data->map(function($item) use ($days) {
            return [
                'day' => $days[$item->day_num - 1],
                'day_num' => $item->day_num,
                'count' => $item->count,
                'total' => round($item->total, 2),
                'average' => round($item->average, 2),
            ];
        });
        
        return response()->json($result);
    }

    /**
     * Top gastos
     */
    public function topExpenses(Request $request)
    {
        $userId = Auth::id();
        $startDate = $request->get('start_date', now()->startOfMonth()->format('Y-m-d'));
        $endDate = $request->get('end_date', now()->format('Y-m-d'));
        $limit = $request->get('limit', 20);
        
        $transactions = Transaction::where('user_id', $userId)
            ->where('type', 'debit')
            ->whereBetween('effective_date', [$startDate, $endDate])
            ->with(['category', 'account'])
            ->orderByRaw('ABS(amount) DESC')
            ->limit($limit)
            ->get();
        
        return response()->json([
            'data' => $transactions->map(function($t) {
                return [
                    'id' => $t->id,
                    'description' => $t->description,
                    'amount' => abs($t->amount),
                    'date' => $t->effective_date->format('Y-m-d'),
                    'category' => $t->category ? $t->category->name : null,
                    'account' => $t->account ? $t->account->name : null,
                ];
            }),
            'total' => $transactions->sum(fn($t) => abs($t->amount)),
        ]);
    }

    /**
     * Comparativa de períodos
     */
    public function comparePeriods(Request $request)
    {
        $userId = Auth::id();
        $period1Start = $request->get('period1_start');
        $period1End = $request->get('period1_end');
        $period2Start = $request->get('period2_start');
        $period2End = $request->get('period2_end');
        
        // Si no se especifican, comparar mes actual vs anterior
        if (!$period1Start) {
            $period1Start = now()->startOfMonth()->format('Y-m-d');
            $period1End = now()->endOfMonth()->format('Y-m-d');
            $period2Start = now()->subMonth()->startOfMonth()->format('Y-m-d');
            $period2End = now()->subMonth()->endOfMonth()->format('Y-m-d');
        }
        
        $getPeriodData = function($start, $end) use ($userId) {
            return Transaction::where('user_id', $userId)
                ->whereBetween('effective_date', [$start, $end])
                ->selectRaw("
                    SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) as income,
                    SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) as expense,
                    COUNT(*) as transactions
                ")
                ->first();
        };
        
        $period1 = $getPeriodData($period1Start, $period1End);
        $period2 = $getPeriodData($period2Start, $period2End);
        
        return response()->json([
            'period1' => [
                'label' => Carbon::parse($period1Start)->format('M Y'),
                'start' => $period1Start,
                'end' => $period1End,
                'income' => $period1->income ?? 0,
                'expense' => $period1->expense ?? 0,
                'balance' => ($period1->income ?? 0) - ($period1->expense ?? 0),
                'transactions' => $period1->transactions ?? 0,
            ],
            'period2' => [
                'label' => Carbon::parse($period2Start)->format('M Y'),
                'start' => $period2Start,
                'end' => $period2End,
                'income' => $period2->income ?? 0,
                'expense' => $period2->expense ?? 0,
                'balance' => ($period2->income ?? 0) - ($period2->expense ?? 0),
                'transactions' => $period2->transactions ?? 0,
            ],
            'variation' => [
                'income' => ($period2->income ?? 0) > 0 
                    ? round(((($period1->income ?? 0) - ($period2->income ?? 0)) / ($period2->income ?? 1)) * 100, 1) 
                    : 0,
                'expense' => ($period2->expense ?? 0) > 0 
                    ? round(((($period1->expense ?? 0) - ($period2->expense ?? 0)) / ($period2->expense ?? 1)) * 100, 1) 
                    : 0,
            ],
        ]);
    }

    /**
     * Reporte de cuentas
     */
    public function accountsReport(Request $request)
    {
        $userId = Auth::id();
        
        $accounts = Account::where('user_id', $userId)
            ->withCount('transactions')
            ->get();
        
        $result = $accounts->map(function($account) {
            // Últimas transacciones
            $recentActivity = Transaction::where('account_id', $account->id)
                ->orderBy('effective_date', 'desc')
                ->limit(5)
                ->get(['id', 'description', 'amount', 'type', 'effective_date']);
            
            // Movimientos del mes
            $monthStats = Transaction::where('account_id', $account->id)
                ->whereMonth('effective_date', now()->month)
                ->whereYear('effective_date', now()->year)
                ->selectRaw("
                    SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) as income,
                    SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) as expense
                ")
                ->first();
            
            return [
                'id' => $account->id,
                'name' => $account->name,
                'type' => $account->type,
                'currency' => $account->currency,
                'balance' => $account->current_balance,
                'transactions_count' => $account->transactions_count,
                'month_income' => $monthStats->income ?? 0,
                'month_expense' => $monthStats->expense ?? 0,
                'recent_activity' => $recentActivity,
            ];
        });
        
        return response()->json([
            'accounts' => $result,
            'summary' => [
                'total_accounts' => $accounts->count(),
                'total_balance' => $accounts->where('include_in_total', true)->sum('current_balance'),
            ],
        ]);
    }

    /**
     * Proyección de gastos
     */
    public function projection(Request $request)
    {
        $userId = Auth::id();
        $months = $request->get('months', 3);
        
        // Obtener promedio de los últimos meses
        $historical = Transaction::where('user_id', $userId)
            ->where('effective_date', '>=', now()->subMonths($months)->startOfMonth())
            ->where('effective_date', '<', now()->startOfMonth())
            ->selectRaw("
                AVG(CASE WHEN type = 'credit' THEN amount ELSE NULL END) as avg_income,
                AVG(CASE WHEN type = 'debit' THEN ABS(amount) ELSE NULL END) as avg_expense,
                SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) / ? as monthly_income,
                SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) / ? as monthly_expense
            ", [$months, $months])
            ->first();
        
        // Gastos del mes actual
        $currentMonth = Transaction::where('user_id', $userId)
            ->whereMonth('effective_date', now()->month)
            ->whereYear('effective_date', now()->year)
            ->selectRaw("
                SUM(CASE WHEN type = 'credit' THEN amount ELSE 0 END) as income,
                SUM(CASE WHEN type = 'debit' THEN ABS(amount) ELSE 0 END) as expense
            ")
            ->first();
        
        // Días transcurridos y restantes
        $daysElapsed = now()->day;
        $daysInMonth = now()->daysInMonth;
        $daysRemaining = $daysInMonth - $daysElapsed;
        
        // Proyección del mes
        $projectedExpense = ($currentMonth->expense / $daysElapsed) * $daysInMonth;
        $projectedIncome = ($currentMonth->income / $daysElapsed) * $daysInMonth;
        
        return response()->json([
            'historical_average' => [
                'income' => round($historical->monthly_income ?? 0, 2),
                'expense' => round($historical->monthly_expense ?? 0, 2),
            ],
            'current_month' => [
                'income' => round($currentMonth->income ?? 0, 2),
                'expense' => round($currentMonth->expense ?? 0, 2),
                'days_elapsed' => $daysElapsed,
                'days_remaining' => $daysRemaining,
            ],
            'projection' => [
                'income' => round($projectedIncome, 2),
                'expense' => round($projectedExpense, 2),
                'balance' => round($projectedIncome - $projectedExpense, 2),
            ],
            'vs_average' => [
                'income' => ($historical->monthly_income ?? 0) > 0 
                    ? round((($projectedIncome - ($historical->monthly_income ?? 0)) / ($historical->monthly_income ?? 1)) * 100, 1) 
                    : 0,
                'expense' => ($historical->monthly_expense ?? 0) > 0 
                    ? round((($projectedExpense - ($historical->monthly_expense ?? 0)) / ($historical->monthly_expense ?? 1)) * 100, 1) 
                    : 0,
            ],
        ]);
    }

    /**
     * Reporte de recurrencias
     */
    public function recurringReport(Request $request)
    {
        $userId = Auth::id();
        
        $templates = RecurringTemplate::where('user_id', $userId)
            ->where('is_active', true)
            ->with(['category', 'account'])
            ->get();
        
        $monthlyIncome = $templates->where('type', 'credit')->sum('amount');
        $monthlyExpense = $templates->where('type', 'debit')->sum(fn($t) => abs($t->amount));
        
        return response()->json([
            'templates' => $templates->map(function($t) {
                return [
                    'id' => $t->id,
                    'description' => $t->description,
                    'amount' => abs($t->amount),
                    'type' => $t->type,
                    'frequency' => $t->frequency,
                    'category' => $t->category ? $t->category->name : null,
                    'next_date' => $t->next_occurrence_date,
                ];
            }),
            'summary' => [
                'total_recurring' => $templates->count(),
                'monthly_income' => $monthlyIncome,
                'monthly_expense' => $monthlyExpense,
                'net_recurring' => $monthlyIncome - $monthlyExpense,
            ],
        ]);
    }
}
