<?php

class BookingController extends Controller
{
    public function index(Request $request): void
    {
        $db = $this->db();
        $facilities = $db->fetchAll("SELECT id, name_en, name_ar, facility_code FROM facilities WHERE is_active = 1 AND is_bookable = 1 ORDER BY name_en");

        $todayCount     = (int) $db->fetchColumn("SELECT COUNT(*) FROM facility_bookings WHERE booking_date = CURDATE() AND status NOT IN ('cancelled','no_show')");
        $pendingCount   = (int) $db->fetchColumn("SELECT COUNT(*) FROM facility_bookings WHERE status = 'pending'");
        $confirmedCount = (int) $db->fetchColumn("SELECT COUNT(*) FROM facility_bookings WHERE status = 'confirmed' AND booking_date >= CURDATE()");

        $this->view('bookings/index', [
            'title'       => lang('facilities.bookings'),
            'breadcrumbs' => [
                ['label' => lang('facilities.title'), 'url' => '/facilities'],
                ['label' => lang('facilities.bookings')],
            ],
            'facilities'     => $facilities,
            'todayCount'     => $todayCount,
            'pendingCount'   => $pendingCount,
            'confirmedCount' => $confirmedCount,
        ]);
    }

    public function create(Request $request): void
    {
        $db = $this->db();
        $facilities = $db->fetchAll(
            "SELECT f.id, f.name_en, f.name_ar, f.facility_code, f.booking_fee_per_hour, f.booking_fee_members,
                    f.min_booking_minutes, f.max_booking_minutes, f.advance_booking_days
             FROM facilities f WHERE f.is_active = 1 AND f.is_bookable = 1 ORDER BY f.name_en"
        );

        $this->view('bookings/create', [
            'title'       => lang('facilities.create_booking'),
            'breadcrumbs' => [
                ['label' => lang('facilities.title'), 'url' => '/facilities'],
                ['label' => lang('facilities.bookings'), 'url' => '/bookings'],
                ['label' => lang('facilities.create_booking')],
            ],
            'facilities' => $facilities,
        ]);
    }

    public function store(Request $request): void
    {
        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid security token'], 403);
            return;
        }

        $validator = new Validator($request->all(), [
            'facility_id'  => 'required|integer',
            'member_id'    => 'required|integer',
            'booking_date' => 'required|date',
            'start_time'   => 'required|string',
            'end_time'     => 'required|string',
            'booking_type' => 'nullable|in:regular,recurring,tournament,event,training,private',
            'notes'        => 'nullable|string|max:500',
        ]);

        if ($validator->fails()) {
            $this->json(['success' => false, 'errors' => $validator->errors()], 422);
            return;
        }

        $data = $validator->validated();
        $db = $this->db();

        // Check availability via stored procedure
        $db->execute(
            "CALL sp_check_booking_availability(?, ?, ?, ?, @p_avail, @p_conflicts)",
            [$data['facility_id'], $data['booking_date'], $data['start_time'], $data['end_time']]
        );
        $availability = $db->fetchOne("SELECT @p_avail AS is_available, @p_conflicts AS conflict_count");

        if (!$availability || !$availability['is_available']) {
            $this->json(['success' => false, 'message' => lang('facilities.slot_not_available')], 422);
            return;
        }

        // Calculate duration and fee
        $startTs = strtotime($data['start_time']);
        $endTs   = strtotime($data['end_time']);
        $durationMinutes = ($endTs - $startTs) / 60;

        $facility = $db->fetchOne("SELECT booking_fee_members, min_booking_minutes, max_booking_minutes, advance_booking_days FROM facilities WHERE id = ?", [$data['facility_id']]);
        if ($facility) {
            if ($facility['min_booking_minutes'] && $durationMinutes < $facility['min_booking_minutes']) {
                $this->json(['success' => false, 'message' => "Minimum booking is {$facility['min_booking_minutes']} minutes"], 422);
                return;
            }
            if ($facility['max_booking_minutes'] && $durationMinutes > $facility['max_booking_minutes']) {
                $this->json(['success' => false, 'message' => "Maximum booking is {$facility['max_booking_minutes']} minutes"], 422);
                return;
            }
            $advDays = $facility['advance_booking_days'] ?: 30;
            $maxDate = date('Y-m-d', strtotime("+{$advDays} days"));
            if ($data['booking_date'] > $maxDate) {
                $this->json(['success' => false, 'message' => "Cannot book more than {$advDays} days in advance"], 422);
                return;
            }
        }

        $feePerHour = (float) ($facility['booking_fee_members'] ?? 0);
        $feeAmount  = round($feePerHour * ($durationMinutes / 60), 4);

        $bookingNumber = SequenceGenerator::next('booking_number');

        $insertData = [
            'booking_number'    => $bookingNumber,
            'facility_id'      => $data['facility_id'],
            'member_id'        => $data['member_id'],
            'booking_date'     => $data['booking_date'],
            'start_time'       => $data['start_time'],
            'end_time'         => $data['end_time'],
            'duration_minutes' => (int) $durationMinutes,
            'booking_type'     => $data['booking_type'] ?? 'regular',
            'status'           => 'pending',
            'fee_amount'       => $feeAmount,
            'notes'            => $data['notes'] ?? null,
            'created_at'       => date('Y-m-d H:i:s'),
            'created_by'       => Auth::id(),
        ];

        $id = $db->insert('facility_bookings', $insertData);
        $this->audit('create', 'facility_bookings', $id, "Created booking {$bookingNumber}");

        $this->json(['success' => true, 'message' => lang('facilities.booking_created') . ': ' . $bookingNumber, 'redirect' => '/bookings']);
    }

    public function calendar(Request $request): void
    {
        $facilityId = (int) $request->routeParam('id');
        $db = $this->db();

        $facility = $db->fetchOne("SELECT * FROM facilities WHERE id = ? AND is_bookable = 1", [$facilityId]);
        if (!$facility) {
            $this->abort(404, 'Bookable facility not found');
        }

        $this->view('bookings/calendar', [
            'title'       => lang('facilities.booking_calendar') . ': ' . $facility['name_en'],
            'breadcrumbs' => [
                ['label' => lang('facilities.title'), 'url' => '/facilities'],
                ['label' => lang('facilities.bookings'), 'url' => '/bookings'],
                ['label' => lang('facilities.booking_calendar')],
            ],
            'facility' => $facility,
        ]);
    }

    public function updateStatus(Request $request): void
    {
        $id = (int) $request->routeParam('id');

        if (!CSRF::validate($request->csrfToken())) {
            $this->json(['success' => false, 'message' => 'Invalid security token'], 403);
            return;
        }

        $newStatus = $request->post('status');
        $reason    = $request->post('reason', '');

        $allowed = ['confirmed', 'checked_in', 'completed', 'cancelled', 'no_show'];
        if (!in_array($newStatus, $allowed)) {
            $this->json(['success' => false, 'message' => 'Invalid status'], 422);
            return;
        }

        $db  = $this->db();
        $old = $db->fetchOne("SELECT * FROM facility_bookings WHERE id = ?", [$id]);
        if (!$old) {
            $this->json(['success' => false, 'message' => 'Booking not found'], 404);
            return;
        }

        $updateData = ['status' => $newStatus, 'updated_at' => date('Y-m-d H:i:s')];

        if ($newStatus === 'confirmed') {
            $updateData['confirmed_at'] = date('Y-m-d H:i:s');
        } elseif ($newStatus === 'checked_in') {
            $updateData['checked_in_at'] = date('Y-m-d H:i:s');
            $updateData['checked_in_by'] = Auth::id();
        } elseif ($newStatus === 'completed') {
            $updateData['completed_at'] = date('Y-m-d H:i:s');
        } elseif ($newStatus === 'cancelled') {
            $updateData['cancelled_at']     = date('Y-m-d H:i:s');
            $updateData['cancelled_by']     = Auth::id();
            $updateData['cancellation_reason'] = $reason;
        }

        $db->update('facility_bookings', $updateData, 'id = ?', [$id]);
        $this->audit('update', 'facility_bookings', $id, "Booking status changed to {$newStatus}", $old, $updateData);

        $this->json(['success' => true, 'message' => lang('facilities.booking_updated')]);
    }
}