<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

use App\Core\App;

final class BookingService
{
    public static function createHourlyBooking(array $data): array
    {
        $db = App::getInstance()->db();

        $unitId = (int) ($data['facility_unit_id'] ?? 0);
        $date = $data['booking_date'] ?? '';
        $startTime = $data['start_time'] ?? '';
        $endTime = $data['end_time'] ?? '';
        $participantCount = (int) ($data['participant_count'] ?? 1);
        $spotsReserved = (int) ($data['spots_reserved'] ?? $participantCount);
        $bookerType = $data['booker_type'] ?? 'guest';
        $bookerId = isset($data['booker_id']) ? (int) $data['booker_id'] : null;
        $bookerName = $data['booker_name'] ?? '';
        $isMember = ($bookerType === 'member');

        $availability = SlotAvailabilityService::check($unitId, $date, $startTime, $endTime, $spotsReserved);
        if (!$availability['available']) {
            return ['success' => false, 'error' => $availability['reason']];
        }

        $pricing = PricingCalculatorService::calculate($unitId, $date, $startTime, $endTime, $participantCount, $isMember);
        $totalAmount = $pricing ? $pricing['total_amount'] : 0.00;

        $bookingNumber = self::generateNumber();
        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);

        $bookingData = [
            'booking_number'   => $bookingNumber,
            'facility_unit_id' => $unitId,
            'booking_type'     => 'hourly',
            'booking_date'     => $date,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'booker_type'      => $bookerType,
            'booker_id'        => $bookerId,
            'booker_name'      => $bookerName,
            'participant_count' => $participantCount,
            'spots_reserved'   => $spotsReserved,
            'total_amount'     => $totalAmount,
            'payment_status'   => 'unpaid',
            'status'           => 'confirmed',
            'notes'            => $data['notes'] ?? null,
            'branch_id'        => $data['branch_id'] ?? null,
            'created_by'       => $employeeId,
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s'),
        ];

        $db->insert('sa_bookings', $bookingData);
        $bookingId = (int) $db->lastInsertId();

        if (!empty($data['participants']) && is_array($data['participants'])) {
            foreach ($data['participants'] as $p) {
                $db->insert('sa_booking_participants', [
                    'booking_id'       => $bookingId,
                    'player_id'        => isset($p['player_id']) ? (int) $p['player_id'] : null,
                    'participant_name' => $p['name'] ?? null,
                    'is_member'        => (int) ($p['is_member'] ?? 0),
                    'price_charged'    => $pricing ? $pricing['price_per_person'] * $pricing['duration_hours'] : 0,
                    'created_at'       => date('Y-m-d H:i:s'),
                ]);
            }
        }

        return [
            'success'        => true,
            'booking_id'     => $bookingId,
            'booking_number' => $bookingNumber,
            'total_amount'   => $totalAmount,
            'pricing'        => $pricing,
        ];
    }

    public static function createTrainingBooking(
        int $groupId,
        int $facilityUnitId,
        string $date,
        string $startTime,
        string $endTime,
        ?int $coachId = null
    ): array {
        $db = App::getInstance()->db();

        $group = $db->selectOne("SELECT * FROM sa_groups WHERE id = ?", [$groupId]);
        if (!$group) {
            return ['success' => false, 'error' => 'المجموعة غير موجودة'];
        }

        $unit = $db->selectOne("SELECT * FROM sa_facility_units WHERE id = ?", [$facilityUnitId]);
        if (!$unit) {
            return ['success' => false, 'error' => 'الوحدة غير موجودة'];
        }

        $spotsNeeded = $unit['booking_mode'] === 'shared' ? (int) $group['current_count'] : 1;

        $availability = SlotAvailabilityService::check($facilityUnitId, $date, $startTime, $endTime, $spotsNeeded);
        if (!$availability['available']) {
            return ['success' => false, 'error' => $availability['reason']];
        }

        if ($coachId) {
            $conflicts = ConflictDetectionService::check($facilityUnitId, $date, $startTime, $endTime, $coachId);
            $blocking = array_filter($conflicts, fn($c) => $c['severity'] === 'blocking');
            if (!empty($blocking)) {
                return ['success' => false, 'error' => $blocking[0]['message']];
            }
        }

        $bookingNumber = self::generateNumber();
        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);

        $db->insert('sa_bookings', [
            'booking_number'   => $bookingNumber,
            'facility_unit_id' => $facilityUnitId,
            'booking_type'     => 'training',
            'booking_date'     => $date,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'group_id'         => $groupId,
            'coach_id'         => $coachId ?? (int) $group['coach_id'],
            'participant_count' => (int) $group['current_count'],
            'spots_reserved'   => $spotsNeeded,
            'total_amount'     => 0.00,
            'payment_status'   => 'unpaid',
            'status'           => 'confirmed',
            'is_recurring'     => 1,
            'branch_id'        => null,
            'created_by'       => $employeeId,
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s'),
        ]);

        return [
            'success'        => true,
            'booking_id'     => (int) $db->lastInsertId(),
            'booking_number' => $bookingNumber,
        ];
    }

    public static function cancel(int $bookingId, string $reason = ''): array
    {
        $db = App::getInstance()->db();
        $booking = $db->selectOne("SELECT * FROM sa_bookings WHERE id = ?", [$bookingId]);

        if (!$booking) {
            return ['success' => false, 'error' => 'الحجز غير موجود'];
        }

        if (in_array($booking['status'], ['cancelled', 'no_show'])) {
            return ['success' => false, 'error' => 'الحجز ملغي بالفعل'];
        }

        $employeeId = (int) (App::getInstance()->session()->get('employee_id') ?? 0);

        $db->update('sa_bookings', [
            'status'              => 'cancelled',
            'cancellation_reason' => $reason,
            'cancelled_by'        => $employeeId,
            'cancelled_at'        => date('Y-m-d H:i:s'),
            'updated_at'          => date('Y-m-d H:i:s'),
        ], 'id = ?', [$bookingId]);

        return ['success' => true];
    }

    private static function generateNumber(): string
    {
        $db = App::getInstance()->db();
        $datePrefix = 'BK-' . date('Ymd') . '-';

        for ($attempt = 0; $attempt < 10; $attempt++) {
            $number = $datePrefix . str_pad((string) random_int(1, 9999), 4, '0', STR_PAD_LEFT);
            $exists = $db->selectOne("SELECT id FROM sa_bookings WHERE booking_number = ?", [$number]);
            if (!$exists) {
                return $number;
            }
        }

        return $datePrefix . str_pad((string) random_int(10000, 99999), 5, '0', STR_PAD_LEFT);
    }
}
