<?php

if (!defined('ABSPATH')) {
    exit;
}

function chbk_register_shortcodes()
{
    add_shortcode('chbk_trip_search', 'chbk_shortcode_trip_search');
    add_shortcode('chbk_booking_form', 'chbk_shortcode_booking_form');
    add_filter('the_content', 'chbk_append_booking_form_to_trip_content', 20);
}

function chbk_append_booking_form_to_trip_content($content)
{
    if (is_admin() || !is_singular('chbk_trip') || !in_the_loop() || !is_main_query()) {
        return $content;
    }

    if (!is_string($content)) {
        return $content;
    }

    if (!empty($GLOBALS['chbk_booking_form_rendered']) || strpos($content, 'chbk-booking-shell') !== false) {
        return $content;
    }

    if (function_exists('has_shortcode') && has_shortcode($content, 'chbk_booking_form')) {
        return $content;
    }

    $trip_id = get_the_ID();
    if ($trip_id < 1 || get_post_type($trip_id) !== 'chbk_trip') {
        return $content;
    }

    $form_html = chbk_shortcode_booking_form(['trip_id' => (int) $trip_id]);
    if (!is_string($form_html) || trim($form_html) === '') {
        return $content;
    }

    return $content . "\n\n" . $form_html;
}

function chbk_get_trip_type_label($trip_type)
{
    $trip_type = (string) $trip_type;
    if ($trip_type === 'private' || $trip_type === '' || $trip_type === 'per-group') {
        return 'Per Group';
    }
    if ($trip_type === 'per-seat') {
        return 'Per Seat';
    }
    if ($trip_type === 'hybrid') {
        return 'Hybrid';
    }
    return ucfirst(str_replace('-', ' ', $trip_type));
}

function chbk_format_trip_duration_label($minutes)
{
    $minutes = max(0, (int) $minutes);
    $hours = (int) floor($minutes / 60);
    $remaining_minutes = $minutes % 60;
    $parts = [];

    if ($hours > 0) {
        $parts[] = $hours . ' hour' . ($hours === 1 ? '' : 's');
    }
    if ($remaining_minutes > 0 || empty($parts)) {
        $parts[] = $remaining_minutes . ' minute' . ($remaining_minutes === 1 ? '' : 's');
    }

    return implode(', ', $parts);
}

function chbk_format_trip_days_label($weekdays_csv)
{
    $days = function_exists('chbk_parse_weekdays_csv') ? chbk_parse_weekdays_csv($weekdays_csv) : [];
    if (empty($days)) {
        return 'Not specified';
    }

    if (count($days) === 7) {
        return 'Every day';
    }

    $labels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    $names = [];
    foreach ($days as $day) {
        if (isset($labels[$day])) {
            $names[] = $labels[$day];
        }
    }

    return empty($names) ? 'Not specified' : implode(', ', $names);
}

function chbk_shortcode_trip_search($atts)
{
    $atts = shortcode_atts([
        'limit' => 20,
    ], $atts, 'chbk_trip_search');
    wp_enqueue_style('chbk-frontend-ui');
    $book_now_label = trim((string) chbk_get_setting('trip_card_book_now_label', 'Book Now'));
    if ($book_now_label === '') {
        $book_now_label = 'Book Now';
    }

    $query = new WP_Query([
        'post_type' => 'chbk_trip',
        'post_status' => 'publish',
        'posts_per_page' => (int) $atts['limit'],
        'orderby' => 'title',
        'order' => 'ASC',
    ]);

    ob_start();
    echo '<div class="chbk-trip-listings">';

    if ($query->have_posts()) {
        while ($query->have_posts()) {
            $query->the_post();
            $trip_id = get_the_ID();
            $base_price = (float) get_post_meta($trip_id, 'chbk_base_price', true);
            $currency = (string) chbk_get_setting('currency', 'USD');
            $price_display = chbk_format_currency_display($base_price, $currency);
            $permalink = get_permalink($trip_id);
            $duration_minutes = (int) chbk_get_trip_duration_minutes($trip_id);
            $duration_label = chbk_format_trip_duration_label($duration_minutes);
            $start_time = (string) get_post_meta($trip_id, 'chbk_schedule_start_time', true);
            if ($start_time === '') {
                $start_time = '08:00';
            }
            $start_time_label = $start_time;
            try {
                $start_dt = new DateTime($start_time);
                $start_time_label = $start_dt->format('g:i A');
            } catch (Exception $e) {
            }
            $trip_days_label = chbk_format_trip_days_label((string) get_post_meta($trip_id, 'chbk_schedule_weekdays', true));
            $description = wp_strip_all_tags(get_the_excerpt());
            if ($description === '') {
                $description = wp_trim_words(get_the_content(null, false, $trip_id), 32);
            }
            $min_party = (int) chbk_get_trip_min_capacity($trip_id);
            $max_party = (int) chbk_get_trip_capacity($trip_id);
            $children_not_allowed = (int) get_post_meta($trip_id, 'chbk_children_not_allowed', true) === 1;
            $trip_bookable = function_exists('chbk_is_trip_bookable') ? chbk_is_trip_bookable($trip_id) : true;

            echo '<article class="chbk-trip-card">';
            if (has_post_thumbnail($trip_id)) {
                echo '<a class="chbk-trip-card-image-link" href="' . esc_url($permalink) . '">';
                echo get_the_post_thumbnail($trip_id, 'large', ['class' => 'chbk-trip-card-image', 'loading' => 'lazy']);
                echo '</a>';
            }
            echo '<h3 class="chbk-trip-card-title"><a href="' . esc_url($permalink) . '">' . esc_html(get_the_title()) . '</a></h3>';
            echo '<p class="chbk-trip-card-description">' . esc_html($description) . '</p>';
            echo '<dl class="chbk-trip-card-meta">';
            echo '<div><dt>Starting Time</dt><dd>' . esc_html($start_time_label) . '</dd></div>';
            echo '<div><dt>Trip Days</dt><dd>' . esc_html($trip_days_label) . '</dd></div>';
            echo '<div><dt>Duration</dt><dd>' . esc_html($duration_label) . '</dd></div>';
            echo '<div><dt>Pricing</dt><dd>Starting at ' . esc_html($price_display) . '</dd></div>';
            if ($max_party > 0) {
                echo '<div><dt>Party Size</dt><dd>' . esc_html((string) $min_party) . ' to ' . esc_html((string) $max_party) . ' guests</dd></div>';
            } else {
                echo '<div><dt>Party Size</dt><dd>' . esc_html((string) $min_party) . '+ guests</dd></div>';
            }
            if ($children_not_allowed) {
                echo '<div><dt>Ages</dt><dd>Adults only (children not allowed)</dd></div>';
            }
            echo '</dl>';
            echo '<div class="chbk-trip-card-actions">';
            echo '<p class="chbk-trip-card-price">' . esc_html($price_display) . '</p>';
            echo '<div class="chbk-trip-card-action-buttons">';
            if ($trip_bookable) {
                echo '<a class="chbk-trip-card-button chbk-trip-card-button-primary" href="' . esc_url($permalink) . '">' . esc_html($book_now_label) . '</a>';
            } else {
                echo '<span class="chbk-trip-card-button chbk-trip-card-button-disabled" aria-disabled="true">Unavailable</span>';
            }
            echo '</div>';
            echo '</div>';
            echo '</article>';
        }
        wp_reset_postdata();
    } else {
        echo '<p class="chbk-trip-listings-empty">No trips found.</p>';
    }

    echo '</div>';
    return ob_get_clean();
}

function chbk_shortcode_booking_form($atts)
{
    $atts = shortcode_atts([
        'trip_id' => 0,
    ], $atts, 'chbk_booking_form');

    $trip_id = (int) $atts['trip_id'];
    if ($trip_id < 1) {
        $context_trip_id = get_queried_object_id();
        if ($context_trip_id > 0 && get_post_type($context_trip_id) === 'chbk_trip') {
            $trip_id = (int) $context_trip_id;
        }
    }
    if (!$trip_id) {
        return '<p>Trip not configured.</p>';
    }
    $GLOBALS['chbk_booking_form_rendered'] = true;
    wp_enqueue_style('chbk-frontend-ui');

    $errors = [];
    $created_booking = 0;
    $pending_redirect_url = '';
    $selected_slot = '';
    $selected_party_size = 0;
    $selected_customer_name = '';
    $selected_customer_email = '';
    $selected_gateway = 'stripe';
    // phpcs:disable WordPress.Security.NonceVerification.Missing -- Used only to detect intended submission target; nonce is verified before processing.
    $submitted_trip_id = isset($_POST['chbk_trip_id']) ? absint($_POST['chbk_trip_id']) : 0;
    $submitted_nonce = isset($_POST['chbk_booking_nonce']) ? sanitize_text_field(wp_unslash($_POST['chbk_booking_nonce'])) : '';
    // phpcs:enable WordPress.Security.NonceVerification.Missing
    $is_submission_for_this_trip = $submitted_nonce !== '' && $submitted_trip_id === $trip_id;
    $trip_bookable = function_exists('chbk_is_trip_bookable') ? chbk_is_trip_bookable($trip_id) : true;
    $online_payment_required = chbk_trip_requires_online_payment($trip_id);

    $checkout_result = chbk_consume_frontend_checkout_result($trip_id);
    if (is_array($checkout_result)) {
        if (!empty($checkout_result['error'])) {
            $errors[] = (string) $checkout_result['error'];
        } elseif (!empty($checkout_result['booking_id'])) {
            $created_booking = (int) $checkout_result['booking_id'];
        }
    }

    if ($is_submission_for_this_trip) {
        if (!$trip_bookable) {
            $errors[] = 'Booking is currently unavailable for this trip.';
        } elseif (!wp_verify_nonce($submitted_nonce, 'chbk_submit_booking_' . $trip_id)) {
            $errors[] = 'Invalid submission. Please refresh and try again.';
        } else {
            $selected_slot = isset($_POST['chbk_trip_slot']) ? sanitize_text_field(wp_unslash($_POST['chbk_trip_slot'])) : '';
            $selected_party_size = isset($_POST['chbk_party_size']) ? absint($_POST['chbk_party_size']) : 0;
            $selected_customer_name = isset($_POST['chbk_customer_name']) ? sanitize_text_field(wp_unslash($_POST['chbk_customer_name'])) : '';
            $selected_customer_email = isset($_POST['chbk_customer_email']) ? sanitize_email(wp_unslash($_POST['chbk_customer_email'])) : '';
            $selected_gateway = isset($_POST['chbk_checkout_gateway']) ? sanitize_key(wp_unslash($_POST['chbk_checkout_gateway'])) : 'stripe';

            $trip_datetime = $selected_slot;
            if ($trip_datetime === '') {
                $trip_datetime = chbk_build_trip_datetime_from_request(
                    isset($_POST['chbk_trip_date']) ? sanitize_text_field(wp_unslash($_POST['chbk_trip_date'])) : '',
                    isset($_POST['chbk_trip_time']) ? sanitize_text_field(wp_unslash($_POST['chbk_trip_time'])) : '',
                    isset($_POST['chbk_trip_datetime']) ? sanitize_text_field(wp_unslash($_POST['chbk_trip_datetime'])) : ''
                );
            }

            $args = [
                'trip_id' => $trip_id,
                'party_size' => isset($_POST['chbk_party_size']) ? absint($_POST['chbk_party_size']) : 1,
                'trip_datetime' => $trip_datetime,
                'customer_name' => $selected_customer_name,
                'customer_email' => $selected_customer_email,
            ];

            if ($online_payment_required) {
                $started = chbk_start_frontend_checkout($trip_id, $args, $selected_gateway);
                if (is_wp_error($started)) {
                    $errors[] = $started->get_error_message();
                } else {
                    $pending_redirect_url = isset($started['redirect_url']) ? esc_url_raw((string) $started['redirect_url']) : '';
                    if ($pending_redirect_url !== '' && !headers_sent()) {
                        chbk_redirect_to_checkout_url($pending_redirect_url);
                        exit;
                    }
                }
            } else {
                $created = chbk_create_booking($args);
                if (is_wp_error($created)) {
                    $errors[] = $created->get_error_message();
                } else {
                    $created_booking = (int) $created;
                }
            }
        }
    }

    ob_start();

    echo '<div class="chbk-booking-shell">';
    if (!$trip_bookable) {
        echo '<div class="chbk-booking-notice chbk-booking-notice-warning"><strong>Booking unavailable:</strong> this trip is currently inactive or assigned resources are inactive.</div>';
    }
    if ($created_booking) {
        $payment_status = (string) get_post_meta($created_booking, 'chbk_payment_status', true);
        echo '<div class="chbk-booking-notice chbk-booking-notice-success"><strong>Booking created:</strong> #' . esc_html((string) $created_booking) . '. Payment Status: ' . esc_html(chbk_humanize_slug($payment_status)) . '.</div>';
        $payment_message = chbk_get_payment_message_for_trip($trip_id);
        if ($payment_message !== '') {
            echo '<div class="chbk-booking-notice chbk-booking-notice-info chbk-payment-message"><strong>Payment Instructions:</strong> ' . nl2br(esc_html($payment_message)) . '</div>';
        }
    }

    if ($pending_redirect_url !== '') {
        echo '<div class="chbk-booking-notice chbk-booking-notice-info">Redirecting to secure checkout...</div>';
        wp_add_inline_script(
            'chbk-datepicker',
            'window.location.href = ' . wp_json_encode($pending_redirect_url) . ';',
            'after'
        );
    }

    foreach ($errors as $error) {
        echo '<div class="chbk-booking-notice chbk-booking-notice-error">' . esc_html($error) . '</div>';
    }

    $min = chbk_get_trip_min_capacity($trip_id);
    $max = chbk_get_trip_capacity($trip_id);
    if ($selected_party_size < $min) {
        $selected_party_size = $min;
    }
    if ($max > 0 && $selected_party_size > $max) {
        $selected_party_size = $max;
    }

    $trip_type = (string) get_post_meta($trip_id, 'chbk_trip_type', true);
    if ($trip_type === '' || $trip_type === 'private') {
        $trip_type = 'per-group';
    }
    $base_price = (float) get_post_meta($trip_id, 'chbk_base_price', true);
    $seat_price = (float) get_post_meta($trip_id, 'chbk_seat_price', true);
    $included_enabled = (int) get_post_meta($trip_id, 'chbk_included_seats_enabled', true) === 1 ? 1 : 0;
    $included_count = (int) get_post_meta($trip_id, 'chbk_included_seats_count', true);
    if (!$included_enabled || $trip_type !== 'hybrid') {
        $included_count = 0;
    }

    $pricing_rules = chbk_parse_json_meta(get_post_meta($trip_id, 'chbk_pricing_rules', true));
    if ($seat_price <= 0 && isset($pricing_rules['per_person'])) {
        $seat_price = (float) $pricing_rules['per_person'];
    }

    $window_days = (int) get_post_meta($trip_id, 'chbk_booking_window_days', true);
    $slots = $trip_bookable ? chbk_get_trip_available_slots($trip_id, max($min, 1), $window_days > 0 ? $window_days : 90) : [];
    $enabled_gateways = [];
    $online_must_pay_full = (int) get_post_meta($trip_id, 'chbk_online_payment_must_pay_full', true) === 1 ? 1 : 0;
    $online_deposit_amount = (float) get_post_meta($trip_id, 'chbk_online_payment_deposit_amount', true);
    $online_deposit_type = (string) get_post_meta($trip_id, 'chbk_online_payment_deposit_type', true);
    if (!in_array($online_deposit_type, ['fixed', 'percentage'], true)) {
        $online_deposit_type = 'fixed';
    }
    if ($online_payment_required) {
        $enabled_gateways = chbk_get_enabled_checkout_gateways();
    }

    echo '<form method="post" class="chbk-booking-form" data-chbk-trip-type="' . esc_attr($trip_type) . '" data-chbk-base-price="' . esc_attr((string) $base_price) . '" data-chbk-seat-price="' . esc_attr((string) $seat_price) . '" data-chbk-included-seats="' . esc_attr((string) $included_count) . '" data-chbk-currency="' . esc_attr(chbk_get_setting('currency', 'USD')) . '" data-chbk-online-payment-required="' . esc_attr((string) ($online_payment_required ? 1 : 0)) . '" data-chbk-online-must-pay-full="' . esc_attr((string) $online_must_pay_full) . '" data-chbk-online-deposit-type="' . esc_attr($online_deposit_type) . '" data-chbk-online-deposit-amount="' . esc_attr((string) $online_deposit_amount) . '">';
    echo '<input type="hidden" name="chbk_booking_nonce" value="' . esc_attr(wp_create_nonce('chbk_submit_booking_' . $trip_id)) . '">';
    wp_referer_field();
    echo '<input type="hidden" name="chbk_trip_id" value="' . esc_attr((string) $trip_id) . '">';
    echo '<div class="chbk-booking-grid">';
    echo '<label class="chbk-booking-field"><span>Name</span><input type="text" name="chbk_customer_name" value="' . esc_attr($selected_customer_name) . '" required></label>';
    echo '<label class="chbk-booking-field"><span>Email</span><input type="email" name="chbk_customer_email" value="' . esc_attr($selected_customer_email) . '" required></label>';

    if (!empty($slots)) {
        echo '<label class="chbk-booking-field chbk-booking-field-wide"><span>Available Departure</span><select name="chbk_trip_slot" required>';
        echo '<option value="">Select a departure</option>';
        foreach ($slots as $slot) {
            printf('<option value="%s" %s>%s</option>', esc_attr($slot['local']), selected($selected_slot, $slot['local'], false), esc_html($slot['label']));
        }
        echo '</select></label>';
    } else {
        if ($trip_bookable) {
            echo '<div class="chbk-booking-notice chbk-booking-notice-warning"><strong>No available departures currently.</strong></div>';
        }
    }

    if ($max > 0) {
        printf(
            '<label class="chbk-booking-field"><span>Party Size</span><input type="number" min="%1$s" max="%2$s" value="%3$s" name="chbk_party_size" required></label>',
            esc_attr((string) $min),
            esc_attr((string) $max),
            esc_attr((string) $selected_party_size)
        );
    } else {
        printf(
            '<label class="chbk-booking-field"><span>Party Size</span><input type="number" min="%1$s" value="%2$s" name="chbk_party_size" required></label>',
            esc_attr((string) $min),
            esc_attr((string) $selected_party_size)
        );
    }
    echo '</div>';
    echo '<div class="chbk-booking-summary">';
    echo '<p class="chbk-live-price"><strong>Estimated Total</strong> <span class="chbk-live-price-value"></span></p>';
    if ($online_payment_required) {
        $preview_party_size = $selected_party_size > 0 ? $selected_party_size : max($min, 1);
        $preview_trip_datetime = $selected_slot;
        if ($preview_trip_datetime === '' && !empty($slots) && isset($slots[0]['local'])) {
            $preview_trip_datetime = (string) $slots[0]['local'];
        }
        $required_due = chbk_calculate_required_payment_due_now($trip_id, $preview_party_size, $preview_trip_datetime);
        if (is_array($required_due) && empty($required_due['error']) && isset($required_due['amount'])) {
            echo '<p class="chbk-due-at-booking"><strong>Payment Due at Booking</strong> <span class="chbk-due-at-booking-value">' . esc_html(chbk_format_currency_display((float) $required_due['amount'], (string) chbk_get_setting('currency', 'USD'))) . '</span></p>';
        }
    }
    echo '</div>';

    if ($online_payment_required) {
        if (empty($enabled_gateways)) {
            echo '<div class="chbk-booking-notice chbk-booking-notice-error"><strong>Online payments are required for this trip, but no payment gateways are configured.</strong></div>';
        } else {
            $gateway_count = count($enabled_gateways);
            if ($gateway_count === 1) {
                $selected_gateway = (string) key($enabled_gateways);
                reset($enabled_gateways);
            }
            echo '<div class="chbk-booking-actions">';
            if ($gateway_count === 1) {
                $single_label = isset($enabled_gateways[$selected_gateway]) ? (string) $enabled_gateways[$selected_gateway] : chbk_humanize_slug($selected_gateway);
                echo '<input type="hidden" name="chbk_checkout_gateway" value="' . esc_attr($selected_gateway) . '">';
                echo '<span class="chbk-booking-gateway-label">' . esc_html($single_label) . '</span>';
            } else {
                echo '<label class="chbk-booking-field chbk-booking-gateway"><span>Payment Method</span><select name="chbk_checkout_gateway" required>';
                foreach ($enabled_gateways as $gateway_key => $gateway_label) {
                    printf('<option value="%s" %s>%s</option>', esc_attr((string) $gateway_key), selected($selected_gateway, $gateway_key, false), esc_html((string) $gateway_label));
                }
                echo '</select></label>';
            }
            echo '<button type="submit" class="chbk-booking-submit" ' . (empty($slots) || empty($enabled_gateways) ? 'disabled' : '') . '>Pay and Reserve</button>';
            echo '</div>';
        }
    } else {
        echo '<div class="chbk-booking-actions">';
        echo '<button type="submit" class="chbk-booking-submit" ' . (empty($slots) ? 'disabled' : '') . '>Reserve</button>';
        echo '</div>';
    }
    echo '</form>';
    echo '</div>';

    $output = ob_get_clean();
    $output = preg_replace('#<p>\s*(?:&nbsp;|<br\s*/?>)?\s*</p>#i', '', $output);
    return (string) $output;
}

function chbk_redirect_to_checkout_url($url)
{
    $url = esc_url_raw((string) $url);
    if ($url === '') {
        return;
    }

    $target_host = wp_parse_url($url, PHP_URL_HOST);
    $site_host = wp_parse_url(home_url('/'), PHP_URL_HOST);

    if ($target_host && $site_host && strtolower((string) $target_host) !== strtolower((string) $site_host)) {
        $allow_external = static function ($hosts) use ($target_host) {
            $hosts[] = (string) $target_host;
            return array_unique(array_filter($hosts));
        };
        add_filter('allowed_redirect_hosts', $allow_external);
        wp_safe_redirect($url);
        remove_filter('allowed_redirect_hosts', $allow_external);
        return;
    }

    wp_safe_redirect($url);
}

function chbk_build_trip_datetime_from_request($date, $time, $fallback = '')
{
    $date = trim((string) $date);
    $time = trim((string) $time);
    $fallback = trim((string) $fallback);

    if ($date !== '') {
        return $date . ' ' . ($time !== '' ? $time : '00:00');
    }

    return $fallback;
}
