<?php
declare(strict_types=1);

namespace App\Modules\TrainingGroups\Services;

use App\Core\App;

class WaitingListService
{
    /**
     * When a spot opens in a group, check the waiting list for eligible players and offer the spot.
     */
    public static function processOpenSpot(int $groupId): ?int
    {
        $db = App::getInstance()->db();

        // Get the group details
        $group = $db->selectOne(
            "SELECT tg.*, a.discipline_id
             FROM training_groups tg
             INNER JOIN academies a ON a.id = tg.academy_id
             WHERE tg.id = ?",
            [$groupId]
        );

        if (!$group || (int) $group['is_full'] === 1) {
            return null;
        }

        // Find eligible waiting list entries
        $where = "wl.status = 'waiting' AND wl.discipline_id = ?";
        $params = [(int) $group['discipline_id']];

        if (!empty($group['level_id'])) {
            $where .= " AND (wl.level_id IS NULL OR wl.level_id = ?)";
            $params[] = (int) $group['level_id'];
        }

        $entries = $db->select(
            "SELECT wl.*, p.date_of_birth, p.gender
             FROM waiting_list wl
             LEFT JOIN players p ON p.id = wl.player_id
             WHERE {$where}
             ORDER BY wl.priority ASC, wl.created_at ASC
             LIMIT 10",
            $params
        );

        foreach ($entries as $entry) {
            // Check age eligibility
            if (!empty($entry['date_of_birth']) && ($group['age_from'] !== null || $group['age_to'] !== null)) {
                $dob = new \DateTime($entry['date_of_birth']);
                $now = new \DateTime();
                $age = (int) $now->diff($dob)->y;

                if ($group['age_from'] !== null && $age < (int) $group['age_from']) {
                    continue;
                }
                if ($group['age_to'] !== null && $age > (int) $group['age_to']) {
                    continue;
                }
            }

            // Check gender eligibility
            if (!empty($group['gender_restriction']) && !empty($entry['gender'])) {
                if ($group['gender_restriction'] !== $entry['gender']) {
                    continue;
                }
            }

            // Check day preference
            if ($entry['preferred_day_of_week'] !== null && $group['day_of_week'] !== null) {
                if ((int) $entry['preferred_day_of_week'] !== (int) $group['day_of_week']) {
                    continue;
                }
            }

            // Check time preference
            if (!empty($entry['preferred_time']) && !empty($group['start_time'])) {
                $startHour = (int) substr($group['start_time'], 0, 2);
                if ($entry['preferred_time'] === 'AM' && $startHour >= 12) {
                    continue;
                }
                if ($entry['preferred_time'] === 'PM' && $startHour < 12) {
                    continue;
                }
            }

            // This entry is eligible — offer the spot
            self::offerSpot((int) $entry['id'], $groupId);
            return (int) $entry['id'];
        }

        return null;
    }

    /**
     * Offer a spot in a specific group to a waiting list entry.
     */
    public static function offerSpot(int $waitingListId, int $groupId): void
    {
        $db = App::getInstance()->db();

        $expiresAt = date('Y-m-d H:i:s', strtotime('+48 hours'));

        $db->update('waiting_list', [
            'status'           => 'offered',
            'offered_group_id' => $groupId,
            'offered_at'       => date('Y-m-d H:i:s'),
            'offer_expires_at' => $expiresAt,
        ], 'id = ?', [$waitingListId]);
    }

    /**
     * Cancel a waiting list entry.
     */
    public static function cancel(int $waitingListId): void
    {
        $db = App::getInstance()->db();
        $db->update('waiting_list', [
            'status' => 'cancelled',
        ], 'id = ?', [$waitingListId]);
    }
}
