<?php
declare(strict_types=1);

namespace App\Modules\Facilities\Services;

use App\Core\App;
use App\Core\EventBus;

class AccessControlService
{
    public static function checkAccess(int $facilityId, string $date, string $startTime, ?int $memberId = null, string $bookerType = 'guest'): array
    {
        $db = App::getInstance()->db();
        $dayOfWeek = (int) date('w', strtotime($date));

        $slot = $db->selectOne(
            "SELECT * FROM facility_time_slots
             WHERE facility_id = ? AND day_of_week = ? AND start_time <= ? AND end_time > ? AND is_active = 1
             ORDER BY start_time ASC LIMIT 1",
            [$facilityId, $dayOfWeek, $startTime, $startTime]
        );

        if (!$slot) {
            return ['allowed' => false, 'reason' => 'لا يوجد فترة متاحة في هذا الوقت', 'price' => 0];
        }

        $accessType = $slot['access_type'] ?? 'all';
        $isMember = self::isMember($memberId);

        if ($accessType === 'members_only' && !$isMember) {
            return ['allowed' => false, 'reason' => 'هذه الفترة مخصصة للأعضاء فقط', 'price' => 0];
        }

        if ($accessType === 'vip' && !self::isVipMember($memberId)) {
            return ['allowed' => false, 'reason' => 'هذه الفترة مخصصة لأعضاء VIP فقط', 'price' => 0];
        }

        $price = $isMember
            ? (float) ($slot['member_price'] ?? 0)
            : (float) ($slot['guest_price'] ?? $slot['member_price'] ?? 0);

        if ($price === 0.0) {
            $facility = $db->selectOne("SELECT * FROM facilities WHERE id = ?", [$facilityId]);
            if ($facility) {
                $hour = (int) date('H', strtotime($startTime));
                $timeTier = $hour < 16 ? 'AM' : 'PM';
                $price = $isMember
                    ? (float) ($timeTier === 'AM' ? ($facility['member_rate_am'] ?? $facility['hourly_rate'] ?? 0) : ($facility['member_rate_pm'] ?? $facility['hourly_rate'] ?? 0))
                    : (float) ($timeTier === 'AM' ? ($facility['guest_rate_am'] ?? $facility['hourly_rate'] ?? 0) : ($facility['guest_rate_pm'] ?? $facility['hourly_rate'] ?? 0));
            }
        }

        return [
            'allowed'     => true,
            'reason'      => '',
            'price'       => $price,
            'access_type' => $accessType,
            'slot_id'     => (int) $slot['id'],
            'is_member'   => $isMember,
        ];
    }

    public static function isMember(?int $memberId): bool
    {
        if (!$memberId) return false;
        $db = App::getInstance()->db();
        $member = $db->selectOne(
            "SELECT id, membership_status FROM members WHERE id = ? AND membership_status = 'active'",
            [$memberId]
        );
        return $member !== null && $member !== false;
    }

    public static function isVipMember(?int $memberId): bool
    {
        if (!$memberId) return false;
        $db = App::getInstance()->db();
        $member = $db->selectOne(
            "SELECT id FROM members WHERE id = ? AND membership_status = 'active' AND membership_type IN ('vip', 'premium', 'gold')",
            [$memberId]
        );
        return $member !== null && $member !== false;
    }

    public static function recordFacilityEntry(int $facilityId, array $data): int
    {
        $db = App::getInstance()->db();

        $accessCheck = self::checkAccess(
            $facilityId,
            $data['date'] ?? date('Y-m-d'),
            $data['start_time'] ?? date('H:i:s'),
            !empty($data['member_id']) ? (int) $data['member_id'] : null,
            $data['booker_type'] ?? 'guest'
        );

        if (!$accessCheck['allowed']) {
            throw new \RuntimeException($accessCheck['reason'], 403);
        }

        $db->insert('pool_bookings', [
            'facility_id'      => $facilityId,
            'member_id'        => !empty($data['member_id']) ? (int) $data['member_id'] : null,
            'guest_name'       => $data['guest_name'] ?? null,
            'guest_phone'      => $data['guest_phone'] ?? null,
            'booking_date'     => $data['date'] ?? date('Y-m-d'),
            'start_time'       => $data['start_time'] ?? date('H:i:s'),
            'end_time'         => $data['end_time'] ?? null,
            'booker_type'      => $data['booker_type'] ?? 'guest',
            'amount'           => $accessCheck['price'],
            'status'           => 'active',
            'created_at'       => date('Y-m-d H:i:s'),
            'updated_at'       => date('Y-m-d H:i:s'),
        ]);

        $entryId = (int) $db->selectOne("SELECT LAST_INSERT_ID() AS id")['id'];

        EventBus::dispatch('facility.entry_recorded', [
            'entry_id'    => $entryId,
            'facility_id' => $facilityId,
            'member_id'   => !empty($data['member_id']) ? (int) $data['member_id'] : null,
            'amount'      => $accessCheck['price'],
            'booker_type' => $data['booker_type'] ?? 'guest',
        ]);

        return $entryId;
    }

    public static function getFacilityAccessSchedule(int $facilityId): array
    {
        $db = App::getInstance()->db();
        return $db->select(
            "SELECT * FROM facility_time_slots WHERE facility_id = ? AND is_active = 1 ORDER BY day_of_week ASC, start_time ASC",
            [$facilityId]
        );
    }

    public static function updateSlotAccess(int $slotId, string $accessType, ?float $memberPrice = null, ?float $guestPrice = null): void
    {
        $db = App::getInstance()->db();
        $updateData = [
            'access_type' => $accessType,
            'updated_at'  => date('Y-m-d H:i:s'),
        ];
        if ($memberPrice !== null) $updateData['member_price'] = $memberPrice;
        if ($guestPrice !== null) $updateData['guest_price'] = $guestPrice;

        $db->update('facility_time_slots', $updateData, '`id` = ?', [$slotId]);
    }
}
