<?php
declare(strict_types=1);

namespace App\Modules\SportsActivity\Controllers;

use App\Core\Controller;
use App\Core\Request;
use App\Core\Response;
use App\Core\App;
use App\Core\Pagination;
use App\Modules\SportsActivity\Models\Booking;
use App\Modules\SportsActivity\Services\BookingService;

class BookingController extends Controller
{
    /**
     * List bookings with filters (date range, facility, type, status), pagination.
     */
    public function index(Request $request): Response
    {
        $filters = [
            'date_from'    => trim((string) $request->get('date_from', '')),
            'date_to'      => trim((string) $request->get('date_to', '')),
            'facility_id'  => trim((string) $request->get('facility_id', '')),
            'booking_type' => trim((string) $request->get('booking_type', '')),
            'status'       => trim((string) $request->get('status', '')),
        ];

        $page = max(1, (int) $request->get('page', 1));
        $perPage = 25;
        $db = App::getInstance()->db();

        $where = "1=1";
        $params = [];

        if ($filters['date_from'] !== '') {
            $where .= " AND b.booking_date >= ?";
            $params[] = $filters['date_from'];
        }

        if ($filters['date_to'] !== '') {
            $where .= " AND b.booking_date <= ?";
            $params[] = $filters['date_to'];
        }

        if ($filters['facility_id'] !== '') {
            $where .= " AND fu.facility_id = ?";
            $params[] = (int) $filters['facility_id'];
        }

        if ($filters['booking_type'] !== '') {
            $where .= " AND b.booking_type = ?";
            $params[] = $filters['booking_type'];
        }

        if ($filters['status'] !== '') {
            $where .= " AND b.status = ?";
            $params[] = $filters['status'];
        }

        $total = (int) ($db->selectOne(
            "SELECT COUNT(*) as cnt
             FROM sa_bookings b
             LEFT JOIN sa_facility_units fu ON fu.id = b.facility_unit_id
             WHERE {$where}",
            $params
        )['cnt'] ?? 0);

        $pagination = Pagination::paginate($total, $perPage, $page);
        $offset = ($page - 1) * $perPage;

        $bookings = $db->select(
            "SELECT b.*, fu.name_ar as unit_name, f.name_ar as facility_name
             FROM sa_bookings b
             LEFT JOIN sa_facility_units fu ON fu.id = b.facility_unit_id
             LEFT JOIN sa_facilities f ON f.id = fu.facility_id
             WHERE {$where}
             ORDER BY b.booking_date DESC, b.start_time ASC
             LIMIT {$perPage} OFFSET {$offset}",
            $params
        );

        $facilities = $db->select("SELECT id, name_ar FROM sa_facilities WHERE is_archived = 0 ORDER BY name_ar", []);

        return $this->view('SportsActivity.Views.bookings.index', [
            'bookings'     => $bookings,
            'pagination'   => $pagination,
            'filters'      => $filters,
            'facilities'   => $facilities,
            'bookingTypes' => Booking::getBookingTypeOptions(),
            'statuses'     => Booking::getStatusOptions(),
        ]);
    }

    /**
     * Show form for creating an hourly booking.
     */
    public function create(Request $request): Response
    {
        $db = App::getInstance()->db();

        $facilityUnits = $db->select(
            "SELECT fu.id, fu.name_ar, fu.code, f.name_ar as facility_name, f.id as facility_id
             FROM sa_facility_units fu
             JOIN sa_facilities f ON f.id = fu.facility_id
             WHERE fu.is_active = 1
             ORDER BY f.name_ar ASC, fu.name_ar ASC",
            []
        );

        // Group units by facility
        $grouped = [];
        foreach ($facilityUnits as $unit) {
            $grouped[$unit['facility_name']][] = $unit;
        }

        return $this->view('SportsActivity.Views.bookings.create', [
            'facilityUnitsGrouped' => $grouped,
        ]);
    }

    /**
     * Store a new hourly booking using BookingService.
     */
    public function store(Request $request): Response
    {
        $data = [
            'facility_unit_id'  => (int) $request->post('facility_unit_id', 0),
            'booking_date'      => trim((string) $request->post('booking_date', '')),
            'start_time'        => trim((string) $request->post('start_time', '')),
            'end_time'          => trim((string) $request->post('end_time', '')),
            'participant_count' => (int) $request->post('participant_count', 1),
            'booker_type'       => trim((string) $request->post('booker_type', 'guest')),
            'booker_id'         => $request->post('booker_id', '') !== '' ? (int) $request->post('booker_id', 0) : null,
            'booker_name'       => trim((string) $request->post('booker_name', '')),
            'notes'             => trim((string) $request->post('notes', '')) ?: null,
        ];

        // Basic validation
        $errors = [];
        if ($data['facility_unit_id'] === 0) {
            $errors[] = 'يرجى اختيار الوحدة/الملعب';
        }
        if ($data['booking_date'] === '') {
            $errors[] = 'تاريخ الحجز مطلوب';
        }
        if ($data['start_time'] === '') {
            $errors[] = 'وقت البداية مطلوب';
        }
        if ($data['end_time'] === '') {
            $errors[] = 'وقت النهاية مطلوب';
        }
        if ($data['start_time'] !== '' && $data['end_time'] !== '' && $data['start_time'] >= $data['end_time']) {
            $errors[] = 'وقت البداية يجب أن يكون قبل وقت النهاية';
        }
        if ($data['booker_name'] === '') {
            $errors[] = 'اسم الحاجز مطلوب';
        } elseif (mb_strlen($data['booker_name']) > 300) {
            $errors[] = 'اسم الحاجز يجب ألا يتجاوز 300 حرف';
        }
        if ($data['participant_count'] < 1) {
            $errors[] = 'عدد المشاركين يجب أن يكون 1 على الأقل';
        }

        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('/sa/bookings/create');
        }

        $result = BookingService::createHourlyBooking($data);

        if ($result['success']) {
            return $this->redirect('/sa/bookings/' . $result['booking_id'])->withSuccess('تم إنشاء الحجز بنجاح — رقم: ' . $result['booking_number']);
        }

        $session = App::getInstance()->session();
        $session->flash('_old_input', $request->all());
        return $this->redirect('/sa/bookings/create')->withError($result['error']);
    }

    /**
     * Show booking detail with participants.
     */
    public function show(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();

        $booking = $db->selectOne(
            "SELECT b.*, fu.name_ar as unit_name, fu.code as unit_code,
                    f.name_ar as facility_name, g.name_ar as group_name,
                    c.full_name_ar as coach_name
             FROM sa_bookings b
             LEFT JOIN sa_facility_units fu ON fu.id = b.facility_unit_id
             LEFT JOIN sa_facilities f ON f.id = fu.facility_id
             LEFT JOIN sa_groups g ON g.id = b.group_id
             LEFT JOIN sa_coaches c ON c.id = b.coach_id
             WHERE b.id = ?",
            [(int) $id]
        );

        if (!$booking) {
            return $this->redirect('/sa/bookings')->withError('الحجز غير موجود');
        }

        $participants = $db->select(
            "SELECT bp.*, p.full_name_ar as player_name, p.registration_serial as player_code
             FROM sa_booking_participants bp
             LEFT JOIN sa_players p ON p.id = bp.player_id
             WHERE bp.booking_id = ?
             ORDER BY bp.id ASC",
            [(int) $id]
        );

        return $this->view('SportsActivity.Views.bookings.show', [
            'booking'      => $booking,
            'participants' => $participants,
            'statuses'     => Booking::getStatusOptions(),
            'bookingTypes' => Booking::getBookingTypeOptions(),
        ]);
    }

    /**
     * Cancel a booking.
     */
    public function cancel(Request $request, string $id): Response
    {
        $reason = trim((string) $request->post('reason', ''));
        $result = BookingService::cancel((int) $id, $reason);

        if ($result['success']) {
            return $this->redirect('/sa/bookings/' . $id)->withSuccess('تم إلغاء الحجز');
        }

        return $this->redirect('/sa/bookings/' . $id)->withError($result['error']);
    }

    /**
     * Postpone a booking to a new date/time.
     */
    public function postpone(Request $request, string $id): Response
    {
        $newDate = trim((string) $request->post('new_date', ''));
        $newStartTime = trim((string) $request->post('new_start_time', ''));
        $newEndTime = trim((string) $request->post('new_end_time', ''));
        $reason = trim((string) $request->post('reason', ''));

        if ($newDate === '' || $newStartTime === '' || $newEndTime === '') {
            return $this->redirect('/sa/bookings/' . $id)->withError('يجب تحديد التاريخ والوقت الجديد');
        }

        $result = BookingService::postpone((int) $id, $newDate, $newStartTime, $newEndTime, $reason);

        if ($result['success']) {
            return $this->redirect('/sa/bookings/' . $id)->withSuccess('تم تأجيل الحجز بنجاح');
        }

        return $this->redirect('/sa/bookings/' . $id)->withError($result['error']);
    }

    /**
     * Check in a booking.
     */
    public function checkin(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $booking = $db->selectOne("SELECT * FROM sa_bookings WHERE id = ?", [(int) $id]);

        if (!$booking) {
            return $this->redirect('/sa/bookings')->withError('الحجز غير موجود');
        }

        if ($booking['status'] !== 'confirmed') {
            return $this->redirect('/sa/bookings/' . $id)->withError('لا يمكن تسجيل الحضور لهذا الحجز');
        }

        $db->update('sa_bookings', [
            'status'     => 'checked_in',
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $id]);

        return $this->redirect('/sa/bookings/' . $id)->withSuccess('تم تسجيل الحضور');
    }

    /**
     * Check out (complete) a booking.
     */
    public function checkout(Request $request, string $id): Response
    {
        $db = App::getInstance()->db();
        $booking = $db->selectOne("SELECT * FROM sa_bookings WHERE id = ?", [(int) $id]);

        if (!$booking) {
            return $this->redirect('/sa/bookings')->withError('الحجز غير موجود');
        }

        if (!in_array($booking['status'], ['confirmed', 'checked_in'])) {
            return $this->redirect('/sa/bookings/' . $id)->withError('لا يمكن إتمام هذا الحجز');
        }

        $db->update('sa_bookings', [
            'status'     => 'completed',
            'updated_at' => date('Y-m-d H:i:s'),
        ], 'id = ?', [(int) $id]);

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