<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Budget;
use App\Models\Category;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;

class BudgetController extends Controller
{
    /**
     * Listar presupuestos de un período
     */
    public function index(Request $request)
    {
        $year = $request->get('year', now()->year);
        $month = $request->get('month', now()->month);
        
        $budgets = Budget::forUser(Auth::id())
            ->forPeriod($year, $month)
            ->active()
            ->with(['category', 'subcategory', 'costCenter'])
            ->orderBy('amount', 'desc')
            ->get();
        
        // Calcular totales
        $totalBudget = $budgets->sum('amount');
        $totalSpent = $budgets->sum('spent_amount');
        $totalRemaining = $totalBudget - $totalSpent;
        
        return response()->json([
            'data' => $budgets,
            'summary' => [
                'total_budget' => $totalBudget,
                'total_spent' => $totalSpent,
                'total_remaining' => $totalRemaining,
                'usage_percentage' => $totalBudget > 0 ? round(($totalSpent / $totalBudget) * 100, 1) : 0,
                'year' => $year,
                'month' => $month,
                'period_label' => Carbon::createFromDate($year, $month, 1)->format('F Y'),
            ],
        ]);
    }

    /**
     * Crear un presupuesto (con propagación automática a meses futuros)
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'category_id' => 'nullable|exists:categories,id',
            'subcategory_id' => 'nullable|exists:categories,id',
            'cost_center_id' => 'nullable|exists:cost_centers,id',
            'name' => 'nullable|string|max:255',
            'amount' => 'required|numeric|min:0.01',
            'currency' => 'nullable|string|size:3',
            'year' => 'required|integer|min:2020|max:2100',
            'month' => 'required|integer|min:1|max:12',
            'period_type' => 'nullable|in:monthly,bimestral,trimestral,semestral,yearly',
            'is_cumulative' => 'nullable|boolean',
            'notes' => 'nullable|string',
        ]);
        
        // Validar que ao menos uma (categoria, subcategoria ou centro de custos) esteja preenchida
        if (empty($validated['category_id']) && empty($validated['subcategory_id']) && empty($validated['cost_center_id'])) {
            return response()->json([
                'message' => 'Debe especificar al menos una categoría, subcategoría o centro de custos',
            ], 422);
        }
        
        // Validar que subcategoria pertence à categoria (se ambas fornecidas)
        if (!empty($validated['subcategory_id']) && !empty($validated['category_id'])) {
            $subcat = Category::find($validated['subcategory_id']);
            if ($subcat && $subcat->parent_id != $validated['category_id']) {
                return response()->json([
                    'message' => 'A subcategoria não pertence à categoria selecionada',
                ], 422);
            }
        }
        
        // Se tem subcategoria mas não tem categoria, buscar a categoria pai
        if (!empty($validated['subcategory_id']) && empty($validated['category_id'])) {
            $subcat = Category::find($validated['subcategory_id']);
            if ($subcat && $subcat->parent_id) {
                $validated['category_id'] = $subcat->parent_id;
            }
        }
        
        // Verificar que no exista ya
        $exists = Budget::forUser(Auth::id())
            ->where('category_id', $validated['category_id'])
            ->where('subcategory_id', $validated['subcategory_id'] ?? null)
            ->where('cost_center_id', $validated['cost_center_id'] ?? null)
            ->where('year', $validated['year'])
            ->where('month', $validated['month'])
            ->exists();
        
        if ($exists) {
            return response()->json([
                'message' => 'Ya existe un presupuesto para esta categoría/subcategoría en este período',
            ], 422);
        }
        
        $validated['user_id'] = Auth::id();
                // Adicionar moeda primária do usuário se não fornecida
        if (empty($validated['currency'])) {
            $validated['currency'] = Auth::user()->primary_currency ?? 'EUR';
        }
        
        // Crear el presupuesto del mes actual
        $budget = Budget::create($validated);
        
        // Determinar el salto de meses según period_type
        $periodType = $validated['period_type'] ?? 'monthly';
        $periodStepMap = [
            'monthly' => 1,      // A cada 1 mes (Jan, Feb, Mar, ..., Dec) = 12 presupuestos
            'bimestral' => 2,    // A cada 2 meses (Jan, Mar, May, Jul, Sep, Nov) = 6 presupuestos
            'trimestral' => 3,   // A cada 3 meses (Jan, Apr, Jul, Oct) = 4 presupuestos
            'semestral' => 6,    // A cada 6 meses (Jan, Jul) = 2 presupuestos
            'yearly' => 12,      // A cada 12 meses (solo Jan) = 1 presupuesto
        ];
        
        $step = $periodStepMap[$periodType] ?? 1;
        $currentYear = $validated['year'];
        $currentMonth = $validated['month'];
        
        // Propagar hasta completar 12 meses (1 año)
        for ($monthsAhead = $step; $monthsAhead < 12; $monthsAhead += $step) {
            $nextMonth = $currentMonth + $monthsAhead;
            $nextYear = $currentYear;
            
            if ($nextMonth > 12) {
                $nextMonth -= 12;
                $nextYear++;
            }
            
            // Solo crear si no existe
            $existsNext = Budget::forUser(Auth::id())
                ->where('category_id', $validated['category_id'])
                ->where('subcategory_id', $validated['subcategory_id'] ?? null)
                ->where('cost_center_id', $validated['cost_center_id'] ?? null)
                ->where('year', $nextYear)
                ->where('month', $nextMonth)
                ->exists();
            
            if (!$existsNext) {
                Budget::create([
                    'user_id' => Auth::id(),
                    'category_id' => $validated['category_id'],
                    'subcategory_id' => $validated['subcategory_id'] ?? null,
                    'cost_center_id' => $validated['cost_center_id'] ?? null,
                    'name' => $validated['name'] ?? null,
                    'amount' => $validated['amount'],
                    'currency' => $validated['currency'] ?? null,
                    'year' => $nextYear,
                    'month' => $nextMonth,
                    'period_type' => $validated['period_type'] ?? 'monthly',
                    'is_cumulative' => $validated['is_cumulative'] ?? false,
                    'notes' => $validated['notes'] ?? null,
                ]);
            }
        }
        
        return response()->json([
            'message' => 'Presupuesto creado y propagado',
            'data' => $budget->load(['category', 'subcategory', 'costCenter']),
        ], 201);
    }

    /**
     * Ver un presupuesto
     */
    public function show($id)
    {
        $budget = Budget::forUser(Auth::id())
            ->with(['category', 'subcategory', 'costCenter'])
            ->findOrFail($id);
        
        // Obtener transacciones del período
        $query = Transaction::where('user_id', Auth::id())
            ->where('transaction_type', 'debit')
            ->whereYear('effective_date', $budget->year)
            ->whereMonth('effective_date', $budget->month);
        
        // Se tem subcategoria específica, usa apenas ela
        if ($budget->subcategory_id) {
            $query->where('category_id', $budget->subcategory_id);
        }
        // Se tem apenas categoria, inclui subcategorias
        elseif ($budget->category_id) {
            $categoryIds = [$budget->category_id];
            $subcategories = Category::where('parent_id', $budget->category_id)->pluck('id')->toArray();
            $categoryIds = array_merge($categoryIds, $subcategories);
            $query->whereIn('category_id', $categoryIds);
        }
        
        $transactions = $query->with('category')
            ->orderBy('effective_date', 'desc')
            ->limit(50)
            ->get();
        
        return response()->json([
            'budget' => $budget,
            'transactions' => $transactions,
        ]);
    }

    /**
     * Actualizar un presupuesto
     */
    public function update(Request $request, $id)
    {
        $budget = Budget::forUser(Auth::id())->findOrFail($id);
        
        $validated = $request->validate([
            'amount' => 'sometimes|numeric|min:0.01',
            'notes' => 'nullable|string',
            'is_active' => 'sometimes|boolean',
        ]);
        
        $budget->update($validated);
        
        return response()->json([
            'message' => 'Presupuesto actualizado',
            'data' => $budget->fresh('category'),
        ]);
    }

    /**
     * Eliminar un presupuesto (y de meses futuros)
     */
    public function destroy($id)
    {
        $budget = Budget::forUser(Auth::id())->findOrFail($id);
        
        $categoryId = $budget->category_id;
        $subcategoryId = $budget->subcategory_id;
        $year = $budget->year;
        $month = $budget->month;
        
        $costCenterId = $budget->cost_center_id;

        // Eliminar este e todos os futuros da mesma categoria/subcategoria/centro de custos
        Budget::forUser(Auth::id())
            ->where('category_id', $categoryId)
            ->where('subcategory_id', $subcategoryId)
            ->where('cost_center_id', $costCenterId)
            ->where(function($q) use ($year, $month) {
                $q->where('year', '>', $year)
                  ->orWhere(function($q2) use ($year, $month) {
                      $q2->where('year', $year)
                         ->where('month', '>=', $month);
                  });
            })
            ->delete();
        
        return response()->json([
            'message' => 'Presupuesto eliminado (incluyendo meses futuros)',
        ]);
    }

    /**
     * Copiar presupuestos al siguiente mes
     */
    public function copyToNextMonth(Request $request)
    {
        $validated = $request->validate([
            'year' => 'required|integer',
            'month' => 'required|integer|min:1|max:12',
        ]);
        
        Budget::copyToNextMonth(Auth::id(), $validated['year'], $validated['month']);
        
        $nextMonth = $validated['month'] === 12 ? 1 : $validated['month'] + 1;
        $nextYear = $validated['month'] === 12 ? $validated['year'] + 1 : $validated['year'];
        
        return response()->json([
            'message' => 'Presupuestos copiados',
            'next_period' => [
                'year' => $nextYear,
                'month' => $nextMonth,
            ],
        ]);
    }

    /**
     * Obtener categorías disponibles para presupuesto
     */
    public function availableCategories(Request $request)
    {
        $year = $request->get('year', now()->year);
        $month = $request->get('month', now()->month);
        
        // Obtener pares (category_id, subcategory_id) já usados no período
        $usedPairs = Budget::forUser(Auth::id())
            ->forPeriod($year, $month)
            ->get()
            ->map(fn($b) => $b->category_id . '_' . ($b->subcategory_id ?? 'null'))
            ->toArray();
        
        // Categorías padre con tipo expense o both (gastos)
        $categories = Category::where('user_id', Auth::id())
            ->whereNull('parent_id')
            ->whereIn('type', ['expense', 'both'])
            ->with(['subcategories' => function($q) {
                $q->orderBy('name');
            }])
            ->orderBy('name')
            ->get();
        
        // Filtrar categorias/subcategorias já usadas
        $available = $categories->map(function($category) use ($usedPairs) {
            $categoryKey = $category->id . '_null';
            
            // Filtrar subcategorias não usadas
            $availableSubcategories = $category->subcategories->filter(function($sub) use ($usedPairs, $category) {
                $subKey = $category->id . '_' . $sub->id;
                return !in_array($subKey, $usedPairs);
            })->values();
            
            return [
                'id' => $category->id,
                'name' => $category->name,
                'type' => $category->type,
                'color' => $category->color,
                'icon' => $category->icon,
                'is_available' => !in_array($categoryKey, $usedPairs),
                'subcategories' => $availableSubcategories,
            ];
        })->filter(function($cat) {
            // Manter categoria se ela mesma está disponível OU se tem subcategorias disponíveis
            return $cat['is_available'] || $cat['subcategories']->count() > 0;
        })->values();
        
        return response()->json($available);
    }

    /**
     * Resumen anual de presupuestos
     */
    public function yearSummary(Request $request)
    {
        $year = $request->get('year', now()->year);
        
        $monthlyData = [];
        
        for ($month = 1; $month <= 12; $month++) {
            $budgets = Budget::forUser(Auth::id())
                ->forPeriod($year, $month)
                ->active()
                ->get();
            
            $totalBudget = $budgets->sum('amount');
            $totalSpent = $budgets->sum('spent_amount');
            
            $monthlyData[] = [
                'month' => $month,
                'month_name' => Carbon::createFromDate($year, $month, 1)->format('M'),
                'budgeted' => round($totalBudget, 2),
                'spent' => round($totalSpent, 2),
                'remaining' => round($totalBudget - $totalSpent, 2),
                'percentage' => $totalBudget > 0 ? round(($totalSpent / $totalBudget) * 100, 1) : 0,
            ];
        }
        
        return response()->json($monthlyData);
    }
}
