<?php

namespace App\Http\Controllers\Client;

use App\Http\Controllers\Controller;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Inertia\Inertia;
use Inertia\Response;

class DashboardController extends Controller
{
    public function index(Request $request): Response
    {
        $user = $request->user();
        $client = $user->clientProfile;

        // If no client profile, show a helpful message instead of 403
        if (!$client) {
            return Inertia::render('Client/Dashboard', [
                'client' => [
                    'name' => $user->name,
                    'workouts' => [],
                    'mealPlans' => [],
                ],
                'coach' => null,
                'stats' => [
                    'workouts' => 0,
                    'meal_plans' => 0,
                    'start_weight' => null,
                    'current_weight' => null,
                    'bmi' => null,
                    'tdee' => null,
                    'bmr' => null,
                    'streak' => 0,
                    'total_workouts_completed' => 0,
                    'total_meals_completed' => 0,
                ],
                'compliance_logs' => [],
                'progress_photos' => [],
                'weight_history' => [],
                'notifications' => [],
                'upcoming_workouts' => [],
                'no_profile' => true,
            ]);
        }

        // Get coach info
        $coach = $client->coach;

        // Calculate compliance streak
        $streak = $this->calculateStreak($client);

        // Get current weight from latest progress photo or client record
        $latestWeight = $client->progressPhotos()
            ->whereNotNull('weight')
            ->latest('date')
            ->value('weight');
        $currentWeight = $latestWeight ?? $client->weight;

        // Get weight history for chart from progress photos (last 30 entries)
        $weightHistory = $client->progressPhotos()
            ->whereNotNull('weight')
            ->orderBy('date', 'asc')
            ->take(30)
            ->get(['weight', 'date'])
            ->map(fn($photo) => [
                'weight' => $photo->weight,
                'date' => Carbon::parse($photo->date)->format('d M'),
            ]);

        // Get notifications for client
        $notifications = $user->notifications()
            ->take(10)
            ->get()
            ->map(fn($n) => [
                'id' => $n->id,
                'type' => class_basename($n->type),
                'data' => $n->data,
                'read_at' => $n->read_at,
                'created_at' => $n->created_at->diffForHumans(),
            ]);

        // Unread messages count
        $unreadMessages = \App\Models\Message::where('receiver_id', '=', $user->id)
            ->whereNull('read_at')
            ->count();

        // Weekly compliance data
        $weeklyCompliance = $this->getWeeklyCompliance($client);

        return Inertia::render('Client/Dashboard', [
            'client' => $client->load([
                'workouts' => fn($q) => $q->where('is_active', '=', true)->with(['exercises' => fn($e) => $e->take(20)]),
                'mealPlans' => fn($q) => $q->where('is_active', '=', true)->with(['dietPlans' => fn($dp) => $dp->with(['items' => fn($i) => $i->with('food:id,name,calories,proteins,carbs,fats')->take(30)])]),
            ]),
            'coach' => $coach ? [
                'id' => $coach->id,
                'name' => $coach->name,
                'email' => $coach->email,
                'avatar' => $coach->avatar
                    ? (str_starts_with($coach->avatar, 'http') || str_starts_with($coach->avatar, '/storage/')
                        ? $coach->avatar
                        : '/storage/' . $coach->avatar)
                    : null,
            ] : null,
            'stats' => [
                'workouts' => $client->workouts()->where('is_active', '=', true)->count(),
                'meal_plans' => $client->mealPlans()->where('is_active', '=', true)->count(),
                'start_weight' => $client->weight,
                'current_weight' => $currentWeight,
                'height' => $client->height,
                'age' => $client->age,
                'gender' => $client->gender,
                'activity_level' => $client->activity_level,
                'objective' => $client->objective,
                'bmi' => $client->bmi ? round($client->bmi, 2) : $client->calculateBmi(),
                'tdee' => $client->tdee ? round($client->tdee, 2) : $client->calculateTdee(),
                'bmr' => $client->bmr ? round($client->bmr, 2) : $client->calculateBmr(),
                'macros' => $client->calculateMacros(),
                'streak' => $streak,
                'total_workouts_completed' => $client->complianceLogs()->where('resource_type', '=', 'workout')->count(),
                'total_meals_completed' => $client->complianceLogs()->where('resource_type', '=', 'meal')->count(),
                'unread_messages' => $unreadMessages,
            ],
            'compliance_logs' => $client->complianceLogs()->latest()->take(10)->get(),
            'progress_photos' => $client->progressPhotos()->latest()->take(6)->get(),
            'weight_history' => $weightHistory,
            'weekly_compliance' => $weeklyCompliance,
            'notifications' => $notifications,
        ]);
    }

    /**
     * Calculate compliance streak (consecutive days with at least one completion)
     * Optimized to use a single query instead of N+1
     */
    private function calculateStreak($client): int
    {
        // Get compliance logs from the last 30 days grouped by date
        $logs = $client->complianceLogs()
            ->whereDate('completed_at', '>=', Carbon::today()->subDays(30))
            ->selectRaw('DATE(completed_at) as date')
            ->distinct()
            ->orderBy('date', 'desc')
            ->pluck('date')
            ->map(fn($date) => Carbon::parse($date)->format('Y-m-d'))
            ->toArray();

        if (empty($logs)) {
            return 0;
        }

        $streak = 0;
        $date = Carbon::today();

        // Count consecutive days
        while (in_array($date->format('Y-m-d'), $logs)) {
            $streak++;
            $date = $date->subDay();
        }

        return $streak;
    }

    /**
     * Get weekly compliance data for chart
     * Optimized to use a single query instead of N+1
     */
    private function getWeeklyCompliance($client): array
    {
        $dayNames = ['Dom', 'Lun', 'Mar', 'Mié', 'Jue', 'Vie', 'Sáb'];
        $startDate = Carbon::today()->subDays(6);
        $endDate = Carbon::today();

        // Single query to get all compliance logs for the week
        $logs = $client->complianceLogs()
            ->whereDate('completed_at', '>=', $startDate)
            ->whereDate('completed_at', '<=', $endDate)
            ->selectRaw('DATE(completed_at) as date, resource_type, COUNT(*) as count')
            ->groupBy('date', 'resource_type')
            ->get()
            ->groupBy('date');

        $days = [];
        for ($i = 6; $i >= 0; $i--) {
            $date = Carbon::today()->subDays($i);
            $dateKey = $date->format('Y-m-d');
            $dayLogs = $logs->get($dateKey, collect());

            $days[] = [
                'day' => $dayNames[$date->dayOfWeek],
                'date' => $date->format('d/m'),
                'workouts' => $dayLogs->where('resource_type', '=', 'workout')->sum('count'),
                'meals' => $dayLogs->where('resource_type', '=', 'meal')->sum('count'),
            ];
        }

        return $days;
    }

    public function updateMetrics(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'weight' => 'required|numeric|min:20|max:300',
        ]);

        $user = $request->user();
        $client = $user->clientProfile;

        if ($client) {
            $client->weight = $validated['weight'];
            $client->updateMetrics(); // Recalculate BMR/TDEE/BMI
        }

        return back()->with('success', 'Peso actualizado correctamente. TDEE y BMR recalculados.');
    }
}
