<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Services;

use App\Core\App;
use App\Modules\Cashier\Services\PaymentRequestService;

final class PoolReservationService
{
    private const LANE_CAPACITIES = [
        '50m' => 12,
        '25m' => 8,
        'mix' => 24,
    ];

    private const RESERVATION_TYPE_MAP = [
        'lane_50m' => '50m',
        'lane_25m' => '25m',
        'lane_mix' => 'mix',
    ];

    public static function getPricingOptions(): array
    {
        return [
            'lane_rentals'  => AcademyPricingService::getLaneRentalPricing(),
            'session_cards' => AcademyPricingService::getSessionCardPricing(),
        ];
    }

    public static function checkCapacity(string $reservationType, int $participantCount): array
    {
        $laneType = self::RESERVATION_TYPE_MAP[$reservationType] ?? null;

        if (!$laneType || $reservationType === 'cards') {
            return ['fits' => true, 'overflow' => 0, 'lane_capacity' => 0, 'suggestions' => []];
        }

        $laneCapacity = self::LANE_CAPACITIES[$laneType] ?? 12;
        $overflow = max(0, $participantCount - $laneCapacity);

        $suggestions = [];
        if ($overflow > 0) {
            $suggestions[] = [
                'type'     => 'additional_lane',
                'label_ar' => 'حجز حارة إضافية',
            ];
            $suggestions[] = [
                'type'        => 'overflow_cards',
                'label_ar'    => 'إضافة ' . $overflow . ' كروت للمشاركين الزائدين',
                'cards_needed' => $overflow,
            ];
        }

        return [
            'fits'          => $overflow === 0,
            'lane_capacity' => $laneCapacity,
            'overflow'      => $overflow,
            'suggestions'   => $suggestions,
        ];
    }

    public static function create(array $data): array
    {
        $db = App::getInstance()->db();
        $employee = App::getInstance()->currentEmployee();

        $bookerName      = trim((string) ($data['booker_name'] ?? ''));
        $bookerPhone     = trim((string) ($data['booker_phone'] ?? ''));
        $bookerType      = (string) ($data['booker_type'] ?? 'freelance_coach');
        $participantCount = max(1, (int) ($data['participant_count'] ?? 1));
        $reservationType = (string) ($data['reservation_type'] ?? '');
        $pricingId       = (int) ($data['pricing_id'] ?? 0);
        $sessionsTotal   = (int) ($data['sessions_total'] ?? 0);
        $unitPrice       = (float) ($data['unit_price'] ?? 0);
        $notes           = trim((string) ($data['notes'] ?? ''));

        $overflowType       = $data['overflow_type'] ?? null;
        $overflowCardsCount = (int) ($data['overflow_cards_count'] ?? 0);
        $overflowAmount     = (float) ($data['overflow_amount'] ?? 0);
        $hasOverflow        = ($overflowType !== null && ($overflowCardsCount > 0 || $overflowType === 'additional_lane'));

        if ($bookerName === '') {
            return ['success' => false, 'error' => 'اسم الحاجز مطلوب'];
        }
        if (!in_array($reservationType, ['lane_50m', 'lane_25m', 'lane_mix', 'cards'], true)) {
            return ['success' => false, 'error' => 'نوع الحجز غير صالح'];
        }
        if ($sessionsTotal < 1) {
            return ['success' => false, 'error' => 'عدد الحصص غير صالح'];
        }
        if ($unitPrice <= 0) {
            return ['success' => false, 'error' => 'السعر غير صالح'];
        }

        $totalAmount = $unitPrice + $overflowAmount;

        $programCode = str_starts_with($reservationType, 'lane_') ? 'SWIM-LANE-RENTAL' : 'SWIM-CARDS';
        $program = $db->selectOne(
            "SELECT id FROM sa_programs WHERE code = ? AND is_active = 1 LIMIT 1",
            [$programCode]
        );
        if (!$program) {
            return ['success' => false, 'error' => 'برنامج الإيجار غير موجود — يرجى تشغيل المايقريشن'];
        }
        $programId = (int) $program['id'];

        $typeLabels = [
            'lane_50m' => 'إيجار حارة 50م',
            'lane_25m' => 'إيجار حارة 25م',
            'lane_mix' => 'إيجار حارة ميكس',
            'cards'    => 'كروت حصص',
        ];
        $typeLabel = $typeLabels[$reservationType] ?? $reservationType;
        $groupName = $bookerName . ' — ' . $typeLabel . ' (' . $sessionsTotal . ' حصة)';
        $groupCode = 'GRP-PR-' . strtoupper(substr(md5((string) microtime(true)), 0, 6));

        $db->beginTransaction();
        try {
            $groupId = $db->insert('sa_groups', [
                'code'          => $groupCode,
                'name_ar'       => $groupName,
                'program_id'    => $programId,
                'coach_id'      => null,
                'max_capacity'  => $participantCount,
                'current_count' => $participantCount,
                'is_full'       => 0,
                'status'        => 'active',
                'source_type'   => 'pool_reservation',
                'is_archived'   => 0,
                'created_at'    => date('Y-m-d H:i:s'),
                'updated_at'    => date('Y-m-d H:i:s'),
                'created_by'    => $employee ? (int) $employee->id : null,
            ]);

            $reservationNumber = self::generateNumber();
            $startDate = date('Y-m-d');
            $expiryDate = date('Y-m-d', strtotime('+2 months'));

            $reservationId = $db->insert('sa_pool_reservations', [
                'reservation_number' => $reservationNumber,
                'group_id'           => $groupId,
                'booker_name'        => $bookerName,
                'booker_phone'       => $bookerPhone ?: null,
                'booker_type'        => $bookerType,
                'participant_count'  => $participantCount,
                'reservation_type'   => $reservationType,
                'pricing_id'         => $pricingId > 0 ? $pricingId : null,
                'sessions_total'     => $sessionsTotal,
                'sessions_used'      => 0,
                'unit_price'         => $unitPrice,
                'total_amount'       => $totalAmount,
                'payment_status'     => 'pending',
                'status'             => 'active',
                'start_date'         => $startDate,
                'expiry_date'        => $expiryDate,
                'has_overflow'       => $hasOverflow ? 1 : 0,
                'overflow_type'      => $hasOverflow ? $overflowType : null,
                'overflow_cards_count' => $overflowCardsCount,
                'overflow_amount'    => $overflowAmount,
                'notes'              => $notes ?: null,
                'created_by'         => $employee ? (int) $employee->id : null,
                'created_at'         => date('Y-m-d H:i:s'),
                'updated_at'         => date('Y-m-d H:i:s'),
            ]);

            $db->update('sa_groups', [
                'pool_reservation_id' => $reservationId,
                'updated_at'          => date('Y-m-d H:i:s'),
            ], 'id = ?', [$groupId]);

            $db->commit();
        } catch (\Throwable $e) {
            $db->rollBack();
            return ['success' => false, 'error' => 'فشل إنشاء الحجز: ' . $e->getMessage()];
        }

        if ($totalAmount > 0) {
            PaymentRequestService::createRequest([
                'member_id'           => 0,
                'payment_type'        => 'pool_reservation',
                'amount'              => (string) $totalAmount,
                'description_ar'      => 'حجز سباحة — ' . $bookerName . ' — ' . $typeLabel . ' (' . $sessionsTotal . ' حصة)',
                'related_entity_type' => 'sa_pool_reservations',
                'related_entity_id'   => $reservationId,
            ]);
        }

        return [
            'success'            => true,
            'reservation_id'     => $reservationId,
            'reservation_number' => $reservationNumber,
            'group_id'           => $groupId,
            'total_amount'       => $totalAmount,
        ];
    }

    public static function recordSessionUsage(int $reservationId): array
    {
        $db = App::getInstance()->db();

        $reservation = $db->selectOne(
            "SELECT id, sessions_total, sessions_used, status FROM sa_pool_reservations WHERE id = ?",
            [$reservationId]
        );
        if (!$reservation) {
            return ['success' => false, 'error' => 'الحجز غير موجود'];
        }
        if ($reservation['status'] !== 'active') {
            return ['success' => false, 'error' => 'الحجز غير نشط'];
        }

        $used = (int) $reservation['sessions_used'];
        $total = (int) $reservation['sessions_total'];

        if ($used >= $total) {
            return ['success' => false, 'error' => 'تم استهلاك جميع الحصص'];
        }

        $newUsed = $used + 1;
        $updates = [
            'sessions_used' => $newUsed,
            'updated_at'    => date('Y-m-d H:i:s'),
        ];

        if ($newUsed >= $total) {
            $updates['status'] = 'completed';
        }

        $db->update('sa_pool_reservations', $updates, 'id = ?', [$reservationId]);

        if ($newUsed >= $total) {
            $db->update('sa_groups', [
                'status'      => 'completed',
                'is_archived' => 1,
                'archived_at' => date('Y-m-d H:i:s'),
                'updated_at'  => date('Y-m-d H:i:s'),
            ], 'pool_reservation_id = ?', [$reservationId]);
        }

        return [
            'success'    => true,
            'sessions_used'      => $newUsed,
            'sessions_remaining' => $total - $newUsed,
        ];
    }

    public static function cancel(int $reservationId, string $reason = ''): array
    {
        $db = App::getInstance()->db();

        $reservation = $db->selectOne(
            "SELECT id, group_id, status FROM sa_pool_reservations WHERE id = ?",
            [$reservationId]
        );
        if (!$reservation) {
            return ['success' => false, 'error' => 'الحجز غير موجود'];
        }
        if ($reservation['status'] !== 'active') {
            return ['success' => false, 'error' => 'الحجز غير نشط — لا يمكن الإلغاء'];
        }

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

        $db->update('sa_groups', [
            'status'      => 'cancelled',
            'is_archived' => 1,
            'archived_at' => date('Y-m-d H:i:s'),
            'updated_at'  => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $reservation['group_id']]);

        return ['success' => true];
    }

    public static function generateNumber(): string
    {
        $db = App::getInstance()->db();
        $prefix = 'PR-' . date('Ymd') . '-';
        $row = $db->selectOne(
            "SELECT MAX(CAST(SUBSTRING(reservation_number, " . (strlen($prefix) + 1) . ") AS UNSIGNED)) as max_num
             FROM sa_pool_reservations WHERE reservation_number LIKE ?",
            [$prefix . '%']
        );
        $next = ((int) ($row['max_num'] ?? 0)) + 1;
        return $prefix . str_pad((string) $next, 4, '0', STR_PAD_LEFT);
    }
}
