<?php
declare(strict_types=1);

namespace App\Modules\Coaches\Services;

use App\Core\App;

final class CoachSchedulingService
{
    public static function isAvailable(int $coachId, int $dayOfWeek, string $startTime, string $endTime, ?string $date = null): bool
    {
        $db = App::getInstance()->db();

        $availability = $db->selectOne(
            "SELECT id FROM coach_availability
             WHERE coach_id = ? AND day_of_week = ? AND is_available = 1
             AND start_time <= ? AND end_time >= ?
             AND (effective_from IS NULL OR effective_from <= COALESCE(?, CURDATE()))
             AND (effective_to IS NULL OR effective_to >= COALESCE(?, CURDATE()))",
            [$coachId, $dayOfWeek, $startTime, $endTime, $date, $date]
        );

        if (!$availability) {
            return false;
        }

        $conflicts = self::getConflicts($coachId, $dayOfWeek, $startTime, $endTime);
        return empty($conflicts);
    }

    public static function findAvailableCoaches(int $dayOfWeek, string $startTime, string $endTime, ?int $disciplineId = null): array
    {
        $db = App::getInstance()->db();

        $sql = "SELECT DISTINCT c.id, c.full_name_ar, c.code, c.phone, c.max_players_default
                FROM coaches c
                INNER JOIN coach_availability ca ON ca.coach_id = c.id
                WHERE c.is_active = 1 AND c.is_archived = 0
                AND ca.day_of_week = ? AND ca.is_available = 1
                AND ca.start_time <= ? AND ca.end_time >= ?
                AND (ca.effective_from IS NULL OR ca.effective_from <= CURDATE())
                AND (ca.effective_to IS NULL OR ca.effective_to >= CURDATE())";
        $params = [$dayOfWeek, $startTime, $endTime];

        if ($disciplineId !== null) {
            $sql .= " AND EXISTS (
                SELECT 1 FROM coach_disciplines cd WHERE cd.coach_id = c.id AND cd.discipline_id = ?
            )";
            $params[] = $disciplineId;
        }

        $sql .= " ORDER BY c.full_name_ar ASC";

        $coaches = $db->select($sql, $params);

        return array_filter($coaches, function ($coach) use ($dayOfWeek, $startTime, $endTime) {
            $conflicts = self::getConflicts((int) $coach['id'], $dayOfWeek, $startTime, $endTime);
            return empty($conflicts);
        });
    }

    public static function getConflicts(int $coachId, int $dayOfWeek, string $startTime, string $endTime, ?int $excludeScheduleId = null): array
    {
        $db = App::getInstance()->db();

        $sql = "SELECT asched.id, asched.start_time, asched.end_time, a.name_ar AS academy_name
                FROM academy_schedules asched
                LEFT JOIN academies a ON a.id = asched.academy_id
                WHERE asched.coach_id = ? AND asched.day_of_week = ? AND asched.is_active = 1
                AND asched.start_time < ? AND asched.end_time > ?";
        $params = [$coachId, $dayOfWeek, $endTime, $startTime];

        if ($excludeScheduleId !== null) {
            $sql .= " AND asched.id != ?";
            $params[] = $excludeScheduleId;
        }

        return $db->select($sql, $params);
    }

    public static function getUtilization(int $coachId, string $monthStart, string $monthEnd): array
    {
        $db = App::getInstance()->db();

        $schedules = $db->selectOne(
            "SELECT COUNT(*) AS total_schedules,
                    SUM(TIMESTAMPDIFF(MINUTE, start_time, end_time)) AS total_minutes
             FROM academy_schedules
             WHERE coach_id = ? AND is_active = 1",
            [$coachId]
        );

        $assignments = $db->selectOne(
            "SELECT COUNT(*) AS total_assignments
             FROM coach_academy_assignments
             WHERE coach_id = ? AND is_active = 1",
            [$coachId]
        );

        return [
            'total_schedules'   => (int) ($schedules['total_schedules'] ?? 0),
            'total_minutes'     => (int) ($schedules['total_minutes'] ?? 0),
            'total_hours'       => round(((int) ($schedules['total_minutes'] ?? 0)) / 60, 1),
            'total_assignments' => (int) ($assignments['total_assignments'] ?? 0),
        ];
    }
}
