<?php
/**
 * Hooks loader
 *
 * @package WahraRentalsBookings
 */

defined('ABSPATH') || exit;

/**
 * Loader class for managing WordPress hooks
 */
class WAHRB_Loader {

    /**
     * Actions to register
     *
     * @var array
     */
    protected array $actions = [];

    /**
     * Filters to register
     *
     * @var array
     */
    protected array $filters = [];

    /**
     * Constructor
     */
    public function __construct() {
        $this->define_hooks();
        $this->run();
    }

    /**
     * Define all hooks
     */
    private function define_hooks(): void {
        // WooCommerce product edit hooks — General tab (only in Dokan mode)
        // In solo mode, WAHRB_Solo_Integration provides a dedicated "Rental" tab instead,
        // so we skip these to avoid duplicate fields in the WC product editor.
        if (wahrb_is_dokan_active()) {
            $this->add_action('woocommerce_product_options_general_product_data', $this, 'add_rental_product_fields');
            $this->add_action('woocommerce_process_product_meta', $this, 'save_rental_product_fields');
        }

        // Frontend product page — rental calendar (both modes)
        $this->add_action('woocommerce_single_product_summary', $this, 'display_rental_calendar', 25);

        // Hide add-to-cart on rental products if setting enabled
        $this->add_filter('woocommerce_is_purchasable', $this, 'maybe_hide_add_to_cart_rental', 10, 2);

        // WooCommerce order hooks
        $this->add_action('woocommerce_order_status_completed', $this, 'on_order_completed');
        $this->add_action('woocommerce_order_status_processing', $this, 'on_order_processing');
        $this->add_action('woocommerce_order_status_cancelled', $this, 'on_order_cancelled');
        $this->add_action('woocommerce_order_status_refunded', $this, 'on_order_refunded');

        // Cart hooks
        $this->add_filter('woocommerce_add_cart_item_data', $this, 'add_booking_data_to_cart', 10, 3);
        $this->add_filter('woocommerce_get_item_data', $this, 'display_booking_data_in_cart', 10, 2);
        $this->add_action('woocommerce_checkout_create_order_line_item', $this, 'save_booking_data_to_order_item', 10, 4);

        // Admin hooks - use direct add_action since we're called from plugins_loaded
        // In solo mode, WAHRB_Solo_Integration provides a single merged menu
        // combining both admin and vendor pages — skip the separate admin menu.
        if (wahrb_is_dokan_active()) {
            add_action('admin_menu', [$this, 'add_admin_menu']);
        }
        add_action('admin_init', [$this, 'register_settings']);

        // Clear stats cache when bookings change
        add_action('wahrb_booking_created', [$this, 'clear_stats_cache'], 10, 2);
        add_action('wahrb_booking_status_changed', [$this, 'clear_stats_cache_on_status'], 10, 3);

        // AJAX hooks for legacy support (most should go through REST API)
        $this->add_action('wp_ajax_wahrb_get_availability', $this, 'ajax_get_availability');
        $this->add_action('wp_ajax_nopriv_wahrb_get_availability', $this, 'ajax_get_availability');
    }

    /**
     * Add an action hook
     *
     * @param string $hook Hook name
     * @param object $component Component instance
     * @param string $callback Callback method name
     * @param int $priority Hook priority
     * @param int $accepted_args Number of accepted arguments
     */
    public function add_action(string $hook, object $component, string $callback, int $priority = 10, int $accepted_args = 1): void {
        $this->actions[] = [
            'hook' => $hook,
            'component' => $component,
            'callback' => $callback,
            'priority' => $priority,
            'accepted_args' => $accepted_args,
        ];
    }

    /**
     * Add a filter hook
     *
     * @param string $hook Hook name
     * @param object $component Component instance
     * @param string $callback Callback method name
     * @param int $priority Hook priority
     * @param int $accepted_args Number of accepted arguments
     */
    public function add_filter(string $hook, object $component, string $callback, int $priority = 10, int $accepted_args = 1): void {
        $this->filters[] = [
            'hook' => $hook,
            'component' => $component,
            'callback' => $callback,
            'priority' => $priority,
            'accepted_args' => $accepted_args,
        ];
    }

    /**
     * Register all hooks
     */
    public function run(): void {
        foreach ($this->filters as $hook) {
            add_filter(
                $hook['hook'],
                [$hook['component'], $hook['callback']],
                $hook['priority'],
                $hook['accepted_args']
            );
        }

        foreach ($this->actions as $hook) {
            add_action(
                $hook['hook'],
                [$hook['component'], $hook['callback']],
                $hook['priority'],
                $hook['accepted_args']
            );
        }
    }

    /**
     * Add rental fields to WooCommerce product
     */
    public function add_rental_product_fields(): void {
        global $post;

        echo '<div class="options_group wahrb-rental-options">';

        woocommerce_wp_checkbox([
            'id' => '_wahrb_rental_enabled',
            'label' => __('Enable rental', 'wahra-rentals-bookings'),
            'description' => __('Allow rental of this product', 'wahra-rentals-bookings'),
        ]);

        woocommerce_wp_select([
            'id' => '_wahrb_booking_mode',
            'label' => __('Booking mode', 'wahra-rentals-bookings'),
            'options' => [
                'day' => __('Daily rental', 'wahra-rentals-bookings'),
                'slot' => __('Time slot rental', 'wahra-rentals-bookings'),
                'service' => __('One-time service', 'wahra-rentals-bookings'),
            ],
        ]);

        woocommerce_wp_text_input([
            'id' => '_wahrb_base_price',
            'label' => __('Base price', 'wahra-rentals-bookings') . ' (' . get_woocommerce_currency_symbol() . ')',
            'type' => 'number',
            'custom_attributes' => ['step' => '0.01', 'min' => '0'],
        ]);

        woocommerce_wp_text_input([
            'id' => '_wahrb_security_deposit',
            'label' => __('Security deposit', 'wahra-rentals-bookings') . ' (' . get_woocommerce_currency_symbol() . ')',
            'type' => 'number',
            'custom_attributes' => ['step' => '0.01', 'min' => '0'],
            'description' => __('Security deposit amount (optional)', 'wahra-rentals-bookings'),
        ]);

        woocommerce_wp_text_input([
            'id' => '_wahrb_total_units',
            'label' => __('Available units', 'wahra-rentals-bookings'),
            'type' => 'number',
            'custom_attributes' => ['step' => '1', 'min' => '1'],
            'value' => get_post_meta($post->ID, '_wahrb_total_units', true) ?: 1,
        ]);

        woocommerce_wp_text_input([
            'id' => '_wahrb_min_duration',
            'label' => __('Minimum duration (days)', 'wahra-rentals-bookings'),
            'type' => 'number',
            'custom_attributes' => ['step' => '1', 'min' => '1'],
            'value' => get_post_meta($post->ID, '_wahrb_min_duration', true) ?: 1,
        ]);

        woocommerce_wp_text_input([
            'id' => '_wahrb_max_duration',
            'label' => __('Maximum duration (days)', 'wahra-rentals-bookings'),
            'type' => 'number',
            'custom_attributes' => ['step' => '1', 'min' => '1'],
            'value' => get_post_meta($post->ID, '_wahrb_max_duration', true) ?: 365,
        ]);

        echo '</div>';
    }

    /**
     * Save rental product fields
     *
     * @param int $post_id Product ID
     */
    public function save_rental_product_fields(int $post_id): void {
        $fields = [
            '_wahrb_rental_enabled' => 'checkbox',
            '_wahrb_booking_mode' => 'select',
            '_wahrb_base_price' => 'decimal',
            '_wahrb_security_deposit' => 'decimal',
            '_wahrb_total_units' => 'int',
            '_wahrb_min_duration' => 'int',
            '_wahrb_max_duration' => 'int',
        ];

        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce in woocommerce_process_product_meta hook
        foreach ($fields as $field => $type) {
            if ($type === 'checkbox') {
                // phpcs:ignore WordPress.Security.NonceVerification.Missing
                $value = isset($_POST[$field]) ? 'yes' : 'no';
            } elseif ($type === 'decimal') {
                // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
                $value = isset($_POST[$field]) ? wc_format_decimal(sanitize_text_field(wp_unslash($_POST[$field]))) : '';
            } elseif ($type === 'int') {
                // phpcs:ignore WordPress.Security.NonceVerification.Missing
                $value = isset($_POST[$field]) ? absint(wp_unslash($_POST[$field])) : '';
            } else {
                // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
                $value = isset($_POST[$field]) ? sanitize_text_field(wp_unslash($_POST[$field])) : '';
            }

            update_post_meta($post_id, $field, $value);
        }
    }

    /**
     * Hide "Add to cart" button on rental products when setting is enabled.
     *
     * @param bool        $purchasable Whether the product is purchasable.
     * @param \WC_Product $product     The product object.
     * @return bool
     */
    public function maybe_hide_add_to_cart_rental(bool $purchasable, $product): bool {
        if (!$purchasable || !$product) {
            return $purchasable;
        }

        // Only act on single product pages (don't affect cart/checkout/API)
        if (!is_product()) {
            return $purchasable;
        }

        $booking_settings = get_option('wahrb_settings_booking', []);
        if (empty($booking_settings['hide_add_to_cart_rental'])) {
            return $purchasable;
        }

        // Check if this product has rental enabled
        if (get_post_meta($product->get_id(), '_wahrb_rental_enabled', true) === 'yes') {
            return false;
        }

        return $purchasable;
    }

    /**
     * Display rental calendar on product page
     */
    public function display_rental_calendar(): void {
        global $product;

        if (!$product || get_post_meta($product->get_id(), '_wahrb_rental_enabled', true) !== 'yes') {
            return;
        }

        // Enqueue Flatpickr (local vendor files)
        wp_enqueue_style('flatpickr', WAHRB_PLUGIN_URL . 'assets/vendor/flatpickr/flatpickr.min.css', [], '4.6.13');
        wp_enqueue_script('flatpickr', WAHRB_PLUGIN_URL . 'assets/vendor/flatpickr/flatpickr.min.js', [], '4.6.13', true);
        wp_enqueue_script('flatpickr-fr', WAHRB_PLUGIN_URL . 'assets/vendor/flatpickr/l10n/fr.js', ['flatpickr'], '4.6.13', true);

        // Enqueue intl-tel-input for phone country selector (local vendor files)
        wp_enqueue_style('intl-tel-input', WAHRB_PLUGIN_URL . 'assets/vendor/intl-tel-input/intlTelInput.min.css', [], '25.3.1');
        wp_enqueue_script('intl-tel-input', WAHRB_PLUGIN_URL . 'assets/vendor/intl-tel-input/intlTelInput.min.js', [], '25.3.1', true);

        // Enqueue calendar assets
        wp_enqueue_style('wahrb-calendar-styles', WAHRB_PLUGIN_URL . 'assets/css/wahrb-calendar.css', ['flatpickr', 'intl-tel-input'], WAHRB_VERSION);
        wp_enqueue_script('wahrb-calendar-script', WAHRB_PLUGIN_URL . 'assets/js/wahrb-calendar.js', ['jquery', 'flatpickr', 'flatpickr-fr', 'intl-tel-input'], WAHRB_VERSION, true);

        // Get general settings for date/time format and currency
        $general_settings = get_option('wahrb_settings_general', []);
        $date_format = $general_settings['date_format'] ?? 'Y-m-d';
        $time_format = $general_settings['time_format'] ?? '24h';
        $currency_symbol = !empty($general_settings['currency_symbol']) ? $general_settings['currency_symbol'] : html_entity_decode(get_woocommerce_currency_symbol(), ENT_QUOTES, 'UTF-8');
        $currency_position = $general_settings['currency_position'] ?? 'before';

        // Convert PHP date format to Flatpickr format
        $flatpickr_formats = [
            'Y-m-d' => 'Y-m-d',
            'd/m/Y' => 'd/m/Y',
            'm/d/Y' => 'm/d/Y',
            'd-m-Y' => 'd-m-Y',
            'd.m.Y' => 'd.m.Y',
        ];
        $flatpickr_date_format = $flatpickr_formats[$date_format] ?? 'Y-m-d';

        // Get booking mode for this product
        $booking_mode = get_post_meta($product->get_id(), '_wahrb_booking_mode', true) ?: 'day';

        wp_localize_script('wahrb-calendar-script', 'wahrbCalendarConfig', [
            'apiUrl' => rest_url('wahrb/v1'),
            'nonce' => wp_create_nonce('wp_rest'),
            'productId' => $product->get_id(),
            'bookingMode' => $booking_mode, // day, slot, or service
            'currency' => get_woocommerce_currency(),
            'currencySymbol' => $currency_symbol,
            'currencyPosition' => $currency_position,
            'dateFormat' => $flatpickr_date_format,
            'timeFormat' => $time_format,
            'locale' => substr(determine_locale(), 0, 2), // Works for logged-out users too
            'i18n' => [
                'loadingSlots' => __('Loading available slots...', 'wahra-rentals-bookings'),
                'noSlots' => __('No slots available for this date', 'wahra-rentals-bookings'),
                'errorLoading' => __('Error loading slots', 'wahra-rentals-bookings'),
                'spots' => __('spots', 'wahra-rentals-bookings'),
            ],
            'strings' => [
                'selectDates' => __('Select your dates', 'wahra-rentals-bookings'),
                'startDate' => __('Start date', 'wahra-rentals-bookings'),
                'endDate' => __('End date', 'wahra-rentals-bookings'),
                'checkAvailability' => __('Check availability', 'wahra-rentals-bookings'),
                'addToCart' => __('Add to cart', 'wahra-rentals-bookings'),
                'unavailable' => __('Unavailable', 'wahra-rentals-bookings'),
                'available' => __('Available', 'wahra-rentals-bookings'),
                // Error messages
                'minBookingWindow' => __('Minimum 24h advance booking required', 'wahra-rentals-bookings'),
                'maxBookingWindow' => __('Date too far in the future', 'wahra-rentals-bookings'),
                'minDuration' => __('Minimum duration not met', 'wahra-rentals-bookings'),
                'maxDuration' => __('Maximum duration exceeded', 'wahra-rentals-bookings'),
                'noUnits' => __('No more units available', 'wahra-rentals-bookings'),
                'overlap' => __('These dates are already booked', 'wahra-rentals-bookings'),
                'blackout' => __('These dates are not available', 'wahra-rentals-bookings'),
                // Validation messages for booking form
                'nameRequired' => __('Name is required', 'wahra-rentals-bookings'),
                'nameLettersOnly' => __('Name must contain only letters (no numbers)', 'wahra-rentals-bookings'),
                'nameMinLength' => __('Name must be at least 2 characters', 'wahra-rentals-bookings'),
                'emailRequired' => __('Email is required', 'wahra-rentals-bookings'),
                'emailInvalid' => __('Invalid email format (e.g. name@email.com)', 'wahra-rentals-bookings'),
                'phoneInvalid' => __('Invalid phone number for this country', 'wahra-rentals-bookings'),
                'phoneFormatInvalid' => __('Invalid phone format', 'wahra-rentals-bookings'),
                'selectDatesFirst' => __('Please select dates first.', 'wahra-rentals-bookings'),
                'acceptTerms' => __('Please accept the booking terms and conditions.', 'wahra-rentals-bookings'),
                'sending' => __('Sending...', 'wahra-rentals-bookings'),
                'errorOccurred' => __('An error occurred. Please try again.', 'wahra-rentals-bookings'),
                'submitButton' => __('Send request', 'wahra-rentals-bookings'),
            ],
            'siteUrl' => home_url(),
            'pluginUrl' => WAHRB_PLUGIN_URL,
            'cartUrl' => wc_get_cart_url(),
            // Vendor color customization
            'vendorColors' => $this->get_vendor_colors($product->get_id()),
        ]);

        // Inject CSS custom properties for vendor colors if set
        $vendor_colors = $this->get_vendor_colors($product->get_id());
        if (!empty($vendor_colors['headerColor']) || !empty($vendor_colors['buttonColor'])) {
            wp_add_inline_style('wahrb-calendar-styles', wp_strip_all_tags($this->generate_vendor_color_css($vendor_colors)));
        }

        // Load template
        include WAHRB_PLUGIN_DIR . 'templates/product-calendar.php';
    }

    /**
     * Get vendor colors for booking modal
     *
     * @param int $product_id Product ID
     * @return array
     */
    private function get_vendor_colors(int $product_id): array {
        $vendor_id = (int) get_post_field('post_author', $product_id);
        $vendor_settings = get_user_meta($vendor_id, '_wahrb_vendor_settings', true) ?: [];

        return [
            'headerColor' => $vendor_settings['modal_header_color'] ?? '#2563eb',
            'buttonColor' => $vendor_settings['modal_button_color'] ?? '#2563eb',
            'textColor' => $vendor_settings['modal_text_color'] ?? '#ffffff',
        ];
    }

    /**
     * Generate CSS for vendor colors
     *
     * @param array $colors Vendor colors
     * @return string CSS
     */
    private function generate_vendor_color_css(array $colors): string {
        return sprintf('
            /* Vendor Custom Colors - Generated by vendor settings */
            
            /* Modal header styling */
            #wahrb-booking-modal .wahrb-modal-top,
            .wahrb-modal .wahrb-modal-top,
            .wahrb-booking-form .wahrb-modal-top { 
                background: %s !important; 
                background-color: %s !important;
                color: %s !important; 
            }
            
            #wahrb-booking-modal .wahrb-modal-top h3,
            #wahrb-booking-modal .wahrb-modal-top p,
            #wahrb-booking-modal .wahrb-modal-top span,
            .wahrb-modal .wahrb-modal-top h3,
            .wahrb-modal .wahrb-modal-top p { 
                color: %s !important; 
            }
            
            /* Primary buttons */
            #wahrb-booking-modal .wahrb-btn-primary,
            #wahrb-booking-modal .wahrb-btn-next,
            #wahrb-booking-modal .wahrb-btn-submit,
            #wahrb-booking-modal button.wahrb-btn-primary,
            .wahrb-modal .wahrb-btn-primary,
            .wahrb-modal .wahrb-btn-next,
            .wahrb-modal .wahrb-btn-submit { 
                background-color: %s !important; 
                background: %s !important;
                color: %s !important; 
                border-color: %s !important; 
            }
            
            /* Button hover states */
            #wahrb-booking-modal .wahrb-btn-primary:hover,
            #wahrb-booking-modal .wahrb-btn-next:hover,
            #wahrb-booking-modal .wahrb-btn-submit:hover,
            .wahrb-modal .wahrb-btn-primary:hover,
            .wahrb-modal .wahrb-btn-next:hover,
            .wahrb-modal .wahrb-btn-submit:hover {
                opacity: 0.9 !important;
                background-color: %s !important;
                color: %s !important;
            }
        ',
            $colors['headerColor'], $colors['headerColor'], $colors['textColor'],  // Modal top
            $colors['textColor'],  // Modal top text elements
            $colors['buttonColor'], $colors['buttonColor'], $colors['textColor'], $colors['buttonColor'],  // Primary buttons
            $colors['buttonColor'], $colors['textColor']  // Button hover
        );
    }

    /**
     * Handle order completed
     *
     * @param int $order_id Order ID
     */
    public function on_order_completed(int $order_id): void {
        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        $booking_id = $order->get_meta('_wahrb_booking_id');
        if (!$booking_id) {
            return;
        }

        // Update booking status
        $booking = new WAHRB_Booking($booking_id);
        if ($booking->exists()) {
            $order_type = $order->get_meta('_wahrb_order_type');

            if ($order_type === 'deposit') {
                $booking->confirm();
                // Create balance order if needed
                WAHRB_Balance_Handler::maybe_create_balance_order($booking);
            } elseif ($order_type === 'balance') {
                $booking->mark_balance_paid();
            }
        }
    }

    /**
     * Handle order processing
     *
     * @param int $order_id Order ID
     */
    public function on_order_processing(int $order_id): void {
        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        $booking_id = $order->get_meta('_wahrb_booking_id');
        if (!$booking_id) {
            return;
        }

        // Check if COD payment
        if ($order->get_payment_method() === 'cod') {
            $booking = new WAHRB_Booking($booking_id);
            if ($booking->exists()) {
                $booking->update_status('pending');
            }
        }
    }

    /**
     * Handle order cancelled
     *
     * @param int $order_id Order ID
     */
    public function on_order_cancelled(int $order_id): void {
        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        $booking_id = $order->get_meta('_wahrb_booking_id');
        if (!$booking_id) {
            return;
        }

        $booking = new WAHRB_Booking($booking_id);
        if ($booking->exists() && $booking->get_status() !== 'cancelled') {
            $booking->cancel(__('Order cancelled', 'wahra-rentals-bookings'));
        }
    }

    /**
     * Handle order refunded
     *
     * @param int $order_id Order ID
     */
    public function on_order_refunded(int $order_id): void {
        $order = wc_get_order($order_id);
        if (!$order) {
            return;
        }

        $booking_id = $order->get_meta('_wahrb_booking_id');
        if (!$booking_id) {
            return;
        }

        // Log refund
        WAHRB_Database::instance()->log('order_refunded', 'booking', $booking_id, [
            'order_id' => $order_id,
            'refund_amount' => $order->get_total_refunded(),
        ]);
    }

    /**
     * Add booking data to cart item
     *
     * @param array $cart_item_data Cart item data
     * @param int $product_id Product ID
     * @param int $variation_id Variation ID
     * @return array Modified cart item data
     */
    public function add_booking_data_to_cart(array $cart_item_data, int $product_id, int $variation_id): array {
        // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce verified by WooCommerce add-to-cart handler
        if (isset($_POST['wahrb_start_date']) && isset($_POST['wahrb_end_date'])) {
            $cart_item_data['wahrb_booking'] = [
                // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
                'start_date' => sanitize_text_field(wp_unslash($_POST['wahrb_start_date'])),
                // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
                'end_date' => sanitize_text_field(wp_unslash($_POST['wahrb_end_date'])),
                // phpcs:ignore WordPress.Security.NonceVerification.Missing
                'qty' => isset($_POST['wahrb_qty']) ? absint(wp_unslash($_POST['wahrb_qty'])) : 1,
            ];

            // Create hold
            $hold = WAHRB_Hold::create([
                'product_id' => $product_id,
                'variation_id' => $variation_id ?: null,
                'start_dt' => $cart_item_data['wahrb_booking']['start_date'],
                'end_dt' => $cart_item_data['wahrb_booking']['end_date'],
                'qty' => $cart_item_data['wahrb_booking']['qty'],
            ]);

            if ($hold) {
                $cart_item_data['wahrb_booking']['hold_id'] = $hold->get_id();
            }

            $cart_item_data['unique_key'] = md5(microtime() . wp_rand());
        }

        return $cart_item_data;
    }

    /**
     * Display booking data in cart
     *
     * @param array $item_data Item data to display
     * @param array $cart_item Cart item
     * @return array Modified item data
     */
    public function display_booking_data_in_cart(array $item_data, array $cart_item): array {
        if (!empty($cart_item['wahrb_booking'])) {
            $booking = $cart_item['wahrb_booking'];

            $item_data[] = [
                'key' => __('Start date', 'wahra-rentals-bookings'),
                'value' => date_i18n(get_option('date_format'), strtotime($booking['start_date'])),
            ];

            $item_data[] = [
                'key' => __('End date', 'wahra-rentals-bookings'),
                'value' => date_i18n(get_option('date_format'), strtotime($booking['end_date'])),
            ];
        }

        return $item_data;
    }

    /**
     * Save booking data to order item
     *
     * @param WC_Order_Item_Product $item Order item
     * @param string $cart_item_key Cart item key
     * @param array $values Cart item values
     * @param WC_Order $order Order object
     */
    public function save_booking_data_to_order_item($item, string $cart_item_key, array $values, $order): void {
        if (!empty($values['wahrb_booking'])) {
            $booking = $values['wahrb_booking'];

            $item->add_meta_data('_wahrb_start_date', $booking['start_date']);
            $item->add_meta_data('_wahrb_end_date', $booking['end_date']);
            $item->add_meta_data('_wahrb_qty', $booking['qty']);

            if (!empty($booking['hold_id'])) {
                $item->add_meta_data('_wahrb_hold_id', $booking['hold_id']);
            }
        }
    }

    /**
     * Add admin menu (top-level with submenus)
     */
    public function add_admin_menu(): void {
        // Top-level menu: Wahra Bookings
        add_menu_page(
            __('Wahra Bookings', 'wahra-rentals-bookings'),
            __('Wahra Bookings', 'wahra-rentals-bookings'),
            'manage_woocommerce',
            'bookings-wahra',
            [$this, 'render_admin_page'],
            'dashicons-calendar-alt',
            56 // After WooCommerce (55.5)
        );

        // Submenu: Bookings (same as parent to rename first item)
        add_submenu_page(
            'bookings-wahra',
            __('Wahra Bookings', 'wahra-rentals-bookings'),
            __('Bookings', 'wahra-rentals-bookings'),
            'manage_woocommerce',
            'bookings-wahra',
            [$this, 'render_admin_page']
        );

        // Submenu: Settings
        add_submenu_page(
            'bookings-wahra',
            __('Wahra Settings', 'wahra-rentals-bookings'),
            __('Settings', 'wahra-rentals-bookings'),
            'manage_woocommerce',
            'bookings-wahra-settings',
            [$this, 'render_settings_page']
        );

        // Submenu: Analytics
        add_submenu_page(
            'bookings-wahra',
            __('Wahra Analytics', 'wahra-rentals-bookings'),
            __('Analytics', 'wahra-rentals-bookings'),
            'manage_woocommerce',
            'bookings-wahra-analytics',
            [$this, 'render_analytics_page']
        );

        // Hidden submenu: Booking Detail (not shown in menu)
        add_submenu_page(
            null, // No parent — hidden page
            __('Booking Detail', 'wahra-rentals-bookings'),
            '',
            'manage_woocommerce',
            'bookings-wahra-detail',
            [$this, 'render_admin_booking_detail_page']
        );
    }

    /**
     * Render analytics page
     */
    public function render_analytics_page(): void {
        wp_enqueue_style(
            'wahrb-admin-analytics',
            WAHRB_PLUGIN_URL . 'assets/css/wahrb-admin-analytics.css',
            [],
            WAHRB_VERSION
        );
        wp_enqueue_script(
            'chartjs',
            WAHRB_PLUGIN_URL . 'assets/vendor/chartjs/chart.min.js',
            [],
            '4.5.1',
            true
        );
        include WAHRB_PLUGIN_DIR . 'templates/admin/analytics.php';
    }

    /**
     * Clear stats transients when a booking is created
     *
     * @param int   $booking_id  Booking ID
     * @param array $booking_data Booking data
     */
    public function clear_stats_cache($booking_id, $booking_data): void {
        $vendor_id = absint($booking_data['vendor_id'] ?? 0);
        if ($vendor_id) {
            $this->delete_stats_transients($vendor_id);
        }
    }

    /**
     * Clear stats transients when a booking status changes
     *
     * @param int    $booking_id Booking ID
     * @param string $old_status Previous status
     * @param string $new_status New status
     */
    public function clear_stats_cache_on_status($booking_id, $old_status, $new_status): void {
        global $wpdb;
        $db = WAHRB_Database::instance();
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter -- Custom table
        $vendor_id = (int) $wpdb->get_var($wpdb->prepare("SELECT vendor_id FROM {$db->table('bookings')} WHERE booking_id = %d", $booking_id));
        if ($vendor_id) {
            $this->delete_stats_transients($vendor_id);
        }
    }

    /**
     * Delete all stats transients for a vendor
     *
     * @param int $vendor_id Vendor ID
     */
    private function delete_stats_transients(int $vendor_id): void {
        $periods = ['week', 'month', 'quarter', 'year'];
        foreach ($periods as $period) {
            delete_transient("wahrb_stats_{$vendor_id}_{$period}");
            delete_transient("wahrb_admin_stats_{$period}");
        }
    }

    /**
     * Register settings
     */
    public function register_settings(): void {
        register_setting('wahrb_settings_group', 'wahrb_settings_general', [
            'type' => 'array',
            'sanitize_callback' => [$this, 'sanitize_settings_array'],
        ]);
        register_setting('wahrb_settings_group', 'wahrb_settings_booking', [
            'type' => 'array',
            'sanitize_callback' => [$this, 'sanitize_settings_array'],
        ]);
        register_setting('wahrb_settings_group', 'wahrb_settings_payment', [
            'type' => 'array',
            'sanitize_callback' => [$this, 'sanitize_settings_array'],
        ]);
        register_setting('wahrb_settings_group', 'wahrb_settings_cancellation', [
            'type' => 'array',
            'sanitize_callback' => [$this, 'sanitize_settings_array'],
        ]);
        register_setting('wahrb_settings_group', 'wahrb_settings_emails', [
            'type' => 'array',
            'sanitize_callback' => [$this, 'sanitize_settings_array'],
        ]);
    }

    /**
     * Sanitize settings array
     *
     * @param mixed $input Input value
     * @return array Sanitized array
     */
    public function sanitize_settings_array($input): array {
        if (!is_array($input)) {
            return [];
        }

        $sanitized = [];
        foreach ($input as $key => $value) {
            $key = sanitize_key($key);
            if (is_array($value)) {
                $sanitized[$key] = $this->sanitize_settings_array($value);
            } elseif (is_bool($value)) {
                $sanitized[$key] = (bool) $value;
            } elseif (is_numeric($value)) {
                $sanitized[$key] = is_float($value + 0) ? (float) $value : (int) $value;
            } else {
                $sanitized[$key] = sanitize_text_field($value);
            }
        }

        return $sanitized;
    }

    /**
     * Render admin page
     */
    public function render_admin_page(): void {
        include WAHRB_PLUGIN_DIR . 'templates/admin/bookings.php';
    }

    /**
     * Render admin booking detail page
     */
    public function render_admin_booking_detail_page(): void {
        include WAHRB_PLUGIN_DIR . 'templates/admin/booking-detail.php';
    }

    /**
     * Render settings page
     */
    public function render_settings_page(): void {
        include WAHRB_PLUGIN_DIR . 'templates/admin/settings.php';
    }

    /**
     * AJAX handler for availability check
     *
     * Note: This is intentionally a public action (available to logged-in and non-logged-in users)
     * as it only returns publicly visible availability data for a product.
     * Nonce verification is used to prevent CSRF attacks.
     */
    public function ajax_get_availability(): void {
        // Verify nonce for CSRF protection
        check_ajax_referer('wahrb_availability_nonce', 'nonce');

        // Minimal capability check for logged-in users (all authenticated users can read)
        // This is a public read-only action, but we verify the user is authenticated
        // Note: wp_ajax_nopriv_ handler allows non-logged-in users
        if (is_user_logged_in() && !current_user_can('read')) {
            wp_send_json_error(['message' => __('Permission denied', 'wahra-rentals-bookings')]);
        }

        $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
        $start_date = isset($_POST['start_date']) ? sanitize_text_field(wp_unslash($_POST['start_date'])) : '';
        $end_date = isset($_POST['end_date']) ? sanitize_text_field(wp_unslash($_POST['end_date'])) : '';

        if (!$product_id || !$start_date || !$end_date) {
            wp_send_json_error(['message' => __('Missing parameters', 'wahra-rentals-bookings')]);
        }

        $availability = WAHRB_Availability::check($product_id, $start_date, $end_date);

        wp_send_json_success($availability);
    }
}
