<?php
declare(strict_types=1);

namespace App\Modules\Reservations\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Modules\Reservations\Models\Reservation;
use App\Modules\Reservations\Services\ReservationService;
use App\Modules\Reservations\Services\FacilityConflictDetector;
use App\Modules\Facilities\Models\Facility;

class ReservationController extends Controller
{
    /**
     * List all reservations with status tabs, facility filter, date range, and search.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'q'           => trim((string) $request->get('q', '')),
            'facility_id' => trim((string) $request->get('facility_id', '')),
            'status'      => trim((string) $request->get('status', '')),
            'date_from'   => trim((string) $request->get('date_from', '')),
            'date_to'     => trim((string) $request->get('date_to', '')),
        ];

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

        return $this->view('Reservations.Views.index', [
            'reservations' => $result['data'],
            'pagination'   => $result['pagination'],
            'filters'      => $filters,
            'statuses'     => Reservation::getStatuses(),
            'facilities'   => Facility::allActive(),
        ]);
    }

    /**
     * Show the reservation creation form.
     */
    public function create(Request $request): Response
    {
        $db = App::getInstance()->db();
        $disciplines = $db->select(
            "SELECT id, name_ar FROM sport_disciplines WHERE is_active = 1 ORDER BY sort_order, name_ar"
        );

        return $this->view('Reservations.Views.create', [
            'facilities'  => Facility::allActive(),
            'disciplines' => $disciplines,
            'bookerTypes' => Reservation::getBookerTypes(),
        ]);
    }

    /**
     * Validate and store a new reservation.
     */
    public function store(Request $request): Response
    {
        $facilityId      = (int) $request->post('facility_id', 0);
        $reservationDate = trim((string) $request->post('reservation_date', ''));
        $startTime       = trim((string) $request->post('start_time', ''));
        $endTime         = trim((string) $request->post('end_time', ''));
        $bookerType      = trim((string) $request->post('booker_type', ''));
        $bookerName      = trim((string) $request->post('booker_name', ''));
        $bookerPhone     = trim((string) $request->post('booker_phone', ''));
        $playerId        = $request->post('player_id') ? (int) $request->post('player_id') : null;
        $memberId        = $request->post('member_id') ? (int) $request->post('member_id') : null;
        $notes           = trim((string) $request->post('notes', ''));

        // Validation
        $errors = [];
        if ($facilityId <= 0) {
            $errors[] = 'يجب اختيار المرفق';
        }
        if ($reservationDate === '') {
            $errors[] = 'تاريخ الحجز مطلوب';
        }
        if ($startTime === '' || $endTime === '') {
            $errors[] = 'وقت البداية والنهاية مطلوب';
        }
        if ($startTime !== '' && $endTime !== '' && $startTime >= $endTime) {
            $errors[] = 'وقت النهاية يجب أن يكون بعد وقت البداية';
        }
        if (!array_key_exists($bookerType, Reservation::getBookerTypes())) {
            $errors[] = 'نوع الحاجز غير صالح';
        }
        if ($bookerName === '') {
            $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('/reservations/create');
        }

        $result = ReservationService::create([
            'facility_id'      => $facilityId,
            'reservation_date' => $reservationDate,
            'start_time'       => $startTime,
            'end_time'         => $endTime,
            'booker_type'      => $bookerType,
            'booker_name'      => $bookerName,
            'booker_phone'     => $bookerPhone,
            'player_id'        => $playerId,
            'member_id'        => $memberId,
            'notes'            => $notes ?: null,
        ]);

        if (!$result['success']) {
            $session = App::getInstance()->session();
            $conflictMessages = array_map(
                fn($c) => ['type' => 'error', 'message' => $c['message']],
                $result['conflicts']
            );
            $session->flash('_alerts', $conflictMessages);
            $session->flash('_old_input', $request->all());
            return $this->redirect('/reservations/create');
        }

        return $this->redirect('/reservations/' . $result['reservation']->id)
            ->withSuccess('تم إنشاء الحجز بنجاح — رقم: ' . $result['reservation']->reservation_number);
    }

    /**
     * Show reservation detail with action buttons.
     */
    public function show(Request $request, string $id): Response
    {
        $reservation = Reservation::find((int) $id);
        if (!$reservation) {
            return $this->redirect('/reservations')->withError('الحجز غير موجود');
        }

        $facility = Facility::find((int) $reservation->facility_id);

        return $this->view('Reservations.Views.show', [
            'reservation' => $reservation,
            'facility'    => $facility,
            'statuses'    => Reservation::getStatuses(),
            'bookerTypes' => Reservation::getBookerTypes(),
        ]);
    }

    /**
     * Confirm a reservation.
     */
    public function confirm(Request $request, string $id): Response
    {
        $reservation = Reservation::find((int) $id);
        if (!$reservation) {
            return $this->redirect('/reservations')->withError('الحجز غير موجود');
        }

        ReservationService::confirm((int) $id);

        return $this->redirect('/reservations/' . $id)->withSuccess('تم تأكيد الحجز بنجاح');
    }

    /**
     * Cancel a reservation with an optional reason.
     */
    public function cancel(Request $request, string $id): Response
    {
        $reservation = Reservation::find((int) $id);
        if (!$reservation) {
            return $this->redirect('/reservations')->withError('الحجز غير موجود');
        }

        $reason = trim((string) $request->post('cancel_reason', ''));

        ReservationService::cancel((int) $id, $reason ?: null);

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

    /**
     * Check in a reservation.
     */
    public function checkIn(Request $request, string $id): Response
    {
        $reservation = Reservation::find((int) $id);
        if (!$reservation) {
            return $this->redirect('/reservations')->withError('الحجز غير موجود');
        }

        ReservationService::checkIn((int) $id);

        return $this->redirect('/reservations/' . $id)->withSuccess('تم تسجيل الدخول بنجاح');
    }

    /**
     * Calendar view for reservations.
     */
    public function calendar(Request $request): Response
    {
        $dateFrom = trim((string) $request->get('date_from', date('Y-m-d')));
        $dateTo   = trim((string) $request->get('date_to', date('Y-m-d', strtotime('+6 days'))));

        $facilities = Facility::allActive();

        $db = App::getInstance()->db();
        $reservations = $db->select(
            "SELECT r.*, f.name_ar as facility_name
             FROM `reservations` r
             LEFT JOIN `facilities` f ON f.id = r.facility_id
             WHERE r.`reservation_date` BETWEEN ? AND ?
               AND r.`status` NOT IN ('cancelled', 'no_show')
               AND r.`is_archived` = 0
             ORDER BY r.`reservation_date` ASC, r.`start_time` ASC",
            [$dateFrom, $dateTo]
        );

        return $this->view('Reservations.Views.calendar', [
            'facilities'   => $facilities,
            'reservations' => $reservations,
            'dateFrom'     => $dateFrom,
            'dateTo'       => $dateTo,
        ]);
    }
}
