<?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\Models\PoolSchedule;
use App\Modules\PoolManagement\Services\PoolGridService;
use App\Modules\PoolManagement\Services\PoolOccupancyOptimizer;

class PoolGridController extends Controller
{
    public function grid(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')));
        $gridState = PoolGridService::getGridState((int) $id, $date);
        $utilization = PoolOccupancyOptimizer::getUtilizationMetrics((int) $id, $date, $date);
        $schedules = PoolSchedule::getActiveForPool((int) $id, $date);

        return $this->view('PoolManagement.Views.grid', [
            'pool'        => $pool,
            'gridState'   => $gridState,
            'utilization' => $utilization,
            'date'        => $date,
            'schedules'   => $schedules,
            'bookingTypes'=> PoolConfiguration::getBookingTypes(),
        ]);
    }

    public function bookCells(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')));
        $cellsJson = trim((string) $request->post('cells_json', '[]'));
        $bookingType = trim((string) $request->post('booking_type', 'free_swim'));
        $bookerName = trim((string) $request->post('booker_name', ''));
        $swimmers = max(1, (int) $request->post('expected_swimmers', 1));
        $notes = trim((string) $request->post('notes', ''));

        $cells = json_decode($cellsJson, true);
        if (!is_array($cells) || empty($cells)) {
            return $this->redirect('/pool/' . $id . '/grid?date=' . $date)->withError('يجب تحديد خلايا من الشبكة');
        }
        if ($bookerName === '') {
            return $this->redirect('/pool/' . $id . '/grid?date=' . $date)->withError('اسم الحاجز مطلوب');
        }

        // Group cells by contiguous time ranges per lane set
        $laneSet = [];
        $minTime = '99:99';
        $maxTime = '00:00';
        foreach ($cells as $cell) {
            $lane = (int) ($cell['lane'] ?? 0);
            $start = $cell['start'] ?? '';
            $end = $cell['end'] ?? '';
            if ($lane > 0) $laneSet[$lane] = true;
            if ($start < $minTime) $minTime = $start;
            if ($end > $maxTime) $maxTime = $end;
        }
        $selectedLanes = array_keys($laneSet);

        if (empty($selectedLanes) || $minTime >= $maxTime) {
            return $this->redirect('/pool/' . $id . '/grid?date=' . $date)->withError('تحديد غير صالح');
        }

        // Check availability
        $availability = PoolGridService::checkLaneAvailability((int) $id, $date, $minTime, $maxTime, $selectedLanes);
        if (!$availability['available']) {
            return $this->redirect('/pool/' . $id . '/grid?date=' . $date)->withError('بعض الخلايا المحددة غير متاحة');
        }

        $selectionMode = count($selectedLanes) === count($pool->getLanes()) ? 'full_pool' : (count($selectedLanes) === 1 ? 'lane' : 'multi_lane');
        $bookingCode = 'PB-' . date('ymd') . '-' . strtoupper(bin2hex(random_bytes(3)));

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

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

    public function apiState(Request $request, string $id): Response
    {
        $date = trim((string) $request->get('date', date('Y-m-d')));
        $gridState = PoolGridService::getGridState((int) $id, $date);

        return $this->json($gridState);
    }
}
