<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

use App\Core\App;

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

        $facility = $db->selectOne(
            "SELECT * FROM sa_facilities WHERE id = ? AND is_active = 1 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.max_capacity,
                    c.full_name_ar as coach_name, g.name_ar as group_name, g.code as group_code
             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')
             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] = [];

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

                $status = 'free';
                $label = '';
                $bookingId = null;
                $bookingType = null;
                $spotsUsed = 0;

                if (!empty($slotBookings)) {
                    foreach ($slotBookings as $sb) {
                        $spotsUsed += (int) $sb['spots_reserved'];
                    }

                    $first = $slotBookings[0];
                    $bookingType = $first['booking_type'];
                    $bookingId = (int) $first['id'];

                    if ($bookingType === 'training') {
                        $status = 'training';
                        $label = $first['group_name'] ?? 'تدريب';
                    } elseif ($bookingType === 'blocked') {
                        $status = 'blocked';
                        $label = 'محجوب';
                    } elseif ($bookingType === 'maintenance') {
                        $status = 'maintenance';
                        $label = 'صيانة';
                    } else {
                        $status = 'hourly';
                        $label = $first['booker_name'] ?? 'حجز';
                    }
                }

                $grid[$unitId][] = [
                    'start'        => $slot['start'],
                    'end'          => $slot['end'],
                    'status'       => $status,
                    'label'        => $label,
                    'booking_id'   => $bookingId,
                    'booking_type' => $bookingType,
                    'spots_used'   => $spotsUsed,
                    'max_capacity' => (int) $unit['max_capacity'],
                    'bookings'     => count($slotBookings),
                ];
            }
        }

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

    public static function bulkAssign(int $facilityId, string $date, string $action, array $cells, ?int $groupId, ?string $notes): array
    {
        $db = App::getInstance()->db();
        $ts = date('Y-m-d H:i:s');
        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);

        $validActions = ['training', 'blocked', 'maintenance'];
        if (!in_array($action, $validActions, true)) {
            return ['success' => false, 'error' => 'إجراء غير صالح'];
        }

        if ($action === 'training' && !$groupId) {
            return ['success' => false, 'error' => 'المجموعة مطلوبة لتعيين تدريب'];
        }

        $group = null;
        $coachId = null;
        if ($groupId) {
            $group = $db->selectOne("SELECT * FROM sa_groups WHERE id = ? AND status = 'active'", [$groupId]);
            if (!$group) {
                return ['success' => false, 'error' => 'المجموعة غير موجودة أو غير نشطة'];
            }
            $coachId = $group['coach_id'] ? (int) $group['coach_id'] : null;
        }

        $bookingCount = (int) ($db->selectOne("SELECT COUNT(*) as cnt FROM sa_bookings", [])['cnt'] ?? 0);
        $assigned = 0;
        $skipped = 0;

        foreach ($cells as $cell) {
            $unitId = (int) ($cell['unit_id'] ?? 0);
            $startTime = $cell['start_time'] ?? '';
            $endTime = $cell['end_time'] ?? '';

            if (!$unitId || !$startTime || !$endTime) {
                $skipped++;
                continue;
            }

            $conflict = $db->selectOne(
                "SELECT id FROM sa_bookings
                 WHERE facility_unit_id = ? AND booking_date = ?
                 AND start_time < ? AND end_time > ?
                 AND status NOT IN ('cancelled')
                 AND booking_type IN ('training', 'blocked', 'maintenance')",
                [$unitId, $date, $endTime, $startTime]
            );

            if ($conflict) {
                $skipped++;
                continue;
            }

            $bookingCount++;
            $bookingNumber = 'BK-' . str_pad((string) $bookingCount, 6, '0', STR_PAD_LEFT);

            $data = [
                'booking_number'   => $bookingNumber,
                'facility_unit_id' => $unitId,
                'booking_type'     => $action,
                'booking_date'     => $date,
                'start_time'       => $startTime,
                'end_time'         => $endTime,
                'group_id'         => $groupId,
                'coach_id'         => $coachId,
                'booker_type'      => $action === 'training' ? 'academy' : 'member',
                'booker_name'      => $action === 'training' ? ($group['name_ar'] ?? 'تدريب') : 'إدارة',
                'participant_count'=> $action === 'training' ? (int) ($group['current_count'] ?? 0) : 0,
                'spots_reserved'   => $action === 'training' ? (int) ($group['max_capacity'] ?? 8) : 8,
                'status'           => 'confirmed',
                'payment_status'   => 'paid',
                'notes'            => $notes,
                'branch_id'        => 1,
                'created_at'       => $ts,
                'updated_at'       => $ts,
                'created_by'       => $employeeId,
            ];

            $db->insert('sa_bookings', $data);
            $assigned++;
        }

        return ['success' => true, 'assigned' => $assigned, 'skipped' => $skipped];
    }

    public static function bulkClear(int $facilityId, string $date, array $cells): array
    {
        $db = App::getInstance()->db();
        $ts = date('Y-m-d H:i:s');
        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);
        $cleared = 0;

        foreach ($cells as $cell) {
            $unitId = (int) ($cell['unit_id'] ?? 0);
            $startTime = $cell['start_time'] ?? '';
            $endTime = $cell['end_time'] ?? '';

            if (!$unitId || !$startTime || !$endTime) continue;

            $existing = $db->select(
                "SELECT id FROM sa_bookings
                 WHERE facility_unit_id = ? AND booking_date = ?
                 AND start_time < ? AND end_time > ?
                 AND status NOT IN ('cancelled')",
                [$unitId, $date, $endTime, $startTime]
            );

            foreach ($existing as $row) {
                $db->update('sa_bookings', [
                    'status'             => 'cancelled',
                    'cancellation_reason'=> 'مسح من شبكة الحمام',
                    'cancelled_by'       => $employeeId,
                    'cancelled_at'       => $ts,
                    'updated_at'         => $ts,
                ], 'id = ?', [(int) $row['id']]);
                $cleared++;
            }
        }

        return ['success' => true, 'cleared' => $cleared];
    }

    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;
    }
}
