<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

use App\Core\App;

final class MirrorStateService
{
    public static function getFacilityState(int $facilityId, string $date): array
    {
        $db = App::getInstance()->db();

        $facility = $db->selectOne(
            "SELECT * FROM sa_facilities WHERE id = ? AND is_archived = 0",
            [$facilityId]
        );

        if (!$facility) {
            return ['error' => 'المرفق غير موجود'];
        }

        $units = $db->select(
            "SELECT * FROM sa_facility_units WHERE facility_id = ? AND is_active = 1 ORDER BY sort_order",
            [$facilityId]
        );

        $bookings = $db->select(
            "SELECT b.*, fu.name_ar as unit_name, fu.booking_mode, fu.max_capacity,
                    c.full_name_ar as coach_name, g.name_ar as group_name
             FROM sa_bookings b
             JOIN sa_facility_units fu ON fu.id = b.facility_unit_id
             LEFT JOIN sa_coaches c ON c.id = b.coach_id
             LEFT JOIN sa_groups g ON g.id = b.group_id
             WHERE fu.facility_id = ? AND b.booking_date = ?
             AND b.status NOT IN ('cancelled', 'no_show')
             ORDER BY fu.sort_order, b.start_time",
            [$facilityId, $date]
        );

        $hours = json_decode($facility['operating_hours_json'], true) ?: ['start' => '06:00', 'end' => '22:00', 'slot_minutes' => 60];
        $slots = self::buildTimeSlots($hours['start'], $hours['end'], (int) $hours['slot_minutes']);

        $grid = [];
        foreach ($units as $unit) {
            $unitId = (int) $unit['id'];
            $unitBookings = array_filter($bookings, fn($b) => (int) $b['facility_unit_id'] === $unitId);

            $grid[$unitId] = [
                'unit'  => $unit,
                'slots' => [],
            ];

            foreach ($slots as $slot) {
                $slotBookings = array_filter($unitBookings, function ($b) use ($slot) {
                    return $b['start_time'] < $slot['end'] && $b['end_time'] > $slot['start'];
                });

                $occupied = 0;
                foreach ($slotBookings as $sb) {
                    $occupied += (int) $sb['spots_reserved'];
                }

                $cellStatus = 'free';
                if ($unit['booking_mode'] === 'shared') {
                    if ($occupied >= (int) $unit['max_capacity']) {
                        $cellStatus = 'full';
                    } elseif ($occupied > 0) {
                        $cellStatus = 'partial';
                    }
                } else {
                    if (!empty($slotBookings)) {
                        $first = reset($slotBookings);
                        $cellStatus = $first['booking_type'] === 'training' ? 'training' : 'booked';
                        if ($first['booking_type'] === 'maintenance' || $first['booking_type'] === 'blocked') {
                            $cellStatus = 'blocked';
                        }
                    }
                }

                $grid[$unitId]['slots'][] = [
                    'time_start' => $slot['start'],
                    'time_end'   => $slot['end'],
                    'status'     => $cellStatus,
                    'occupied'   => $occupied,
                    'max'        => (int) $unit['max_capacity'],
                    'bookings'   => array_values($slotBookings),
                ];
            }
        }

        return [
            'facility' => $facility,
            'units'    => $units,
            'grid'     => $grid,
            'slots'    => $slots,
            'date'     => $date,
        ];
    }

    private static function buildTimeSlots(string $start, string $end, int $slotMinutes): array
    {
        $slots = [];
        $current = strtotime($start);
        $endTs = strtotime($end);

        while ($current < $endTs) {
            $next = $current + ($slotMinutes * 60);
            $slots[] = [
                'start' => date('H:i', $current),
                'end'   => date('H:i', $next),
            ];
            $current = $next;
        }

        return $slots;
    }
}
