<?php
/**
 * Shortcodes handler
 *
 * @package NemtlyBooking
 */

namespace NemtlyBooking\Core;

class Shortcodes {

    /**
     * Initialize shortcodes
     */
    public function __construct() {
        $this->register_shortcodes();
    }

    /**
     * Register all shortcodes
     */
    public function register_shortcodes() {
        add_shortcode( 'nemtly_booking_form', [ $this, 'booking_form_shortcode' ] );
        add_shortcode( 'nemtly_event_list', [ $this, 'event_list_shortcode' ] );
        add_shortcode( 'nemtly_events_new', [ $this, 'events_new_layout_shortcode' ] );
        add_shortcode( 'nemtly_calendar', [ $this, 'calendar_shortcode' ] );
        add_shortcode( 'nemtly_booking_calendar', [ $this, 'booking_calendar_shortcode' ] );
    }

    /**
     * Booking form shortcode
     *
     * @param array $atts Shortcode attributes.
     * @return string HTML output.
     */
    public function booking_form_shortcode( $atts ) {
        // Parse attributes
        $atts = shortcode_atts(
            [
                'event_id' => '',
                'class'    => '',
            ],
            $atts,
            'nemtly_booking_form'
        );

        // Validate event ID
        $event_id = ! empty( $atts['event_id'] ) ? absint( $atts['event_id'] ) : 0;

        // If no ID provided, try to get current post ID
        if ( ! $event_id ) {
            $event_id = get_the_ID();
        }

        // Check if event exists
        if ( ! $this->event_exists( $event_id ) ) {
            return '';
        }

        // Enqueue scripts and styles
        $this->enqueue_booking_form_assets();

        // Generate unique container ID
        $container_id = 'nb-booking-form-' . $event_id . '-' . wp_rand( 1000, 9999 );

        // Get additional CSS classes
        $css_class = sanitize_html_class( $atts['class'] );

        /**
         * Filter the wrapper CSS classes for the `[nemtly_booking_form]` mount point.
         *
         * @since PBOOKING_SINCE
         *
         * @param string[] $classes CSS classes applied to the wrapper div.
         * @param array    $atts    Sanitized shortcode attributes.
         */
        $wrapper_classes = apply_filters(
            'nemtly_booking_booking_form_classes',
            array_filter( [ 'nemtly-booking-form-container', $css_class ] ),
            $atts
        );

        /**
         * Filter the `data-*` attributes passed from the wrapper div to the booking form React app.
         *
         * @since PBOOKING_SINCE
         *
         * @param array $data_attrs Map of attribute name (without the `data-` prefix) to value.
         * @param array $atts       Sanitized shortcode attributes.
         */
        $data_attrs = apply_filters(
            'nemtly_booking_booking_form_data',
            [ 'event-id' => $event_id ],
            $atts
        );

        $output = Template::render(
            'shortcodes/booking-form.php',
            [
                'container_id'    => $container_id,
                'wrapper_classes' => $wrapper_classes,
                'data_attrs'      => $data_attrs,
                'event_id'        => $event_id,
                'atts'            => $atts,
            ]
        );

        /**
         * Filter the final `[nemtly_booking_form]` shortcode HTML output.
         *
         * @since PBOOKING_SINCE
         *
         * @param string $output Rendered shortcode HTML.
         * @param array  $atts   Sanitized shortcode attributes.
         */
        return apply_filters( 'nemtly_booking_booking_form_html', $output, $atts );
    }

    /**
     * Booking calendar shortcode — renders an inline booking calendar for a single event.
     *
     * Displays the date picker, time slot picker, attendee form, and payment flow
     * for a single event. Ideal for service providers (consultants, therapists, tutors)
     * who want to embed a booking widget on any page.
     *
     * Usage: [nemtly_booking_calendar event_id="123"]
     *
     * @since PBOOKING_SINCE
     *
     * @param array $atts Shortcode attributes.
     *
     * @return string HTML output.
     */
    public function booking_calendar_shortcode( $atts ) {
        $atts = shortcode_atts(
            [
                'event_id' => '',
                'class'    => '',
            ],
            $atts,
            'nemtly_booking_calendar'
        );

        $event_id = ! empty( $atts['event_id'] ) ? absint( $atts['event_id'] ) : 0;

        if ( ! $event_id ) {
            return '';
        }

        if ( ! $this->event_exists( $event_id ) ) {
            return '';
        }

        $this->enqueue_booking_form_assets();

        $container_id = 'nb-booking-form-' . $event_id . '-' . wp_rand( 1000, 9999 );
        $css_class    = sanitize_html_class( $atts['class'] );

        /**
         * Filter the wrapper CSS classes for the `[nemtly_booking_calendar]` mount point.
         *
         * @since PBOOKING_SINCE
         *
         * @param string[] $classes CSS classes applied to the wrapper div.
         * @param array    $atts    Sanitized shortcode attributes.
         */
        $wrapper_classes = apply_filters(
            'nemtly_booking_booking_calendar_classes',
            array_filter( [ 'nemtly-booking-form-container', $css_class ] ),
            $atts
        );

        /**
         * Filter the `data-*` attributes passed from the wrapper div to the booking calendar React app.
         *
         * @since PBOOKING_SINCE
         *
         * @param array $data_attrs Map of attribute name (without the `data-` prefix) to value.
         * @param array $atts       Sanitized shortcode attributes.
         */
        $data_attrs = apply_filters(
            'nemtly_booking_booking_calendar_data',
            [ 'event-id' => $event_id ],
            $atts
        );

        $output = Template::render(
            'shortcodes/booking-calendar.php',
            [
                'container_id'    => $container_id,
                'wrapper_classes' => $wrapper_classes,
                'data_attrs'      => $data_attrs,
                'event_id'        => $event_id,
                'atts'            => $atts,
            ]
        );

        /**
         * Filter the final `[nemtly_booking_calendar]` shortcode HTML output.
         *
         * @since PBOOKING_SINCE
         *
         * @param string $output Rendered shortcode HTML.
         * @param array  $atts   Sanitized shortcode attributes.
         */
        return apply_filters( 'nemtly_booking_booking_calendar_html', $output, $atts );
    }

    /**
     * Event list shortcode
     *
     * @param array $atts Shortcode attributes.
     * @return string HTML output.
     */
    public function event_list_shortcode( $atts ) {
        // Parse attributes
        $atts = shortcode_atts(
            [
                'limit'           => 12,
                'order'           => 'ASC',
                'orderby'         => 'event_date',
                'show_form'       => 'false',
                'show_filters'    => 'true',
                'show_pagination' => 'true',
                'show_search'     => 'true',
                'layout'          => 'grid',
                'class'           => '',
            ],
            $atts,
            'nemtly_event_list'
        );

        /**
         * Filter the parsed `[nemtly_event_list]` shortcode attributes before they are sanitized.
         *
         * @since PBOOKING_SINCE
         *
         * @param array $atts Shortcode attributes merged with their defaults.
         */
        $atts = apply_filters( 'nemtly_booking_event_list_atts', $atts );

        // Validate and sanitize attributes
        $limit           = absint( $atts['limit'] );
        $order           = in_array( strtoupper( $atts['order'] ), [ 'ASC', 'DESC' ], true ) ? strtoupper( $atts['order'] ) : 'ASC';
        $orderby         = in_array( $atts['orderby'], [ 'event_date', 'title', 'created' ], true ) ? $atts['orderby'] : 'event_date';
        $show_form       = 'true' === $atts['show_form'];
        $show_filters    = 'true' === $atts['show_filters'];
        $show_pagination = 'true' === $atts['show_pagination'];
        $show_search     = 'true' === $atts['show_search'];
        $layout          = in_array( $atts['layout'], [ 'grid', 'list' ], true ) ? $atts['layout'] : 'grid';
        $css_class       = sanitize_html_class( $atts['class'] );

        // Get events
        $events = $this->get_upcoming_events( $limit, $order, $orderby );

        // Enqueue frontend assets
        $this->enqueue_frontend_events_assets();

        /**
         * Filter the wrapper CSS classes for the `[nemtly_event_list]` mount point.
         *
         * @since PBOOKING_SINCE
         *
         * @param string[] $classes CSS classes applied to the wrapper div.
         * @param array    $atts    Sanitized shortcode attributes.
         */
        $wrapper_classes = apply_filters(
            'nemtly_booking_event_list_classes',
            array_filter( [ 'nb-events-display', $css_class ] ),
            $atts
        );

        /**
         * Filter the `data-*` attributes passed from the wrapper div to the events React app.
         *
         * @since PBOOKING_SINCE
         *
         * @param array $data_attrs Map of attribute name (without the `data-` prefix) to value.
         * @param array $atts       Sanitized shortcode attributes.
         */
        $data_attrs = apply_filters(
            'nemtly_booking_event_list_data',
            [
                'limit'           => $limit,
                'show-filters'    => $show_filters ? 'true' : 'false',
                'show-pagination' => $show_pagination ? 'true' : 'false',
                'show-search'     => $show_search ? 'true' : 'false',
                'layout'          => $layout,
            ],
            $atts
        );

        $output = Template::render(
            'shortcodes/event-list.php',
            [
                'wrapper_classes' => $wrapper_classes,
                'data_attrs'      => $data_attrs,
                'events'          => $events,
                'atts'            => $atts,
            ]
        );

        /**
         * Filter the final `[nemtly_event_list]` shortcode HTML output.
         *
         * @since PBOOKING_SINCE
         *
         * @param string $output Rendered shortcode HTML.
         * @param array  $atts   Sanitized shortcode attributes.
         */
        return apply_filters( 'nemtly_booking_event_list_html', $output, $atts );
    }

    /**
     * Check if event exists
     *
     * @param int $event_id Event ID.
     * @return bool
     */
    private function event_exists( $event_id ) {
        $post = get_post( $event_id );
        return $post && 'nemtly_event' === $post->post_type && 'publish' === $post->post_status;
    }

    /**
     * Get upcoming events
     *
     * @param int    $limit   Number of events to retrieve.
     * @param string $order   Sort order.
     * @param string $orderby Sort field.
     * @return array Array of Event objects.
     */
    private function get_upcoming_events( $limit, $order, $orderby ) {
        $today = current_time( 'Y-m-d' );

        $args = [
            'post_type'      => 'nemtly_event',
            'post_status'    => 'publish',
            'posts_per_page' => $limit,
            'meta_query'     => [
                [
                    'key'     => 'nemtly_event_date',
                    'value'   => $today,
                    'compare' => '>=',
                    'type'    => 'DATE',
                ],
            ],
            'meta_key'       => 'nemtly_event_date',
            'orderby'        => $orderby,
            'order'          => $order,
        ];

        $posts  = get_posts( $args );
        $events = [];

        foreach ( $posts as $post ) {
            $events[] = new \NemtlyBooking\Models\Event(
                [
                    'id'            => $post->ID,
                    'title'         => $post->post_title,
                    'description'   => $post->post_content,
                    'date'          => get_post_meta( $post->ID, 'nemtly_event_date', true ),
                    'time'          => get_post_meta( $post->ID, 'nemtly_event_time', true ),
                    'duration'      => get_post_meta( $post->ID, 'nemtly_event_duration', true ),
                    'location'      => get_post_meta( $post->ID, 'nemtly_location', true ),
                    'max_attendees' => get_post_meta( $post->ID, 'nemtly_max_attendees', true ),
                    'status'        => get_post_meta( $post->ID, 'nemtly_event_status', true ),
                ]
            );
        }

        return $events;
    }

    /**
     * Enqueue booking form assets
     */
    private function enqueue_booking_form_assets() {
        // Only enqueue if not already enqueued
        if ( ! wp_script_is( 'nemtly-booking-form', 'enqueued' ) ) {
            // Enqueue built styles
            wp_enqueue_style(
                'nemtly-booking-form-styles',
                plugin_dir_url( dirname( __DIR__ ) ) . 'assets/css/booking-form.css',
                [],
                NEMTLY_BOOKING_VERSION
            );

            // Enqueue built scripts
            $asset_path = plugin_dir_path( dirname( __DIR__ ) ) . 'assets/js/booking-form.asset.php';
            $asset      = file_exists( $asset_path ) ? require $asset_path : [
                'dependencies' => [ 'wp-element', 'wp-api-fetch', 'wp-i18n' ],
                'version'      => NEMTLY_BOOKING_VERSION,
            ];

            wp_enqueue_script(
                'nemtly-booking-form',
                plugin_dir_url( dirname( __DIR__ ) ) . 'assets/js/booking-form.js',
                $asset['dependencies'],
                $asset['version'],
                true
            );

            $plugin_settings = get_option( 'nemtly_booking_settings', [] );

            // Localize script
            wp_localize_script(
                'nemtly-booking-form',
                'nemtlyBookingAjax',
                [
                    'nonce'     => wp_create_nonce( 'nemtly_nonce' ),
                    'ajaxUrl'   => admin_url( 'admin-ajax.php' ),
                    'restUrl'   => rest_url( 'nemtly-booking/v1/' ),
                    'restNonce' => wp_create_nonce( 'wp_rest' ),
                    'legal'     => [
                        'terms_url'   => esc_url( (string) apply_filters( 'nemtly_booking_terms_url', '' ) ),
                        'privacy_url' => esc_url( (string) apply_filters( 'nemtly_booking_privacy_url', (string) get_privacy_policy_url() ) ),
                    ],
                    'strings'   => [
                        'loading'        => __( 'Loading...', 'nemtly-booking' ),
                        'processing'     => __( 'Processing...', 'nemtly-booking' ),
                        'error'          => __( 'An error occurred. Please try again.', 'nemtly-booking' ),
                        'success'        => __( 'Booking successful!', 'nemtly-booking' ),
                        'confirmBooking' => __( 'Confirm Booking', 'nemtly-booking' ),
                        'cancel'         => __( 'Cancel', 'nemtly-booking' ),
                        'requiredField'  => __( 'This field is required.', 'nemtly-booking' ),
                        'invalidEmail'   => __( 'Please enter a valid email address.', 'nemtly-booking' ),
                    ],
                    'captcha'   => [
                        'type'          => $plugin_settings['captcha_type'] ?? 'disabled',
                        'site_key'      => 'turnstile' === ( $plugin_settings['captcha_type'] ?? '' )
                            ? esc_attr( $plugin_settings['turnstile_site_key'] ?? '' )
                            : '',
                        'site_key_name' => 'turnstile',
                    ],
                ]
            );

            // Set up REST API nonce for wp-api-fetch
            wp_add_inline_script(
                'nemtly-booking-form',
                sprintf(
                    'wp.apiFetch.use( wp.apiFetch.createNonceMiddleware( %s ) );',
                    wp_json_encode( wp_create_nonce( 'wp_rest' ) )
                ),
                'before'
            );

            // Set script translations
            wp_set_script_translations( 'nemtly-booking-form', 'nemtly-booking' );
        }
    }

    /**
     * Enqueue frontend assets for event list
     */
    private function enqueue_frontend_events_assets() {
        // Only enqueue if not already enqueued
        if ( ! wp_script_is( 'nemtly-booking-events-frontend', 'enqueued' ) ) {
            // Enqueue built styles
            wp_enqueue_style(
                'nemtly-events-frontend-styles',
                plugin_dir_url( dirname( __DIR__ ) ) . 'assets/css/events-frontend.css',
                [],
                NEMTLY_BOOKING_VERSION
            );

            // Enqueue built scripts
            $asset_path = plugin_dir_path( dirname( __DIR__ ) ) . 'assets/js/events-frontend.asset.php';
            $asset      = file_exists( $asset_path ) ? require $asset_path : [
                'dependencies' => [ 'wp-element', 'wp-api-fetch', 'wp-i18n' ],
                'version'      => NEMTLY_BOOKING_VERSION,
            ];

            wp_enqueue_script(
                'nemtly-events-frontend',
                plugin_dir_url( dirname( __DIR__ ) ) . 'assets/js/events-frontend.js',
                $asset['dependencies'],
                $asset['version'],
                true
            );

            // Localize script
            wp_localize_script(
                'nemtly-events-frontend',
                'nemtlyEventsAjax',
                [
                    'nonce'     => wp_create_nonce( 'nemtly_nonce' ),
                    'ajaxUrl'   => admin_url( 'admin-ajax.php' ),
                    'restUrl'   => rest_url( 'nemtly-booking/v1/' ),
                    'restNonce' => wp_create_nonce( 'wp_rest' ),
                    'strings'   => [
                        'loading'        => __( 'Loading...', 'nemtly-booking' ),
                        'processing'     => __( 'Processing...', 'nemtly-booking' ),
                        'error'          => __( 'An error occurred. Please try again.', 'nemtly-booking' ),
                        'success'        => __( 'Booking successful!', 'nemtly-booking' ),
                        'confirmBooking' => __( 'Confirm Booking', 'nemtly-booking' ),
                        'cancel'         => __( 'Cancel', 'nemtly-booking' ),
                        'requiredField'  => __( 'This field is required.', 'nemtly-booking' ),
                        'invalidEmail'   => __( 'Please enter a valid email address.', 'nemtly-booking' ),
                    ],
                ]
            );

            // Set script translations
            wp_set_script_translations( 'nemtly-events-frontend', 'nemtly-booking' );
        }
    }

    /**
     * Calendar shortcode — renders the interactive event calendar.
     *
     * Accepted attributes:
     *   view             string  Default view: month|week|day|list. Default: month.
     *   views            string  Comma-separated list of allowed views. Default: month,week,day,list.
     *   categories       string  Comma-separated category term IDs to pre-filter. Default: all.
     *   tags             string  Comma-separated tag term IDs to pre-filter. Default: all.
     *   event_type       string  Filter by event type slug. Default: all.
     *   show_toolbar     bool    Show/hide navigation bar. Default: true.
     *   show_filters     bool    Show/hide filter dropdowns. Default: true.
     *   week_starts_on   string  sunday|monday. Default: sunday.
     *   events_per_cell  int     Max events per day cell before "+N more". Default: 3.
     *   time_format      string  12h|24h|site_default. Default: site_default.
     *   show_event_time  bool    Show event times on chips. Default: true.
     *   show_booking_btn bool    Show "Book Now" button. Default: true.
     *   show_past_events bool    Show past events. Default: false.
     *   color_by         string  category|event_type|none. Default: category.
     *   height           string  auto|fixed. Default: auto.
     *   height_px        int     Fixed height in pixels. Default: 600.
     *   class            string  Additional CSS class on the wrapper element.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $atts Shortcode attributes.
     *
     * @return string HTML output.
     */
    public function calendar_shortcode( $atts ) {
        $atts = shortcode_atts(
            [
                'view'             => 'month',
                'views'            => 'month,week,day,list',
                'categories'       => '',
                'tags'             => '',
                'event_type'       => '',
                'show_toolbar'     => 'true',
                'show_filters'     => 'true',
                'week_starts_on'   => 'sunday',
                'events_per_cell'  => '3',
                'time_format'      => 'site_default',
                'show_event_time'  => 'true',
                'show_booking_btn' => 'true',
                'show_past_events' => 'false',
                'color_by'         => 'category',
                'height'           => 'auto',
                'height_px'        => '600',
                'class'            => '',
            ],
            $atts,
            'nemtly_calendar'
        );

        // Validate view value.
        $allowed_views = [ 'month', 'week', 'day', 'list' ];
        $view          = in_array( $atts['view'], $allowed_views, true ) ? $atts['view'] : 'month';

        // Available views.
        $requested       = array_map( 'trim', explode( ',', $atts['views'] ) );
        $valid_views     = array_intersect( $requested, $allowed_views );
        $available_views = ! empty( $valid_views ) ? array_values( $valid_views ) : $allowed_views;
        $views           = implode( ',', $available_views );

        // Sanitize comma-separated IDs.
        $categories   = sanitize_text_field( $atts['categories'] );
        $tags         = sanitize_text_field( $atts['tags'] );
        $event_type   = sanitize_text_field( $atts['event_type'] );
        $show_toolbar = 'false' !== $atts['show_toolbar'] ? 'true' : 'false';
        $show_filters = 'false' !== $atts['show_filters'] ? 'true' : 'false';
        $css_class    = sanitize_html_class( $atts['class'] );

        // Week start: convert string to int.
        $week_starts_on = 'monday' === $atts['week_starts_on'] ? 1 : 0;

        // Display settings from shortcode attributes.
        $calendar_config = [
            'defaultView'      => $view,
            'availableViews'   => $available_views,
            'firstDayOfWeek'   => $week_starts_on,
            'eventsPerCell'    => absint( $atts['events_per_cell'] ) > 0 ? absint( $atts['events_per_cell'] ) : 3,
            'timeFormat'       => in_array( $atts['time_format'], [ '12h', '24h', 'site_default' ], true )
                ? $atts['time_format'] : 'site_default',
            'showEventTime'    => 'false' !== $atts['show_event_time'],
            'showBookingBtn'   => 'false' !== $atts['show_booking_btn'],
            'showPastEvents'   => 'true' === $atts['show_past_events'],
            'colorBy'          => in_array( $atts['color_by'], [ 'category', 'event_type', 'none' ], true )
                ? $atts['color_by'] : 'category',
            'calendarHeight'   => in_array( $atts['height'], [ 'auto', 'fixed' ], true )
                ? $atts['height'] : 'auto',
            'calendarHeightPx' => absint( $atts['height_px'] ) > 0 ? absint( $atts['height_px'] ) : 600,
        ];

        $this->enqueue_calendar_assets( $calendar_config );

        $uid          = wp_rand( 1000, 9999 );
        $container_id = 'nb-event-calendar-' . $uid;

        ob_start();
        ?>
        <div id="<?php echo esc_attr( $container_id ); ?>"
            class="nb-event-calendar <?php echo esc_attr( $css_class ); ?>"
            data-view="<?php echo esc_attr( $view ); ?>"
            data-views="<?php echo esc_attr( $views ); ?>"
            data-categories="<?php echo esc_attr( $categories ); ?>"
            data-tags="<?php echo esc_attr( $tags ); ?>"
            data-event-type="<?php echo esc_attr( $event_type ); ?>"
            data-show-toolbar="<?php echo esc_attr( $show_toolbar ); ?>"
            data-show-filters="<?php echo esc_attr( $show_filters ); ?>"
            data-week-starts-on="<?php echo esc_attr( $week_starts_on ); ?>">
            <noscript>
                <p><?php esc_html_e( 'Please enable JavaScript to view the event calendar.', 'nemtly-booking' ); ?></p>
            </noscript>
        </div>
        <?php

        return ob_get_clean();
    }

    /**
     * Enqueue assets required by the event calendar.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $config Calendar display configuration derived from shortcode attributes.
     *
     * @return void
     */
    private function enqueue_calendar_assets( $config = [] ) {
        if ( wp_script_is( 'nemtly-event-calendar', 'enqueued' ) ) {
            return;
        }

        wp_enqueue_style(
            'nemtly-event-calendar-styles',
            plugin_dir_url( dirname( __DIR__ ) ) . 'assets/css/event-calendar.css',
            [],
            NEMTLY_BOOKING_VERSION
        );

        $asset_path = plugin_dir_path( dirname( __DIR__ ) ) . 'assets/js/event-calendar.asset.php';
        $asset      = file_exists( $asset_path ) ? require $asset_path : [
            'dependencies' => [ 'wp-element', 'wp-api-fetch', 'wp-i18n' ],
            'version'      => NEMTLY_BOOKING_VERSION,
        ];

        wp_enqueue_script(
            'nemtly-event-calendar',
            plugin_dir_url( dirname( __DIR__ ) ) . 'assets/js/event-calendar.js',
            $asset['dependencies'],
            $asset['version'],
            true
        );

        $defaults = [
            'defaultView'      => 'month',
            'availableViews'   => [ 'month', 'week', 'day', 'list' ],
            'firstDayOfWeek'   => 0,
            'eventsPerCell'    => 3,
            'timeFormat'       => 'site_default',
            'showEventTime'    => true,
            'showBookingBtn'   => true,
            'showPastEvents'   => false,
            'colorBy'          => 'category',
            'categoryColors'   => [],
            'calendarHeight'   => 'auto',
            'calendarHeightPx' => 600,
        ];

        $config = wp_parse_args( $config, $defaults );

        wp_localize_script(
            'nemtly-event-calendar',
            'nemtlyCalendar',
            [
                'restUrl'          => rest_url( 'nemtly-booking/v1' ),
                'restNonce'        => wp_create_nonce( 'wp_rest' ),
                'defaultView'      => $config['defaultView'],
                'availableViews'   => $config['availableViews'],
                'firstDayOfWeek'   => (int) $config['firstDayOfWeek'],
                'eventsPerCell'    => (int) $config['eventsPerCell'],
                'timeFormat'       => $config['timeFormat'],
                'showEventTime'    => (bool) $config['showEventTime'],
                'showBookingBtn'   => (bool) $config['showBookingBtn'],
                'showPastEvents'   => (bool) $config['showPastEvents'],
                'colorBy'          => $config['colorBy'],
                'categoryColors'   => $config['categoryColors'],
                'calendarHeight'   => $config['calendarHeight'],
                'calendarHeightPx' => (int) $config['calendarHeightPx'],
                'siteTimezone'     => wp_timezone_string(),
                'strings'          => [
                    'loading'       => __( 'Loading events...', 'nemtly-booking' ),
                    'noEvents'      => __( 'No events this period.', 'nemtly-booking' ),
                    'error'         => __( 'Could not load events. Please try again.', 'nemtly-booking' ),
                    'retry'         => __( 'Retry', 'nemtly-booking' ),
                    'today'         => __( 'Today', 'nemtly-booking' ),
                    'month'         => __( 'Month', 'nemtly-booking' ),
                    'week'          => __( 'Week', 'nemtly-booking' ),
                    'day'           => __( 'Day', 'nemtly-booking' ),
                    'list'          => __( 'List', 'nemtly-booking' ),
                    'viewDetails'   => __( 'View Details', 'nemtly-booking' ),
                    'bookNow'       => __( 'Book Now', 'nemtly-booking' ),
                    'allCategories' => __( 'All Categories', 'nemtly-booking' ),
                    'allTags'       => __( 'All Tags', 'nemtly-booking' ),
                    /* translators: %d: number of additional events not shown in the cell */
                    'moreEvents'    => __( '+%d more', 'nemtly-booking' ),
                    'noJs'          => __( 'Please enable JavaScript to view the event calendar.', 'nemtly-booking' ),
                ],
            ]
        );

        // Set up REST API nonce for wp-api-fetch.
        wp_add_inline_script(
            'nemtly-event-calendar',
            sprintf(
                'wp.apiFetch.use( wp.apiFetch.createNonceMiddleware( %s ) );',
                wp_json_encode( wp_create_nonce( 'wp_rest' ) )
            ),
            'before'
        );

        wp_set_script_translations( 'nemtly-event-calendar', 'nemtly-booking' );
    }

    /**
     * Events new layout shortcode
     *
     * @param array $atts Shortcode attributes.
     * @return string HTML output.
     */
    public function events_new_layout_shortcode( $atts ) {
        // Parse attributes
        $atts = shortcode_atts(
            [
                'limit'           => 12,
                'order'           => 'ASC',
                'orderby'         => 'event_date',
                'show_filters'    => 'true',
                'show_pagination' => 'true',
                'class'           => '',
            ],
            $atts,
            'nemtly_events_new'
        );

        // Validate and sanitize attributes
        $limit           = absint( $atts['limit'] );
        $order           = in_array( strtoupper( $atts['order'] ), [ 'ASC', 'DESC' ], true ) ? strtoupper( $atts['order'] ) : 'ASC';
        $orderby         = in_array( $atts['orderby'], [ 'event_date', 'title', 'created' ], true ) ? $atts['orderby'] : 'event_date';
        $show_filters    = 'true' === $atts['show_filters'];
        $show_pagination = 'true' === $atts['show_pagination'];
        $css_class       = sanitize_html_class( $atts['class'] );

        // Get events
        $events = $this->get_upcoming_events( $limit, $order, $orderby );

        // Convert Event objects to arrays for template
        $events_data = [];
        foreach ( $events as $event ) {
            $events_data[] = [
                'id'             => $event->get_id(),
                'title'          => $event->get_title(),
                'description'    => $event->get_description(),
                'date'           => $event->get_formatted_date(),
                'time'           => $event->get_time(),
                'location'       => $event->get_location(),
                'featured_image' => $event->get_featured_image_src( 'medium' ),
                'is_bookable'    => $event->is_bookable(),
            ];
        }

        // Set up pagination data
        $pagination = [
            'current_page' => 1,
            'total_pages'  => 1,
            'total_items'  => count( $events_data ),
        ];

        // Set template variables
        $template_vars = [
            'events'          => $events_data,
            'show_filters'    => $show_filters,
            'show_pagination' => $show_pagination,
            'active_filter'   => 'all',
            'pagination'      => $pagination,
        ];

        // Enqueue frontend assets
        $this->enqueue_frontend_events_assets();

        // Start output buffering
        ob_start();

        // Include template
        include plugin_dir_path( dirname( __DIR__ ) ) . 'templates/events-display-new.php';

        return ob_get_clean();
    }
}