<?php
/**
 * Availability engine - Supports day, slot, and service booking modes
 *
 * @package WahraRentalsBookings
 */

defined('ABSPATH') || exit;

/**
 * Availability class
 */
class WAHRB_Availability {

    /**
     * Check availability for a product
     *
     * @param int $product_id Product ID
     * @param string $start_date Start date (Y-m-d or datetime)
     * @param string $end_date End date (Y-m-d or datetime)
     * @param int|null $variation_id Variation ID
     * @param int $qty Quantity requested
     * @param int|null $exclude_booking_id Booking ID to exclude (for edits)
     * @return array Availability result
     */
    public static function check(
        int $product_id,
        string $start_date,
        string $end_date,
        ?int $variation_id = null,
        int $qty = 1,
        ?int $exclude_booking_id = null
    ): array {
        global $wpdb;
        $db = WAHRB_Database::instance();

        // Normalize dates
        $start_dt = gmdate('Y-m-d H:i:s', strtotime($start_date));
        $end_dt = gmdate('Y-m-d H:i:s', strtotime($end_date));

        // Validate dates
        // For slot/service modes, start and end can be the same date (single day booking)
        // For day mode, end must be after start
        $booking_mode = get_post_meta($product_id, '_wahrb_booking_mode', true) ?: 'day';
        
        if ($booking_mode === 'day' && strtotime($start_dt) >= strtotime($end_dt)) {
            return [
                'available' => false,
                'message' => __('End date must be after start date', 'wahra-rentals-bookings'),
                'reason' => 'invalid_dates',
            ];
        }

        if (strtotime($start_dt) < strtotime(gmdate('Y-m-d 00:00:00'))) {
            return [
                'available' => false,
                'message' => __('Start date cannot be in the past', 'wahra-rentals-bookings'),
                'reason' => 'past_date',
            ];
        }

        // Check product exists and is rental enabled
        $product = wc_get_product($product_id);
        if (!$product) {
            return [
                'available' => false,
                'message' => __('Product not found', 'wahra-rentals-bookings'),
                'reason' => 'product_not_found',
            ];
        }

        if (get_post_meta($product_id, '_wahrb_rental_enabled', true) !== 'yes') {
            return [
                'available' => false,
                'message' => __('This product is not available for rental', 'wahra-rentals-bookings'),
                'reason' => 'not_rental',
            ];
        }

        // ============================================
        // GET BOOKING MODE - KEY DIFFERENTIATION
        // ============================================
        $booking_mode = get_post_meta($product_id, '_wahrb_booking_mode', true) ?: 'day';

        // Get product settings
        $total_units = (int) get_post_meta($product_id, '_wahrb_total_units', true) ?: 1;

        // Calculate duration based on mode
        $duration_seconds = strtotime($end_dt) - strtotime($start_dt);
        
        // Mode-specific duration validation and calculation
        $validation_result = self::validate_duration_by_mode($product_id, $duration_seconds, $booking_mode, $total_units);
        if (!$validation_result['valid']) {
            return $validation_result['error'];
        }
        
        $duration_units = $validation_result['duration_units'];
        $unit_label = $validation_result['unit_label'];
        $total_units = $validation_result['total_units']; // May be overridden for service mode

        // Check booking window
        $booking_settings = get_option('wahrb_settings_booking', []);
        $min_window_hours = $booking_settings['min_booking_window_hours'] ?? 24;
        $max_window_days = $booking_settings['max_booking_window_days'] ?? 365;

        $hours_until_start = (strtotime($start_dt) - time()) / 3600; // Both in UTC epoch
        $days_until_start = $hours_until_start / 24;

        if ($hours_until_start < $min_window_hours) {
            return [
                'available' => false,
                /* translators: %d: hours */
                'message' => sprintf(__('You must book at least %d hour(s) in advance', 'wahra-rentals-bookings'), $min_window_hours),
                'reason' => 'min_booking_window',
            ];
        }

        if ($days_until_start > $max_window_days) {
            return [
                'available' => false,
                /* translators: %d: days */
                'message' => sprintf(__('You cannot book more than %d day(s) in advance', 'wahra-rentals-bookings'), $max_window_days),
                'reason' => 'max_booking_window',
            ];
        }

        // Check blackout dates (applies to all modes)
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $blackouts = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM {$db->table('blackout_dates')} WHERE product_id = %d AND (variation_id IS NULL OR variation_id = %d) AND date_start <= %s AND date_end >= %s AND deleted_at IS NULL",
            $product_id,
            $variation_id ?: 0,
            gmdate('Y-m-d', strtotime($end_dt)),
            gmdate('Y-m-d', strtotime($start_dt))
        ));

        if (!empty($blackouts)) {
            $blackout = $blackouts[0];
            $reason = $blackout->reason ?: __('Dates not available', 'wahra-rentals-bookings');
            return [
                'available' => false,
                'message' => $reason,
                'reason' => 'blackout',
                'blackout_dates' => [
                    'start' => $blackout->date_start,
                    'end' => $blackout->date_end,
                ],
            ];
        }

        // Get buffer times - MODE SPECIFIC
        $buffers = self::get_buffers_by_mode($product_id, $booking_mode, $booking_settings);
        $buffer_before = $buffers['before'];
        $buffer_after = $buffers['after'];

        /**
         * ════════════════════════════════════════════════════════════════════════
         * MULTI-UNIT AVAILABILITY LOGIC
         * ════════════════════════════════════════════════════════════════════════
         * 
         * This system handles both single-unit and multi-unit product scenarios:
         * 
         * SINGLE-UNIT PRODUCTS (total_units = 1):
         * - Once a booking is CONFIRMED (or checked_in/out/completed), the unit is blocked
         * - NO further bookings allowed for overlapping time periods
         * - Pending bookings don't block the unit (vendor hasn't confirmed yet)
         * 
         * MULTI-UNIT PRODUCTS (total_units > 1):
         * - Multiple bookings can occur in the same time period
         * - Each confirmed booking occupies 1 unit (qty=1) or more (qty>1)
         * - Available units = total_units - (booked_units + held_units)
         * - A slot remains available if ANY units are free
         * 
         * STATUSES THAT BLOCK UNITS:
         * - 'confirmed': Vendor approved, booking is locked in
         * - 'checked_in': Rental has started
         * - 'checked_out': Item has been returned, awaiting validation
         * - 'completed': Booking fully closed
         * 
         * STATUSES THAT DON'T BLOCK UNITS:
         * - 'pending': Awaiting vendor confirmation (not a guarantee)
         * - 'cancelled': Canceled bookings don't occupy units
         * - 'failed': Failed payment doesn't occupy units
         * 
         * HOLDS (temporary reservations):
         * - Active holds also count as "used units" during checkout process
         * - Holds prevent overbooking during the customer's checkout flow
         * - Automatically expire after configured duration (default: 15 min)
         * ════════════════════════════════════════════════════════════════════════
         */

        // Check overlapping bookings
        $exclude_sql = $exclude_booking_id ? $wpdb->prepare(' AND booking_id != %d', $exclude_booking_id) : '';

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $overlapping = $wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(qty), 0) FROM {$db->table('bookings')} WHERE product_id = %d AND (variation_id IS NULL OR variation_id = %d) AND status IN ('confirmed', 'checked_in', 'checked_out', 'completed') AND deleted_at IS NULL AND ((start_dt < %s AND end_dt > %s) OR (DATE_SUB(start_dt, INTERVAL %d SECOND) <= %s AND DATE_ADD(end_dt, INTERVAL %d SECOND) >= %s)) {$exclude_sql}",
            $product_id,
            $variation_id ?: 0,
            $end_dt,
            $start_dt,
            $buffer_before,
            $end_dt,
            $buffer_after,
            $start_dt
        ));

        $booked_units = (int) $overlapping;

        // Check active holds
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $active_holds = $wpdb->get_var($wpdb->prepare(
            "SELECT COALESCE(SUM(qty), 0) FROM {$db->table('holds')} WHERE product_id = %d AND (variation_id IS NULL OR variation_id = %d) AND is_active = 1 AND converted_to_booking = 0 AND expires_at > NOW() AND start_dt < %s AND end_dt > %s",
            $product_id,
            $variation_id ?: 0,
            $end_dt,
            $start_dt
        ));

        $held_units = (int) $active_holds;
        $used_units = $booked_units + $held_units;
        $available_units = $total_units - $used_units;

        if ($available_units < $qty) {
            $suggestions = self::find_alternatives($product_id, $start_dt, $end_dt, $variation_id, $qty, $booking_mode);

            return [
                'available' => false,
                'message' => __('This slot is not available', 'wahra-rentals-bookings'),
                'reason' => 'no_availability',
                'available_units' => max(0, $available_units),
                'requested_units' => $qty,
                'suggestions' => $suggestions,
                'booking_mode' => $booking_mode,
            ];
        }

        // Available!
        return [
            'available' => true,
            'message' => __('Available', 'wahra-rentals-bookings'),
            'available_units' => $available_units,
            'total_units' => $total_units,
            'duration_units' => $duration_units,
            'unit_label' => $unit_label,
            'booking_mode' => $booking_mode,
        ];
    }

    /**
     * Validate duration based on booking mode
     *
     * @param int $product_id Product ID
     * @param int $duration_seconds Duration in seconds
     * @param string $booking_mode Booking mode (day/slot/service)
     * @param int $total_units Total units available
     * @return array Validation result
     */
    private static function validate_duration_by_mode(int $product_id, int $duration_seconds, string $booking_mode, int $total_units): array {
        
        if ($booking_mode === 'slot') {
            // ============================================
            // SLOT MODE: Calculate in hours
            // ============================================
            $duration_hours = ceil($duration_seconds / 3600);
            $slot_duration_minutes = (int) get_post_meta($product_id, '_wahrb_slot_duration_minutes', true) ?: 60;
            
            // Validate slot duration
            $min_hours = (int) get_post_meta($product_id, '_wahrb_min_duration_hours', true) ?: 1;
            $max_hours = (int) get_post_meta($product_id, '_wahrb_max_duration_hours', true) ?: 24;
            
            if ($duration_hours < $min_hours) {
                return [
                    'valid' => false,
                    'error' => [
                        'available' => false,
                        /* translators: %d: minimum duration in hours */
                        'message' => sprintf(__('Minimum duration is %d hour(s)', 'wahra-rentals-bookings'), $min_hours),
                        'reason' => 'min_duration',
                    ],
                ];
            }
            
            if ($duration_hours > $max_hours) {
                return [
                    'valid' => false,
                    'error' => [
                        'available' => false,
                        /* translators: %d: maximum duration in hours */
                        'message' => sprintf(__('Maximum duration is %d hour(s)', 'wahra-rentals-bookings'), $max_hours),
                        'reason' => 'max_duration',
                    ],
                ];
            }
            
            return [
                'valid' => true,
                'duration_units' => $duration_hours,
                'unit_label' => __('hour(s)', 'wahra-rentals-bookings'),
                'total_units' => $total_units,
            ];
            
        } elseif ($booking_mode === 'service') {
            // ============================================
            // SERVICE MODE: Fixed duration per session
            // ============================================
            $service_duration_minutes = (int) get_post_meta($product_id, '_wahrb_service_duration_minutes', true) ?: 60;
            $capacity_per_slot = (int) get_post_meta($product_id, '_wahrb_capacity_per_slot', true) ?: 1;
            
            return [
                'valid' => true,
                'duration_units' => 1, // Always 1 session
                'unit_label' => __('session(s)', 'wahra-rentals-bookings'),
                'total_units' => $capacity_per_slot, // Use capacity for services
            ];
            
        } else {
            // ============================================
            // DAY MODE: Calculate in days (default)
            // ============================================
            $duration_days = ceil($duration_seconds / 86400);
            $min_duration = (int) get_post_meta($product_id, '_wahrb_min_duration', true) ?: 1;
            $max_duration = (int) get_post_meta($product_id, '_wahrb_max_duration', true) ?: 365;
            
            if ($duration_days < $min_duration) {
                return [
                    'valid' => false,
                    'error' => [
                        'available' => false,
                        /* translators: %d: minimum rental duration in days */
                        'message' => sprintf(__('Minimum duration is %d day(s)', 'wahra-rentals-bookings'), absint($min_duration)),
                        'reason' => 'min_duration',
                    ],
                ];
            }

            if ($duration_days > $max_duration) {
                return [
                    'valid' => false,
                    'error' => [
                        'available' => false,
                        /* translators: %d: maximum rental duration in days */
                        'message' => sprintf(__('Maximum duration is %d day(s)', 'wahra-rentals-bookings'), absint($max_duration)),
                        'reason' => 'max_duration',
                    ],
                ];
            }
            
            return [
                'valid' => true,
                'duration_units' => $duration_days,
                'unit_label' => __('day(s)', 'wahra-rentals-bookings'),
                'total_units' => $total_units,
            ];
        }
    }

    /**
     * Get buffer times based on booking mode
     *
     * @param int $product_id Product ID
     * @param string $booking_mode Booking mode
     * @param array $booking_settings Global booking settings
     * @return array Buffer times in seconds
     */
    private static function get_buffers_by_mode(int $product_id, string $booking_mode, array $booking_settings): array {
        $product_buffer_before = get_post_meta($product_id, '_wahrb_buffer_before', true);
        $product_buffer_after = get_post_meta($product_id, '_wahrb_buffer_after', true);
        
        if ($booking_mode === 'slot') {
            // For slot mode, buffers are in minutes
            $buffer_before = ($product_buffer_before !== '' && $product_buffer_before !== false) 
                ? (int) $product_buffer_before * 60  // minutes to seconds
                : (($booking_settings['slot_buffer_minutes'] ?? 15) * 60);
            $buffer_after = ($product_buffer_after !== '' && $product_buffer_after !== false) 
                ? (int) $product_buffer_after * 60 
                : (($booking_settings['slot_buffer_minutes'] ?? 15) * 60);
        } elseif ($booking_mode === 'service') {
            // For service mode, minimal buffers between appointments
            $buffer_before = ($product_buffer_before !== '' && $product_buffer_before !== false) 
                ? (int) $product_buffer_before * 60 
                : (($booking_settings['service_buffer_minutes'] ?? 10) * 60);
            $buffer_after = ($product_buffer_after !== '' && $product_buffer_after !== false) 
                ? (int) $product_buffer_after * 60 
                : (($booking_settings['service_buffer_minutes'] ?? 10) * 60);
        } else {
            // For day mode, buffers in hours
            $buffer_before_hours = ($product_buffer_before !== '' && $product_buffer_before !== false) 
                ? (int) $product_buffer_before 
                : ($booking_settings['buffer_before_hours'] ?? 2);
            $buffer_after_hours = ($product_buffer_after !== '' && $product_buffer_after !== false) 
                ? (int) $product_buffer_after 
                : ($booking_settings['buffer_after_hours'] ?? 1);
            $buffer_before = $buffer_before_hours * 3600;
            $buffer_after = $buffer_after_hours * 3600;
        }
        
        return [
            'before' => $buffer_before,
            'after' => $buffer_after,
        ];
    }

    /**
     * Find alternative available dates/times
     *
     * @param int $product_id Product ID
     * @param string $start_dt Original start date
     * @param string $end_dt Original end date
     * @param int|null $variation_id Variation ID
     * @param int $qty Quantity
     * @param string $booking_mode Booking mode
     * @return array Suggestions
     */
    private static function find_alternatives(
        int $product_id,
        string $start_dt,
        string $end_dt,
        ?int $variation_id,
        int $qty,
        string $booking_mode = 'day'
    ): array {
        $suggestions = [];
        $duration_seconds = strtotime($end_dt) - strtotime($start_dt);

        if ($booking_mode === 'slot') {
            // For slot mode, try next time slots (hourly increments)
            for ($i = 1; $i <= 8; $i++) {
                $new_start = gmdate('Y-m-d H:i:s', strtotime($start_dt) + ($i * 3600));
                $new_end = gmdate('Y-m-d H:i:s', strtotime($new_start) + $duration_seconds);

                $check = self::check($product_id, $new_start, $new_end, $variation_id, $qty);

                if ($check['available']) {
                    $suggestions[] = [
                        'start_date' => $new_start,
                        'end_date' => $new_end,
                        'formatted' => gmdate('H:i', strtotime($new_start)) . ' - ' . gmdate('H:i', strtotime($new_end)),
                    ];

                    if (count($suggestions) >= 3) {
                        break;
                    }
                }
            }
        } else {
            // For day/service mode, try next days
            $duration_days = ceil($duration_seconds / 86400);
            
            for ($i = 1; $i <= 14; $i++) {
                $new_start = gmdate('Y-m-d', strtotime($start_dt) + ($i * 86400));
                $new_end = gmdate('Y-m-d', strtotime($new_start) + ($duration_days * 86400));

                $check = self::check($product_id, $new_start, $new_end, $variation_id, $qty);

                if ($check['available']) {
                    $suggestions[] = [
                        'start_date' => $new_start,
                        'end_date' => $new_end,
                        'formatted' => date_i18n(get_option('date_format'), strtotime($new_start)) . ' - ' . date_i18n(get_option('date_format'), strtotime($new_end)),
                    ];

                    if (count($suggestions) >= 3) {
                        break;
                    }
                }
            }
        }

        return $suggestions;
    }

    /**
     * Generate available time slots for a product on a given date
     *
     * @param int $product_id Product ID
     * @param string $date Date (Y-m-d)
     * @param int|null $variation_id Variation ID
     * @return array Available time slots
     */
    public static function get_time_slots(int $product_id, string $date, ?int $variation_id = null): array {
        $booking_mode = get_post_meta($product_id, '_wahrb_booking_mode', true) ?: 'day';
        
        if ($booking_mode !== 'slot' && $booking_mode !== 'service') {
            return []; // Time slots only for slot/service modes
        }
        
        // Get business hours for this day
        $day_of_week = gmdate('N', strtotime($date)); // 1 (Mon) to 7 (Sun)
        $business_hours = get_post_meta($product_id, '_wahrb_business_hours', true) ?: [];
        
        // Default business hours if not set
        if (empty($business_hours)) {
            $business_hours = [
                'start' => '09:00',
                'end' => '18:00',
            ];
        } elseif (isset($business_hours[$day_of_week])) {
            $business_hours = $business_hours[$day_of_week];
        }
        
        // Check if closed this day
        if (isset($business_hours['closed']) && $business_hours['closed']) {
            return [];
        }
        
        $start_time = $business_hours['start'] ?? '09:00';
        $end_time = $business_hours['end'] ?? '18:00';
        
        // Get slot/service duration
        if ($booking_mode === 'slot') {
            $duration_minutes = (int) get_post_meta($product_id, '_wahrb_slot_duration_minutes', true) ?: 60;
        } else {
            $duration_minutes = (int) get_post_meta($product_id, '_wahrb_service_duration_minutes', true) ?: 60;
        }
        
        // Get buffer between slots
        $booking_settings = get_option('wahrb_settings_booking', []);
        $buffer_minutes = $booking_settings[$booking_mode . '_buffer_minutes'] ?? 15;
        
        // Generate slots
        $slots = [];
        $current = strtotime($date . ' ' . $start_time);
        $end_timestamp = strtotime($date . ' ' . $end_time);
        
        while ($current + ($duration_minutes * 60) <= $end_timestamp) {
            $slot_start = gmdate('Y-m-d H:i:s', $current);
            $slot_end = gmdate('Y-m-d H:i:s', $current + ($duration_minutes * 60));
            
            // Check availability for this slot
            $availability = self::check($product_id, $slot_start, $slot_end, $variation_id, 1);
            
            $slots[] = [
                'start_time' => gmdate('H:i', $current),
                'end_time' => gmdate('H:i', $current + ($duration_minutes * 60)),
                'start_datetime' => $slot_start,
                'end_datetime' => $slot_end,
                'available' => $availability['available'],
                'available_units' => $availability['available_units'] ?? 0,
                'formatted' => gmdate('H:i', $current) . ' - ' . gmdate('H:i', $current + ($duration_minutes * 60)),
            ];
            
            // Move to next slot (duration + buffer)
            $current += ($duration_minutes + $buffer_minutes) * 60;
        }
        
        return $slots;
    }

    /**
     * Get calendar data for a product (supports all modes)
     *
     * @param int $product_id Product ID
     * @param string $start_date Start date for calendar view
     * @param int $months Number of months to show
     * @param int|null $variation_id Variation ID
     * @return array Calendar data
     */
    public static function get_calendar_data(
        int $product_id,
        string $start_date,
        int $months = 2,
        ?int $variation_id = null
    ): array {
        global $wpdb;
        $db = WAHRB_Database::instance();  
        
        $booking_mode = get_post_meta($product_id, '_wahrb_booking_mode', true) ?: 'day';

        $start = new DateTime($start_date);
        $end = clone $start;
        $end->modify("+{$months} months");

        $calendar = [];
        $current = clone $start;

        while ($current < $end) {
            $date_str = $current->format('Y-m-d');

            // Check if this day is available
            $next_day = clone $current;
            $next_day->modify('+1 day');

            $availability = self::check($product_id, $date_str, $next_day->format('Y-m-d'), $variation_id, 1);

            // Get pricing for this day
            $pricing = WAHRB_Pricing_Engine::instance()->get_day_price($product_id, $date_str, $variation_id);

            $day_data = [
                'date' => $date_str,
                'available' => $availability['available'],
                'price' => $pricing['price'],
                'is_weekend' => in_array($current->format('N'), [6, 7]),
                'is_high_season' => $pricing['is_high_season'] ?? false,
                'available_units' => $availability['available_units'] ?? 0,
                'booking_mode' => $booking_mode,
            ];
            
            // For slot/service modes, include time slots
            if ($booking_mode === 'slot' || $booking_mode === 'service') {
                $day_data['time_slots'] = self::get_time_slots($product_id, $date_str, $variation_id);
                $day_data['has_available_slots'] = !empty(array_filter($day_data['time_slots'], fn($s) => $s['available']));
            }

            $calendar[$date_str] = $day_data;

            $current->modify('+1 day');
        }

        // Get blackout dates
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $blackouts = $wpdb->get_results($wpdb->prepare(
            "SELECT date_start, date_end, reason FROM {$db->table('blackout_dates')} WHERE product_id = %d AND (variation_id IS NULL OR variation_id = %d) AND date_end >= %s AND date_start <= %s AND deleted_at IS NULL",
            $product_id,
            $variation_id ?: 0,
            $start->format('Y-m-d'),
            $end->format('Y-m-d')
        ), ARRAY_A);

        // Get existing bookings
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter
        $bookings = $wpdb->get_results($wpdb->prepare(
            "SELECT DATE(start_dt) as start_date, DATE(end_dt) as end_date, TIME(start_dt) as start_time, TIME(end_dt) as end_time, status, booking_mode FROM {$db->table('bookings')} WHERE product_id = %d AND (variation_id IS NULL OR variation_id = %d) AND status IN ('confirmed', 'checked_in', 'checked_out', 'completed') AND deleted_at IS NULL AND end_dt >= %s AND start_dt <= %s",
            $product_id,
            $variation_id ?: 0,
            $start->format('Y-m-d'),
            $end->format('Y-m-d')
        ), ARRAY_A);

        return [
            'calendar' => $calendar,
            'blackouts' => $blackouts,
            'bookings' => $bookings,
            'currency' => get_woocommerce_currency(),
            'currency_symbol' => html_entity_decode(get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8'),
            'booking_mode' => $booking_mode,
        ];
    }
}
