<?php

namespace App\Http\Controllers\Coach;

use App\Http\Controllers\Controller;
use App\Models\Client;
use App\Models\DietPlan;
use App\Models\Food;
use App\Models\MealPlan;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\AdminMealPlanCreated;
use App\Notifications\MealPlanAssigned;
use App\Notifications\MealPlanUpdated;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;

class MealPlanController extends Controller
{
    /**
     * Display a listing of meal plans for a client.
     */
    public function index(Request $request, Client $client): Response
    {
        $this->authorize('view', $client);

        return Inertia::render('Coach/MealPlans/Index', [
            'client' => $client,
            'mealPlans' => $client->mealPlans()
                ->with('dietPlans.items.food')
                ->latest()
                ->get()
                ->map(function ($plan) {
                    $plan->totals = $plan->calculateTotals();
                    return $plan;
                }),
        ]);
    }

    /**
     * Show the form for creating a new meal plan.
     */
    public function create(Request $request, Client $client): Response
    {
        $this->authorize('update', $client);

        // Get available foods (global + coach's custom)
        $foods = Food::where('is_custom', false)
            ->orWhere('user_id', $request->user()->id)
            ->orderBy('category')
            ->orderBy('name')
            ->get();

        // Load client with calculated macros
        $clientData = $client->toArray();
        $clientData['macros'] = $client->calculateMacros();

        return Inertia::render('Coach/MealPlans/Create', [
            'client' => $clientData,
            'foods' => $foods,
            'mealTypes' => Food::MEAL_TYPES,
        ]);
    }

    /**
     * Store a newly created meal plan.
     */
    public function store(Request $request, Client $client): RedirectResponse
    {
        $this->authorize('update', $client);

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string|max:1000',
            'notes' => 'nullable|string',
            'is_active' => 'boolean',
            'diet_plans' => 'required|array|min:1',
            'diet_plans.*.name' => 'required|string|max:255',
            'diet_plans.*.description' => 'nullable|string|max:1000',
            'diet_plans.*.days' => 'nullable|array',
            'diet_plans.*.use_percentages' => 'boolean',
            'diet_plans.*.protein_percent' => 'nullable|integer|min:0|max:100',
            'diet_plans.*.fat_percent' => 'nullable|integer|min:0|max:100',
            'diet_plans.*.carb_percent' => 'nullable|integer|min:0|max:100',
            'diet_plans.*.calorie_adjustment' => 'nullable|integer|min:-100|max:100',
            'diet_plans.*.meal_items' => 'required|array|min:1',
            'diet_plans.*.meal_items.*.food_id' => 'required|exists:foods,id',
            'diet_plans.*.meal_items.*.meal_type' => 'required|string',
            'diet_plans.*.meal_items.*.quantity' => 'required|numeric|min:0.1|max:2000',
            'diet_plans.*.meal_items.*.unit' => 'nullable|string|max:50',
        ]);

        // Deactivate other meal plans if this one should be active
        if ($request->boolean('is_active', true)) {
            $client->mealPlans()->update(['is_active' => false]);
        }

        // Calculate target macros based on client's TDEE
        $targetCalories = $client->tdee ?? null;

        $mealPlan = $client->mealPlans()->create([
            'name' => $validated['name'],
            'description' => $validated['description'] ?? null,
            'notes' => $validated['notes'] ?? null,
            'goal_type' => 'maintain',
            'goal_percentage' => 0,
            'target_calories' => $targetCalories,
            'is_active' => $request->boolean('is_active', true),
        ]);

        // Create diet plans with their meal items
        foreach ($validated['diet_plans'] as $planIndex => $planData) {
            $dietPlan = $mealPlan->dietPlans()->create([
                'name' => $planData['name'],
                'description' => $planData['description'] ?? null,
                'days' => $planData['days'] ?? [],
                'use_percentages' => $planData['use_percentages'] ?? true,
                'protein_percent' => $planData['protein_percent'] ?? 30,
                'fat_percent' => $planData['fat_percent'] ?? 25,
                'carb_percent' => $planData['carb_percent'] ?? 45,
                'calorie_adjustment' => $planData['calorie_adjustment'] ?? 0,
                'is_active' => true,
                'order' => $planIndex,
            ]);

            // Create meal items for this diet plan
            foreach ($planData['meal_items'] as $index => $itemData) {
                $food = Food::find($itemData['food_id']);
                $quantity = $itemData['quantity'];

                $dietPlan->items()->create([
                    'food_id' => $itemData['food_id'],
                    'meal_type' => $itemData['meal_type'],
                    'quantity' => $quantity,
                    'unit' => $itemData['unit'] ?? null,
                    'proteins' => round(($food->proteins ?? 0) * $quantity / 100, 2),
                    'carbs' => round(($food->carbs ?? 0) * $quantity / 100, 2),
                    'fats' => round(($food->fats ?? 0) * $quantity / 100, 2),
                    'calories' => round(($food->calories ?? 0) * $quantity / 100, 2),
                    'order' => $index,
                ]);
            }
        }

        // Send notification to client if they have a user account
        if ($client->clientUser) {
            $client->clientUser->notify(new MealPlanAssigned($mealPlan));
        }

        // Notify admins about new meal plan creation
        if (Setting::get('notify_new_meal_plan', true)) {
            $admins = User::where('role', 'admin')->where('status', 'active')->get();
            foreach ($admins as $admin) {
                $admin->notify(new AdminMealPlanCreated($mealPlan, $request->user()));
            }
        }

        return redirect()->route('coach.clients.meal-plans.show', [$client, $mealPlan])
            ->with('success', 'Plan de alimentación creado exitosamente con ' . count($validated['diet_plans']) . ' dieta(s).');
    }

    /**
     * Display the specified meal plan.
     */
    public function show(Request $request, Client $client, MealPlan $mealPlan): Response
    {
        $this->authorize('view', $client);

        // Load portal user for avatar
        $client->load('portalUser:id,avatar');
        $avatar = $client->portalUser?->avatar;
        if ($avatar) {
            $client->avatar_url = str_starts_with($avatar, 'http') || str_starts_with($avatar, '/storage/') 
                ? $avatar 
                : '/storage/' . $avatar;
        } else {
            $client->avatar_url = null;
        }

        return Inertia::render('Coach/MealPlans/Show', [
            'client' => $client,
            'mealPlan' => $mealPlan->load('dietPlans.items.food'),
            'totals' => $mealPlan->calculateTotals(),
        ]);
    }

    /**
     * Show the form for editing the specified meal plan.
     */
    public function edit(Request $request, Client $client, MealPlan $mealPlan): Response
    {
        $this->authorize('update', $client);

        $foods = Food::where('is_custom', false)
            ->orWhere('user_id', $request->user()->id)
            ->orderBy('category')
            ->orderBy('name')
            ->get();

        return Inertia::render('Coach/MealPlans/Edit', [
            'client' => $client,
            'mealPlan' => $mealPlan->load('dietPlans.items.food'),
            'foods' => $foods,
            'mealTypes' => Food::MEAL_TYPES,
        ]);
    }

    /**
     * Update the specified meal plan.
     */
    public function update(Request $request, Client $client, MealPlan $mealPlan): RedirectResponse
    {
        $this->authorize('update', $client);

        // Si solo se envían notas, actualizar solo las notas
        if ($request->has('notes') && !$request->has('diet_plans')) {
            $mealPlan->update([
                'notes' => $request->input('notes'),
            ]);
            
            return redirect()->back()->with('success', 'Notas actualizadas exitosamente.');
        }

        $validated = $request->validate([
            'name' => 'required|string|max:255',
            'description' => 'nullable|string|max:1000',
            'notes' => 'nullable|string',
            'is_active' => 'boolean',
            'diet_plans' => 'required|array|min:1',
            'diet_plans.*.id' => 'nullable|integer',
            'diet_plans.*.name' => 'required|string|max:255',
            'diet_plans.*.description' => 'nullable|string|max:1000',
            'diet_plans.*.days' => 'nullable|array',
            'diet_plans.*.use_percentages' => 'boolean',
            'diet_plans.*.protein_percent' => 'nullable|integer|min:0|max:100',
            'diet_plans.*.fat_percent' => 'nullable|integer|min:0|max:100',
            'diet_plans.*.carb_percent' => 'nullable|integer|min:0|max:100',
            'diet_plans.*.calorie_adjustment' => 'nullable|integer|min:-100|max:100',
            'diet_plans.*.meal_items' => 'required|array|min:1',
            'diet_plans.*.meal_items.*.food_id' => 'required|exists:foods,id',
            'diet_plans.*.meal_items.*.meal_type' => 'required|string',
            'diet_plans.*.meal_items.*.quantity' => 'required|numeric|min:0.1|max:2000',
            'diet_plans.*.meal_items.*.unit' => 'nullable|string|max:50',
        ]);

        // Deactivate other meal plans if this one should be active
        if ($request->boolean('is_active', true)) {
            $client->mealPlans()->where('id', '!=', $mealPlan->id)->update(['is_active' => false]);
        }

        $mealPlan->update([
            'name' => $validated['name'],
            'description' => $validated['description'] ?? null,
            'notes' => $validated['notes'] ?? null,
            'is_active' => $request->boolean('is_active', true),
        ]);

        // Get existing diet plan IDs
        $existingDietPlanIds = $mealPlan->dietPlans->pluck('id')->toArray();
        $updatedDietPlanIds = [];

        // Update or create diet plans
        foreach ($validated['diet_plans'] as $planIndex => $planData) {
            $dietPlanData = [
                'name' => $planData['name'],
                'description' => $planData['description'] ?? null,
                'days' => $planData['days'] ?? [],
                'use_percentages' => $planData['use_percentages'] ?? true,
                'protein_percent' => $planData['protein_percent'] ?? 30,
                'fat_percent' => $planData['fat_percent'] ?? 25,
                'carb_percent' => $planData['carb_percent'] ?? 45,
                'calorie_adjustment' => $planData['calorie_adjustment'] ?? 0,
                'is_active' => true,
                'order' => $planIndex,
            ];

            if (!empty($planData['id']) && in_array($planData['id'], $existingDietPlanIds)) {
                // Update existing diet plan
                $dietPlan = DietPlan::find($planData['id']);
                $dietPlan->update($dietPlanData);
                $updatedDietPlanIds[] = $planData['id'];
            } else {
                // Create new diet plan
                $dietPlan = $mealPlan->dietPlans()->create($dietPlanData);
                $updatedDietPlanIds[] = $dietPlan->id;
            }

            // Delete existing items and recreate
            $dietPlan->items()->delete();

            foreach ($planData['meal_items'] as $index => $itemData) {
                $food = Food::find($itemData['food_id']);
                $quantity = $itemData['quantity'];

                $dietPlan->items()->create([
                    'food_id' => $itemData['food_id'],
                    'meal_type' => $itemData['meal_type'],
                    'quantity' => $quantity,
                    'unit' => $itemData['unit'] ?? null,
                    'proteins' => round(($food->proteins ?? 0) * $quantity / 100, 2),
                    'carbs' => round(($food->carbs ?? 0) * $quantity / 100, 2),
                    'fats' => round(($food->fats ?? 0) * $quantity / 100, 2),
                    'calories' => round(($food->calories ?? 0) * $quantity / 100, 2),
                    'order' => $index,
                ]);
            }
        }

        // Delete diet plans that were removed
        $dietPlansToDelete = array_diff($existingDietPlanIds, $updatedDietPlanIds);
        if (!empty($dietPlansToDelete)) {
            DietPlan::whereIn('id', $dietPlansToDelete)->delete();
        }

        // Send notification to client if they have a user account
        if ($client->clientUser) {
            $client->clientUser->notify(new MealPlanUpdated($mealPlan));
        }

        return redirect()->route('coach.clients.meal-plans.show', [$client, $mealPlan])
            ->with('success', 'Dieta actualizada correctamente.');
    }

    /**
     * Remove the specified meal plan.
     */
    public function destroy(Request $request, Client $client, MealPlan $mealPlan): RedirectResponse
    {
        $this->authorize('update', $client);

        $mealPlanName = $mealPlan->name;
        $coachName = $request->user()->name;

        $mealPlan->delete();

        // Notify client if they have a user account
        if ($client->user) {
            $client->user->notify(new \App\Notifications\MealPlanDeleted($mealPlanName, $coachName));
        }

        return redirect()->route('coach.clients.meal-plans.index', $client)
            ->with('success', 'Dieta eliminada correctamente.');
    }

    /**
     * Toggle meal plan active status.
     */
    public function toggleActive(Request $request, Client $client, MealPlan $mealPlan): RedirectResponse
    {
        $this->authorize('update', $client);

        if (!$mealPlan->is_active) {
            $client->mealPlans()->where('id', '!=', $mealPlan->id)->update(['is_active' => false]);
        }

        $mealPlan->update(['is_active' => !$mealPlan->is_active]);

        return back()->with('success', $mealPlan->is_active ? 'Dieta activada.' : 'Dieta desactivada.');
    }

    /**
     * Duplicate a meal plan.
     */
    public function duplicate(Request $request, Client $client, MealPlan $mealPlan): RedirectResponse
    {
        $this->authorize('update', $client);

        $newPlan = $mealPlan->replicate();
        $newPlan->name = $mealPlan->name . ' (Copia)';
        $newPlan->is_active = false;
        $newPlan->save();

        // Duplicate diet plans
        foreach ($mealPlan->dietPlans as $dietPlan) {
            $newDietPlan = $dietPlan->replicate();
            $newDietPlan->meal_plan_id = $newPlan->id;
            $newDietPlan->save();

            // Duplicate meal items
            foreach ($dietPlan->items as $item) {
                $newItem = $item->replicate();
                $newItem->diet_plan_id = $newDietPlan->id;
                $newItem->save();
            }
        }

        return back()->with('success', 'Dieta duplicada correctamente.');
    }

    /**
     * Add a new empty diet plan to an existing meal plan.
     */
    public function addDietPlan(Request $request, Client $client, MealPlan $mealPlan): RedirectResponse
    {
        $this->authorize('update', $client);

        $existingCount = $mealPlan->dietPlans()->count();
        
        $dietPlan = $mealPlan->dietPlans()->create([
            'name' => 'Plan ' . ($existingCount + 1),
            'description' => null,
            'days' => [],
            'use_percentages' => true,
            'protein_percent' => 30,
            'fat_percent' => 25,
            'carb_percent' => 45,
            'calorie_adjustment' => $client->calorie_adjustment ?? 0,
            'is_active' => true,
            'order' => $existingCount,
        ]);

        // Redirect to edit with the new plan's index
        return redirect()->route('coach.clients.meal-plans.edit', [
            'client' => $client,
            'meal_plan' => $mealPlan,
            'plan' => $existingCount, // 0-based index of the new plan
        ])->with('success', 'Nuevo plan de dieta agregado. Ahora puedes agregar alimentos.');
    }

    /**
     * Delete a specific diet plan from a meal plan.
     */
    public function deleteDietPlan(Request $request, Client $client, MealPlan $mealPlan, DietPlan $dietPlan): RedirectResponse
    {
        $this->authorize('update', $client);

        // Ensure the diet plan belongs to this meal plan
        if ($dietPlan->meal_plan_id !== $mealPlan->id) {
            abort(404);
        }

        // Don't allow deleting the last diet plan
        if ($mealPlan->dietPlans()->count() <= 1) {
            return back()->with('error', 'No puedes eliminar el único plan de dieta.');
        }

        $dietPlan->delete();

        return back()->with('success', 'Plan de dieta eliminado correctamente.');
    }
}
