<?php
declare(strict_types=1);

namespace App\Modules\PoolManagement\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\PoolManagement\Models\PoolConfiguration;
use App\Modules\PoolManagement\Models\PoolBooking;
use App\Modules\PoolManagement\Services\PoolGridService;
use App\Modules\PoolManagement\Services\PoolOccupancyOptimizer;

class PoolBookingController extends Controller
{
    public function index(Request $request): Response
    {
        $filters = [
            'pool_config_id' => trim((string) $request->get('pool_config_id', '')),
            'date_from'      => trim((string) $request->get('date_from', '')),
            'date_to'        => trim((string) $request->get('date_to', '')),
            'status'         => trim((string) $request->get('status', '')),
            'booking_type'   => trim((string) $request->get('booking_type', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $result = PoolBooking::search($filters, 25, $page);

        return $this->view('PoolManagement.Views.bookings', [
            'bookings'     => $result['data'],
            'pagination'   => $result['pagination'],
            'filters'      => $filters,
            'pools'        => PoolConfiguration::allActive(),
            'bookingTypes' => PoolConfiguration::getBookingTypes(),
            'statuses'     => PoolBooking::getStatuses(),
        ]);
    }

    public function create(Request $request, string $id): Response
    {
        $pool = PoolConfiguration::find((int) $id);
        if (!$pool) {
            return $this->redirect('/pool')->withError('حمام السباحة غير موجود');
        }

        $date = trim((string) $request->get('date', date('Y-m-d')));
        $lanes = $pool->getLanes();

        return $this->view('PoolManagement.Views.book', [
            'pool'         => $pool,
            'lanes'        => $lanes,
            'date'         => $date,
            'bookingTypes' => PoolConfiguration::getBookingTypes(),
            'bookerTypes'  => PoolBooking::getBookerTypes(),
        ]);
    }

    public function store(Request $request, string $id): Response
    {
        $pool = PoolConfiguration::find((int) $id);
        if (!$pool) {
            return $this->redirect('/pool')->withError('حمام السباحة غير موجود');
        }

        $date = trim((string) $request->post('booking_date', date('Y-m-d')));
        $startTime = trim((string) $request->post('start_time', ''));
        $endTime = trim((string) $request->post('end_time', ''));
        $bookingType = trim((string) $request->post('booking_type', ''));
        $selectedLanes = $request->post('lanes', []);
        $bookerType = trim((string) $request->post('booker_type', 'member'));
        $bookerName = trim((string) $request->post('booker_name', ''));
        $swimmers = max(1, (int) $request->post('expected_swimmers', 1));

        if (!is_array($selectedLanes)) {
            $selectedLanes = [];
        }
        $selectedLanes = array_map('intval', $selectedLanes);

        $errors = [];
        if (empty($startTime)) $errors[] = 'وقت البداية مطلوب';
        if (empty($endTime)) $errors[] = 'وقت النهاية مطلوب';
        if ($startTime >= $endTime) $errors[] = 'وقت البداية يجب أن يكون قبل النهاية';
        if (empty($bookingType)) $errors[] = 'نوع الحجز مطلوب';
        if (empty($selectedLanes)) $errors[] = 'يجب اختيار حارة واحدة على الأقل';
        if ($bookerName === '') $errors[] = 'اسم الحاجز مطلوب';

        if (empty($errors)) {
            $availability = PoolGridService::checkLaneAvailability((int) $id, $date, $startTime, $endTime, $selectedLanes);
            if (!$availability['available']) {
                $errors[] = 'الحارات المختارة غير متاحة في هذا الوقت';
            }
        }

        if (!empty($errors)) {
            $session = App::getInstance()->session();
            $session->flash('_alerts', array_map(fn($e) => ['type' => 'error', 'message' => $e], $errors));
            $session->flash('_old_input', $request->all());
            return $this->redirect('/pool/' . $id . '/book?date=' . $date);
        }

        $selectionMode = count($selectedLanes) === count($pool->getLanes()) ? 'full_pool' : (count($selectedLanes) === 1 ? 'lane' : 'multi_lane');

        $bookingCode = 'PB-' . date('ymd') . '-' . strtoupper(bin2hex(random_bytes(3)));

        $booking = PoolBooking::create([
            'booking_code'     => $bookingCode,
            'pool_config_id'   => (int) $id,
            'booking_date'     => $date,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'booking_type'     => $bookingType,
            'selection_mode'   => $selectionMode,
            'lanes_json'       => json_encode($selectedLanes),
            'booker_type'      => $bookerType,
            'booker_name'      => $bookerName,
            'expected_swimmers'=> $swimmers,
            'unit_rate'        => 0,
            'total_amount'     => 0,
            'payment_status'   => 'pending',
            'status'           => 'confirmed',
        ]);

        return $this->redirect('/pool/' . $id . '/grid?date=' . $date)->withSuccess('تم الحجز بنجاح — كود: ' . $bookingCode);
    }

    public function show(Request $request, string $id): Response
    {
        $booking = PoolBooking::find((int) $id);
        if (!$booking) {
            return $this->redirect('/pool/bookings')->withError('الحجز غير موجود');
        }

        $pool = PoolConfiguration::find((int) $booking->pool_config_id);

        return $this->view('PoolManagement.Views.booking_show', [
            'booking'      => $booking->toArray(),
            'poolName'     => $pool ? $pool->name_ar : '',
            'bookingTypes' => PoolConfiguration::getBookingTypes(),
            'statuses'     => PoolBooking::getStatuses(),
            'bookerTypes'  => PoolBooking::getBookerTypes(),
        ]);
    }

    public function cancel(Request $request, string $id): Response
    {
        $booking = PoolBooking::find((int) $id);
        if (!$booking) {
            return $this->redirect('/pool/bookings')->withError('الحجز غير موجود');
        }

        $employee = App::getInstance()->currentEmployee();
        $booking->update([
            'status'       => 'cancelled',
            'cancelled_by' => $employee ? ($employee->id ?? $employee['id'] ?? null) : null,
            'cancelled_at' => date('Y-m-d H:i:s'),
            'cancel_reason'=> trim((string) $request->post('cancel_reason', '')),
        ]);

        return $this->redirect('/pool/bookings')->withSuccess('تم إلغاء الحجز');
    }

    public function checkin(Request $request, string $id): Response
    {
        $booking = PoolBooking::find((int) $id);
        if (!$booking) {
            return $this->redirect('/pool/bookings')->withError('الحجز غير موجود');
        }

        $actualSwimmers = (int) $request->post('actual_swimmers', $booking->expected_swimmers);
        $booking->update([
            'status'          => 'checked_in',
            'actual_swimmers' => $actualSwimmers,
        ]);

        return $this->redirect('/pool/' . $booking->pool_config_id . '/grid?date=' . $booking->booking_date)
            ->withSuccess('تم تسجيل الدخول');
    }
}
