<?php

namespace App\Domain\HR\Services;

use App\Domain\HR\Models\Trainer;
use App\Domain\Training\Models\TrainingGroup;
use App\Domain\Training\Models\TrainingSchedule;
use Carbon\Carbon;

class TrainerWorkloadService
{
    public function getWorkload(int $userId): array
    {
        return $this->getWorkloadsForUsers([$userId])[$userId] ?? $this->emptyWorkload($userId);
    }

    public function getWorkloadsForUsers(array $userIds): array
    {
        if (empty($userIds)) {
            return [];
        }

        $schedules = TrainingSchedule::where('is_active', true)
            ->where(function ($q) use ($userIds) {
                $q->whereIn('trainer_id', $userIds)
                  ->orWhereIn('assistant_trainer_id', $userIds);
            })
            ->select(['id', 'trainer_id', 'assistant_trainer_id', 'training_group_id', 'start_time', 'end_time', 'day_of_week'])
            ->get();

        $headTrainerGroups = TrainingGroup::whereIn('head_trainer_id', $userIds)
            ->whereIn('status', ['active', 'forming', 'full'])
            ->with(['schedules' => fn ($q) => $q->where('is_active', true)->whereNull('trainer_id')])
            ->get();

        $trainerCapacities = Trainer::whereHas('employee', fn ($q) => $q->whereIn('user_id', $userIds))
            ->with('employee:id,user_id')
            ->get()
            ->keyBy(fn ($t) => $t->employee->user_id);

        $result = [];
        foreach ($userIds as $userId) {
            $weeklyMinutes = 0;
            $sessionsPerDay = [];
            $groupIds = collect();

            foreach ($schedules as $schedule) {
                $isMainTrainer = $schedule->trainer_id === $userId;
                $isAssistant = $schedule->assistant_trainer_id === $userId;

                if (!$isMainTrainer && !$isAssistant) {
                    continue;
                }

                $minutes = $this->minutesBetween($schedule->start_time, $schedule->end_time);
                $weeklyMinutes += $minutes;
                $sessionsPerDay[$schedule->day_of_week] = ($sessionsPerDay[$schedule->day_of_week] ?? 0) + 1;
                $groupIds->push($schedule->training_group_id);
            }

            foreach ($headTrainerGroups as $group) {
                if ($group->head_trainer_id !== $userId) {
                    continue;
                }
                foreach ($group->schedules as $schedule) {
                    $minutes = $this->minutesBetween($schedule->start_time, $schedule->end_time);
                    $weeklyMinutes += $minutes;
                    $sessionsPerDay[$schedule->day_of_week] = ($sessionsPerDay[$schedule->day_of_week] ?? 0) + 1;
                    $groupIds->push($schedule->training_group_id);
                }
            }

            $weeklyHours = round($weeklyMinutes / 60, 1);
            $maxDailySessions = !empty($sessionsPerDay) ? max($sessionsPerDay) : 0;
            $totalWeeklySessions = array_sum($sessionsPerDay);

            $trainer = $trainerCapacities[$userId] ?? null;
            $maxWeeklyHours = $trainer?->max_weekly_hours ?? 40;
            $maxDailySessionsCap = $trainer?->max_daily_sessions ?? 8;

            $loadPercent = $maxWeeklyHours > 0 ? min(100, round(($weeklyHours / $maxWeeklyHours) * 100)) : 0;

            $result[$userId] = [
                'user_id' => $userId,
                'weekly_hours' => $weeklyHours,
                'weekly_sessions' => $totalWeeklySessions,
                'max_weekly_hours' => (float) $maxWeeklyHours,
                'max_daily_sessions' => $maxDailySessionsCap,
                'peak_daily_sessions' => $maxDailySessions,
                'groups_count' => $groupIds->unique()->count(),
                'load_percent' => $loadPercent,
                'load_level' => $this->resolveLoadLevel($loadPercent),
            ];
        }

        return $result;
    }

    private function minutesBetween($start, $end): int
    {
        $s = Carbon::parse($start);
        $e = Carbon::parse($end);

        return max(0, $s->diffInMinutes($e));
    }

    private function resolveLoadLevel(int $percent): string
    {
        if ($percent >= 85) {
            return 'high';
        }
        if ($percent >= 60) {
            return 'medium';
        }

        return 'low';
    }

    private function emptyWorkload(int $userId): array
    {
        return [
            'user_id' => $userId,
            'weekly_hours' => 0,
            'weekly_sessions' => 0,
            'max_weekly_hours' => 40,
            'max_daily_sessions' => 8,
            'peak_daily_sessions' => 0,
            'groups_count' => 0,
            'load_percent' => 0,
            'load_level' => 'low',
        ];
    }
}
