<?php
/**
 * Admin screen for FoodOrd table reservations.
 *
 * @package FoodOrd
 */

defined( 'ABSPATH' ) || exit;

/**
 * Class Foodord_Table_Reservations_Admin
 */
class Foodord_Table_Reservations_Admin {
	private const OPTION_BANNER_IMAGE_ID    = 'foodord_table_reservation_banner_image_id';
	private const OPTION_BANNER_DISABLED    = 'foodord_table_reservation_banner_disabled';
	private const NOTICE_TRANSIENT_PREFIX   = 'foodord_reservation_notice_';
	private const MANAGEMENT_ITEMS_PER_PAGE = 10;

	/**
	 * Core reservations service.
	 *
	 * @var Foodord_Table_Reservations
	 */
	private $reservations;

	/**
	 * Shared reservation operations.
	 *
	 * @var Foodord_Table_Reservation_Operations
	 */
	private $operations;

	/**
	 * Constructor.
	 */
	public function __construct() {
		$this->reservations = new Foodord_Table_Reservations();
		$this->operations   = new Foodord_Table_Reservation_Operations( $this->reservations );
	}

	/**
	 * Bootstrap admin hooks.
	 */
	public function init(): void {
		add_action( 'admin_menu', array( $this, 'register_submenu' ), 19 );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) );
		add_action( 'admin_post_foodord_save_reservation_floor', array( $this, 'handle_save_floor' ) );
		add_action( 'admin_post_foodord_delete_reservation_floor', array( $this, 'handle_delete_floor' ) );
		add_action( 'admin_post_foodord_save_reservation_table', array( $this, 'handle_save_table' ) );
		add_action( 'admin_post_foodord_save_reservation_banner', array( $this, 'handle_save_banner' ) );
		add_action( 'admin_post_foodord_delete_reservation_table', array( $this, 'handle_delete_table' ) );
		add_action( 'admin_post_foodord_create_manual_reservation', array( $this, 'handle_create_manual_reservation' ) );
		add_action( 'admin_post_foodord_update_reservation_status', array( $this, 'handle_update_reservation_status' ) );
		add_action( 'admin_post_foodord_resend_reservation_status_email', array( $this, 'handle_resend_reservation_status_email' ) );
		add_action( 'admin_post_foodord_bulk_reservation_action', array( $this, 'handle_bulk_reservation_action' ) );
		add_action( 'wp_ajax_foodord_save_reservation_floor', array( $this, 'ajax_save_floor' ) );
		add_action( 'wp_ajax_foodord_save_reservation_table', array( $this, 'ajax_save_table' ) );
		add_action( 'wp_ajax_foodord_filter_reservation_tables', array( $this, 'ajax_filter_tables' ) );
		add_action( 'wp_ajax_foodord_paginate_reservation_management', array( $this, 'ajax_paginate_management_list' ) );
		add_action( 'wp_ajax_foodord_get_manual_reservation_times', array( $this, 'ajax_get_manual_reservation_times' ) );
		add_action( 'wp_ajax_foodord_get_manual_reservation_tables', array( $this, 'ajax_get_manual_reservation_tables' ) );
	}

	/**
	 * Enqueue admin assets for the Reservations page.
	 *
	 * @param string $hook Current admin hook.
	 */
	public function enqueue_assets( $hook ): void {
		$current_page = $this->get_query_text_field( 'page' );

		if ( ! is_string( $hook ) || ( false === strpos( $hook, $this->get_page_slug() ) && $current_page !== $this->get_page_slug() ) ) {
			return;
		}

		wp_enqueue_media();
		$table_selection_settings = Foodord_Table_Reservations::get_table_selection_settings();

		wp_enqueue_style(
			'foodord-admin-faq',
			FOODORD_URL . 'admin/css/foodord-admin-faq.css',
			array(),
			FOODORD_VERSION,
			'all'
		);

		wp_enqueue_style(
			'foodord-table-reservations-admin',
			FOODORD_URL . 'admin/css/foodord-table-reservations-admin.css',
			array(),
			FOODORD_VERSION,
			'all'
		);

		wp_enqueue_script(
			'foodord-reservation-floor-plan-builder',
			FOODORD_URL . 'admin/js/foodord-reservation-floor-plan-builder.js',
			array(),
			FOODORD_VERSION,
			true
		);

		wp_enqueue_script(
			'foodord-reservation-image-plan-marker-editor',
			FOODORD_URL . 'admin/js/foodord-reservation-image-plan-marker-editor.js',
			array(),
			FOODORD_VERSION,
			true
		);

		wp_enqueue_script(
			'foodord-table-reservations-admin',
			FOODORD_URL . 'admin/js/foodord-table-reservations-admin.js',
			array( 'jquery', 'jquery-ui-datepicker', 'foodord-reservation-floor-plan-builder', 'foodord-reservation-image-plan-marker-editor' ),
			FOODORD_VERSION,
			true
		);

		wp_localize_script(
			'foodord-table-reservations-admin',
			'FoodordTableReservationsAdmin',
			array(
				'ajaxUrl'                   => admin_url( 'admin-ajax.php' ),
				'dateDisabled'              => Foodord_Table_Reservations::get_datepicker_disabled_rules(),
				'dateFormat'                => Foodord_Table_Reservations::get_jquery_datepicker_format(),
				'tableFilterNonce'          => wp_create_nonce( 'foodord_filter_reservation_tables' ),
				'managementPaginationNonce' => wp_create_nonce( 'foodord_paginate_reservation_management' ),
				'tableSelection'            => array(
					'layouts' => $table_selection_settings['layouts'],
				),
				'i18n'                      => array(
					'filterError'       => __( 'Unable to filter tables. Please try again.', 'foodord' ),
					'noTablesAvailable' => __( 'No tables available', 'foodord' ),
					'paginationError'   => __( 'Unable to load this page. Please try again.', 'foodord' ),
					'saveError'         => __( 'Unable to save changes. Please try again.', 'foodord' ),
					'selectDuration'    => __( 'Select duration', 'foodord' ),
					'selectTable'       => __( 'Select table', 'foodord' ),
					'selectTime'        => __( 'Select time', 'foodord' ),
					'noTimesAvailable'  => __( 'No times available', 'foodord' ),
				),
			)
		);
	}

	/**
	 * Retrieve current reservations page slug.
	 */
	private function get_page_slug(): string {
		return function_exists( 'foodord_get_settings_page_slug' )
			? foodord_get_settings_page_slug( 'reservations' )
			: 'foodord-reservations';
	}

	/**
	 * Build the current admin page URL.
	 */
	private function get_page_url(): string {
		return admin_url( 'admin.php?page=' . $this->get_page_slug() );
	}

	/**
	 * Build a Reservations page URL for a specific tab.
	 *
	 * @param string $tab Tab key.
	 */
	private function get_tab_url( string $tab ): string {
		return add_query_arg(
			'reservation_tab',
			$this->sanitize_reservation_tab( $tab ),
			$this->get_page_url()
		);
	}

	/**
	 * Get reservation admin tabs.
	 *
	 * @return array<string,string>
	 */
	private function get_reservation_tabs(): array {
		return array(
			'dashboard'     => __( 'Dashboard', 'foodord' ),
			'reservations'  => __( 'Reservations', 'foodord' ),
			'tables'        => __( 'Tables & Floors', 'foodord' ),
			'booking-rules' => __( 'Reservation Rules', 'foodord' ),
			'preorder'      => __( 'Pre-order', 'foodord' ),
			'deposit'       => __( 'Deposit', 'foodord' ),
			'security'      => __( 'Security', 'foodord' ),
			'settings'      => __( 'Settings', 'foodord' ),
		);
	}

	/**
	 * Sanitize a reservation tab key.
	 *
	 * @param string $tab Tab key.
	 */
	private function sanitize_reservation_tab( string $tab ): string {
		$tab = sanitize_key( $tab );

		return array_key_exists( $tab, $this->get_reservation_tabs() ) ? $tab : 'dashboard';
	}

	/**
	 * Get the active reservation admin tab.
	 */
	private function get_active_reservation_tab(): string {
		return $this->sanitize_reservation_tab( $this->get_query_text_field( 'reservation_tab' ) );
	}

	/**
	 * Render reservation admin tabs.
	 *
	 * @param string $active_tab Active tab key.
	 */
	private function render_reservation_tabs( string $active_tab ): void {
		$tabs = $this->get_reservation_tabs();
		?>
		<nav class="foodord-reservations-tabs" aria-label="<?php echo esc_attr__( 'Reservation sections', 'foodord' ); ?>">
			<?php foreach ( $tabs as $tab_key => $label ) : ?>
				<?php
				$is_active = $active_tab === $tab_key;
				$url       = add_query_arg(
					array(
						'page'            => $this->get_page_slug(),
						'reservation_tab' => $tab_key,
					),
					admin_url( 'admin.php' )
				);
				?>
				<a
					class="foodord-reservations-tabs__link <?php echo esc_attr( $is_active ? 'is-active' : '' ); ?>"
					href="<?php echo esc_url( $url ); ?>"
					<?php if ( $is_active ) : ?>
						aria-current="page"
					<?php endif; ?>
				>
					<?php echo esc_html( $label ); ?>
				</a>
			<?php endforeach; ?>
		</nav>
		<?php
	}

	/**
	 * Register the Reservations submenu.
	 */
	public function register_submenu(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		$parent_slug = function_exists( 'foodord_get_admin_parent_slug' )
			? foodord_get_admin_parent_slug()
			: 'foodord-settings';

		add_submenu_page(
			$parent_slug,
			__( 'Reservations', 'foodord' ),
			__( 'Reservations', 'foodord' ),
			'manage_options',
			$this->get_page_slug(),
			array( $this, 'render_page' )
		);
	}

	/**
	 * Handle floor create/update.
	 */
	public function handle_save_floor(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_save_reservation_floor' );

		$result = $this->save_floor_from_request();

		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'floor_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'floor_saved' );
	}

	/**
	 * Handle floor deletion.
	 */
	public function handle_delete_floor(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_delete_reservation_floor' );

		$floor_id = absint( filter_input( INPUT_POST, 'floor_id', FILTER_SANITIZE_NUMBER_INT ) );
		$result   = $this->reservations->delete_floor( $floor_id );

		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'floor_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'floor_deleted' );
	}

	/**
	 * Handle table create/update.
	 */
	public function handle_save_table(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_save_reservation_table' );

		$result = $this->save_table_from_request();

		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'table_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'table_saved' );
	}

	/**
	 * Handle floor create/update over AJAX.
	 */
	public function ajax_save_floor(): void {
		$this->verify_ajax_request( 'foodord_save_reservation_floor' );

		$result = $this->save_floor_from_request();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( array( 'message' => $result->get_error_message() ), 400 );
		}

		$floors = $this->reservations->get_floors();
		$tables = $this->reservations->get_tables( true );

		wp_send_json_success(
			array(
				'message'            => __( 'Floor saved.', 'foodord' ),
				'floorsHtml'         => $this->get_rendered_floors_list( $floors, $tables ),
				'tablesHtml'         => $this->get_rendered_tables_list( $tables ),
				'tableFiltersHtml'   => $this->get_rendered_table_filters( $floors, $tables ),
				'floors'             => $this->get_floor_options_data( $floors ),
				'tableSelectionHtml' => $this->get_rendered_table_selection_settings_form(),
			)
		);
	}

	/**
	 * Handle table create/update over AJAX.
	 */
	public function ajax_save_table(): void {
		$this->verify_ajax_request( 'foodord_save_reservation_table' );

		$result = $this->save_table_from_request();
		if ( is_wp_error( $result ) ) {
			wp_send_json_error( array( 'message' => $result->get_error_message() ), 400 );
		}

		$floors = $this->reservations->get_floors();
		$tables = $this->reservations->get_tables( true );

		wp_send_json_success(
			array(
				'message'            => __( 'Table saved.', 'foodord' ),
				'floorsHtml'         => $this->get_rendered_floors_list( $floors, $tables ),
				'tablesHtml'         => $this->get_rendered_tables_list( $tables ),
				'tableFiltersHtml'   => $this->get_rendered_table_filters( $floors, $tables ),
				'tableSelectionHtml' => $this->get_rendered_table_selection_settings_form(),
			)
		);
	}

	/**
	 * Filter the Tables list over AJAX.
	 */
	public function ajax_filter_tables(): void {
		$this->verify_ajax_request( 'foodord_filter_reservation_tables' );

		wp_send_json_success(
			array(
				'tablesHtml' => $this->get_rendered_tables_list( $this->reservations->get_tables( true ) ),
			)
		);
	}

	/**
	 * Paginate a floor or table management list over AJAX.
	 */
	public function ajax_paginate_management_list(): void {
		$this->verify_ajax_request( 'foodord_paginate_reservation_management' );

		$list_type = sanitize_key( $this->get_post_text_field( 'list_type' ) );
		if ( 'floors' === $list_type ) {
			$html = $this->get_rendered_floors_list(
				$this->reservations->get_floors(),
				$this->reservations->get_tables( true )
			);
		} elseif ( 'tables' === $list_type ) {
			$html = $this->get_rendered_tables_list( $this->reservations->get_tables( true ) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Invalid request.', 'foodord' ) ), 400 );
		}

		wp_send_json_success( array( 'html' => $html ) );
	}

	/**
	 * Get available manual reservation times over AJAX.
	 */
	public function ajax_get_manual_reservation_times(): void {
		$this->verify_ajax_request( 'foodord_create_manual_reservation' );

		$party_size = absint( filter_input( INPUT_POST, 'party_size', FILTER_SANITIZE_NUMBER_INT ) );
		$options    = $this->operations->get_manual_time_options(
			$this->get_post_text_field( 'reservation_date' ),
			$party_size,
			false,
			Foodord_Table_Reservations::get_min_reservation_duration_minutes(),
			true
		);
		$times      = isset( $options['times'] ) && is_array( $options['times'] )
			? array_values( $options['times'] )
			: array();

		wp_send_json_success(
			array(
				'times' => $times,
				'slots' => isset( $options['slots'] ) && is_array( $options['slots'] ) ? array_values( $options['slots'] ) : array(),
			)
		);
	}

	/**
	 * Get selectable tables and duration limits for a manual reservation.
	 */
	public function ajax_get_manual_reservation_tables(): void {
		$this->verify_ajax_request( 'foodord_create_manual_reservation' );

		$options = $this->operations->get_manual_table_options(
			$this->get_post_text_field( 'reservation_date' ),
			$this->get_post_text_field( 'reservation_time' ),
			absint( filter_input( INPUT_POST, 'party_size', FILTER_SANITIZE_NUMBER_INT ) ),
			false,
			true
		);
		if ( is_wp_error( $options ) ) {
			wp_send_json_error( array( 'message' => $options->get_error_message() ), 409 );
		}

		$tables = array_map(
			function ( array $table ): array {
				$name       = sanitize_text_field( (string) ( $table['name'] ?? '' ) );
				$floor_name = sanitize_text_field( (string) ( $table['floor_name'] ?? '' ) );
				$durations  = array_map(
					function ( int $duration ): array {
						return array(
							'value' => $duration,
							'label' => $this->format_reservation_duration_option( $duration ),
						);
					},
					array_map( 'absint', (array) ( $table['duration_options'] ?? array() ) )
				);

				return array(
					'id'                       => absint( $table['id'] ?? 0 ),
					'label'                    => '' !== $floor_name ? $floor_name . ' - ' . $name : $name,
					'table_label'              => $name,
					'floor_label'              => $floor_name,
					'default_duration_minutes' => absint( $table['default_duration_minutes'] ?? 0 ),
					'duration_options'         => $durations,
				);
			},
			$options
		);

		wp_send_json_success( array( 'tables' => array_values( $tables ) ) );
	}

	/**
	 * Verify an AJAX reservation admin request.
	 *
	 * @param string $nonce_action Nonce action.
	 */
	private function verify_ajax_request( string $nonce_action ): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have sufficient permissions to access this page.', 'foodord' ) ), 403 );
		}

		if ( ! check_ajax_referer( $nonce_action, '_wpnonce', false ) ) {
			wp_send_json_error( array( 'message' => __( 'Invalid request.', 'foodord' ) ), 403 );
		}
	}

	/**
	 * Save a floor from the current request.
	 *
	 * @return int|WP_Error
	 */
	private function save_floor_from_request() {
		$floor_id = absint( filter_input( INPUT_POST, 'floor_id', FILTER_SANITIZE_NUMBER_INT ) );
		$floor    = $floor_id > 0 ? $this->reservations->get_floor( $floor_id ) : null;
		$data     = array(
			'name'       => $this->get_post_text_field( 'floor_name' ),
			'sort_order' => $floor ? (int) $floor->sort_order : 0,
		);

		$result = $floor_id > 0
			? $this->reservations->update_floor( $floor_id, $data )
			: $this->reservations->create_floor( $data );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return $floor_id > 0 ? $floor_id : (int) $result;
	}

	/**
	 * Save a reservation table from the current request.
	 *
	 * @return int|WP_Error
	 */
	private function save_table_from_request() {
		$table_id = absint( filter_input( INPUT_POST, 'table_id', FILTER_SANITIZE_NUMBER_INT ) );
		$table    = $table_id > 0 ? $this->reservations->get_table( $table_id ) : null;
		$data     = array(
			'floor_id'                     => absint( filter_input( INPUT_POST, 'floor_id', FILTER_SANITIZE_NUMBER_INT ) ),
			'name'                         => $this->get_post_text_field( 'table_name' ),
			'capacity'                     => absint( filter_input( INPUT_POST, 'table_capacity', FILTER_SANITIZE_NUMBER_INT ) ),
			'reservation_duration_minutes' => absint( filter_input( INPUT_POST, 'reservation_duration_minutes', FILTER_SANITIZE_NUMBER_INT ) ),
			'is_active'                    => true,
			'sort_order'                   => $table ? (int) $table->sort_order : 0,
		);

		$result = $table_id > 0
			? $this->reservations->update_table( $table_id, $data )
			: $this->reservations->create_table( $data );

		if ( is_wp_error( $result ) ) {
			return $result;
		}

		return $table_id > 0 ? $table_id : (int) $result;
	}

	/**
	 * Render floors list into a string.
	 *
	 * @param array<int,object> $floors Floors.
	 * @param array<int,object> $tables Reservation tables.
	 */
	private function get_rendered_floors_list( array $floors, array $tables ): string {
		ob_start();
		$this->render_floors_list( $floors, $tables );

		return (string) ob_get_clean();
	}

	/**
	 * Render table selection settings into a string.
	 */
	private function get_rendered_table_selection_settings_form(): string {
		ob_start();
		$this->render_table_selection_settings_form();

		return (string) ob_get_clean();
	}

	/**
	 * Render tables list into a string.
	 *
	 * @param array<int,object> $tables Reservation tables.
	 */
	private function get_rendered_tables_list( array $tables ): string {
		ob_start();
		$this->render_tables_list( $tables );

		return (string) ob_get_clean();
	}

	/**
	 * Render the Tables filters into a string.
	 *
	 * @param array<int,object> $floors Available floors.
	 * @param array<int,object> $tables Reservation tables.
	 */
	private function get_rendered_table_filters( array $floors, array $tables ): string {
		if ( empty( $tables ) ) {
			return '';
		}

		ob_start();
		$this->render_table_filters( $floors );

		return (string) ob_get_clean();
	}

	/**
	 * Get floor data for rebuilding table form options.
	 *
	 * @param array<int,object> $floors Floors.
	 * @return array<int,array{id:int,name:string}>
	 */
	private function get_floor_options_data( array $floors ): array {
		$options = array();

		foreach ( $floors as $floor ) {
			$options[] = array(
				'id'   => (int) $floor->id,
				'name' => $this->decode_stored_text( (string) $floor->name ),
			);
		}

		return $options;
	}

	/**
	 * Decode text that may have been saved with HTML entities by older admin requests.
	 *
	 * @param string $text Stored text.
	 */
	private function decode_stored_text( string $text ): string {
		return html_entity_decode( $text, ENT_QUOTES, 'UTF-8' );
	}

	/**
	 * Handle reservation banner settings.
	 */
	public function handle_save_banner(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_save_reservation_banner' );

		$is_general_settings         = '1' === $this->get_post_text_field( 'reservation_general_settings_submitted' );
		$is_booking_settings         = '1' === $this->get_post_text_field( 'reservation_booking_settings_submitted' );
		$is_deposit_settings         = '1' === $this->get_post_text_field( 'reservation_deposit_settings_submitted' );
		$is_preorder_settings        = '1' === $this->get_post_text_field( 'reservation_preorder_settings_submitted' );
		$is_security_settings        = '1' === $this->get_post_text_field( 'reservation_security_settings_submitted' );
		$is_table_selection_settings = '1' === $this->get_post_text_field( 'reservation_table_selection_settings_submitted' );

		if ( $is_general_settings ) {
			$image_id        = absint( filter_input( INPUT_POST, 'reservation_banner_image_id', FILTER_SANITIZE_NUMBER_INT ) );
			$banner_disabled = '1' === $this->get_post_text_field( 'reservation_banner_disabled' );
			if ( $image_id > 0 && ! wp_attachment_is_image( $image_id ) ) {
				$this->redirect_with_message( 'banner_error' );
			}

			update_option( self::OPTION_BANNER_IMAGE_ID, $image_id, false );
			update_option( self::OPTION_BANNER_DISABLED, $banner_disabled ? '1' : '0', false );
			Foodord_Table_Reservations::save_auto_confirm_enabled( '1' === $this->get_post_text_field( 'reservation_auto_confirm_enabled' ) );
			Foodord_Table_Reservations::save_customer_management_enabled( '1' === $this->get_post_text_field( 'reservation_customer_management_enabled' ) );
			Foodord_Table_Reservations::save_customer_cancellation_cutoff_minutes( $this->get_post_text_field( 'reservation_customer_cancellation_cutoff' ) );
			Foodord_Table_Reservations::save_privacy_settings(
				array(
					'enabled'         => '1' === $this->get_post_text_field( 'reservation_privacy_enabled' ),
					'statement'       => $this->get_post_textarea_field( 'reservation_privacy_statement' ),
					'privacy_page_id' => $this->get_post_text_field( 'reservation_privacy_page_id' ),
					'store_ip'        => '1' === $this->get_post_text_field( 'reservation_privacy_store_ip' ),
				)
			);
			Foodord_Table_Reservation_Emails::save_customer_content_settings( $this->get_post_email_content_settings() );
		}

		if ( $is_booking_settings ) {
			Foodord_Table_Reservations::save_booking_settings(
				array(
					'schedule'             => $this->get_post_array_field( 'reservation_booking_schedule' ),
					'holiday_ranges'       => $this->get_post_array_field( 'reservation_holiday_ranges' ),
					'maximum_advance_days' => $this->get_post_text_field( 'reservation_maximum_advance_days' ),
					'late_booking'         => $this->get_post_text_field( 'reservation_late_booking' ),
					'capacity_limits'      => array(
						'enabled'          => '1' === $this->get_post_text_field( 'reservation_capacity_limits_enabled' ),
						'max_reservations' => $this->get_post_text_field( 'reservation_capacity_max_reservations' ),
						'max_guests'       => $this->get_post_text_field( 'reservation_capacity_max_guests' ),
						'admin_override'   => '1' === $this->get_post_text_field( 'reservation_capacity_admin_override' ),
					),
				)
			);
		}

		if ( $is_deposit_settings ) {
			Foodord_Table_Reservations::save_deposit_settings(
				array(
					'enabled'    => '1' === $this->get_post_text_field( 'reservation_deposit_enabled' ),
					'type'       => $this->get_post_text_field( 'reservation_deposit_type' ),
					'amount'     => $this->get_post_text_field( 'reservation_deposit_amount' ),
					'applicable' => $this->get_post_text_field( 'reservation_deposit_applicable' ),
					'party_size' => $this->get_post_text_field( 'reservation_deposit_party_size' ),
					'schedule'   => $this->get_post_array_field( 'reservation_deposit_schedule' ),
				)
			);
		}

		if ( $is_preorder_settings ) {
			Foodord_Table_Reservation_Preorders::save_settings(
				array(
					'enabled'            => '1' === $this->get_post_text_field( 'reservation_preorder_enabled' ),
					'mode'               => $this->get_post_text_field( 'reservation_preorder_mode' ),
					'minimum_party_size' => $this->get_post_text_field( 'reservation_preorder_minimum_party_size' ),
					'cutoff_hours'       => $this->get_post_text_field( 'reservation_preorder_cutoff_hours' ),
					'applicable'         => $this->get_post_text_field( 'reservation_preorder_applicable' ),
					'schedule'           => $this->get_post_array_field( 'reservation_preorder_schedule' ),
				)
			);
		}

		if ( $is_security_settings ) {
			Foodord_Table_Reservations::save_recaptcha_settings(
				array(
					'enabled'    => '1' === $this->get_post_text_field( 'reservation_recaptcha_enabled' ),
					'site_key'   => $this->get_post_text_field( 'reservation_recaptcha_site_key' ),
					'secret_key' => $this->get_post_text_field( 'reservation_recaptcha_secret_key' ),
				)
			);
			Foodord_Table_Reservations::save_security_blocklist(
				array(
					'blocked_emails' => $this->get_post_textarea_field( 'reservation_blocked_emails' ),
					'blocked_ips'    => $this->get_post_textarea_field( 'reservation_blocked_ips' ),
				)
			);
		}

		if ( $is_table_selection_settings ) {
			$table_selection_settings = array(
				'enabled'          => '1' === $this->get_post_text_field( 'reservation_table_selection_enabled' ),
				'frontend_enabled' => '1' === $this->get_post_text_field( 'reservation_table_selection_frontend_enabled' ),
				'layouts'          => $this->get_post_json_array_field( 'reservation_table_selection_layouts' ),
			);
			Foodord_Table_Reservations::save_table_selection_settings( $table_selection_settings );
		}

		$this->redirect_with_message( 'banner_saved' );
	}

	/**
	 * Handle table deletion.
	 */
	public function handle_delete_table(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_delete_reservation_table' );

		$table_id = absint( filter_input( INPUT_POST, 'table_id', FILTER_SANITIZE_NUMBER_INT ) );
		$result   = $this->reservations->delete_table( $table_id );

		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'table_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'table_deleted' );
	}

	/**
	 * Handle manual reservation creation from admin.
	 */
	public function handle_create_manual_reservation(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_create_manual_reservation' );
		$actual_date = $this->get_post_text_field( 'reservation_actual_date' );
		$table_id    = absint( filter_input( INPUT_POST, 'table_id', FILTER_SANITIZE_NUMBER_INT ) );
		$duration    = absint( filter_input( INPUT_POST, 'duration_minutes', FILTER_SANITIZE_NUMBER_INT ) );
		if ( $table_id <= 0 || $duration <= 0 ) {
			$this->redirect_with_message( 'reservation_error', __( 'Please select a table and duration.', 'foodord' ) );
		}

		$result = $this->operations->create_manual_reservation(
			array(
				'date'              => '' !== $actual_date ? $actual_date : $this->get_post_text_field( 'reservation_date' ),
				'time'              => $this->get_post_text_field( 'reservation_time' ),
				'party_size'        => absint( filter_input( INPUT_POST, 'party_size', FILTER_SANITIZE_NUMBER_INT ) ),
				'table_id'          => $table_id,
				'duration_minutes'  => $duration,
				'status'            => $this->get_post_text_field( 'reservation_status' ),
				'name'              => $this->get_post_text_field( 'customer_name' ),
				'email'             => $this->get_post_text_field( 'customer_email' ),
				'phone'             => $this->get_post_text_field( 'customer_phone' ),
				'note'              => $this->get_post_textarea_field( 'customer_note' ),
				'send_notification' => '1' === $this->get_post_text_field( 'send_notification' ),
			),
			false,
			true
		);

		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'reservation_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'reservation_created' );
	}

	/**
	 * Handle reservation status update.
	 */
	public function handle_update_reservation_status(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_update_reservation_status' );

		$reservation_id = absint( filter_input( INPUT_POST, 'reservation_id', FILTER_SANITIZE_NUMBER_INT ) );
		$status         = $this->get_post_text_field( 'reservation_status' );
		$reason         = $this->get_post_cancellation_reason();
		$result         = $this->operations->update_status( $reservation_id, $status, $reason );

		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'reservation_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'reservation_updated' );
	}

	/**
	 * Resend the current customer status email for a reservation.
	 */
	public function handle_resend_reservation_status_email(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_resend_reservation_status_email' );

		$reservation_id = absint( filter_input( INPUT_POST, 'reservation_id', FILTER_SANITIZE_NUMBER_INT ) );
		$result         = $this->operations->resend_status_email( $reservation_id );
		if ( is_wp_error( $result ) ) {
			$this->redirect_with_message( 'reservation_error', $result->get_error_message() );
		}

		$this->redirect_with_message( 'reservation_email_sent' );
	}

	/**
	 * Check whether a customer status email can be sent manually.
	 *
	 * @param object $reservation Reservation row.
	 */
	private function can_send_customer_status_email( $reservation ): bool {
		return $this->operations->can_send_customer_status_email( $reservation );
	}

	/**
	 * Check whether a reservation is locked during customer deposit payment.
	 *
	 * @param object $reservation Reservation row.
	 */
	private function reservation_is_awaiting_payment( $reservation ): bool {
		return $this->operations->is_awaiting_payment( $reservation );
	}

	/**
	 * Check whether a reservation already ended.
	 *
	 * @param object $reservation Reservation row.
	 */
	private function reservation_has_ended( $reservation ): bool {
		return $this->operations->has_ended( $reservation );
	}

	/**
	 * Handle a bulk reservation action.
	 */
	public function handle_bulk_reservation_action(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		check_admin_referer( 'foodord_bulk_reservation_action' );

		$bulk_action = sanitize_key( $this->get_post_text_field( 'bulk_action' ) );
		$actions     = $this->get_bulk_reservation_actions();
		if ( ! isset( $actions[ $bulk_action ] ) ) {
			$this->redirect_with_bulk_message( 'reservation_error', __( 'Please select a bulk action.', 'foodord' ) );
		}

		$reservation_ids = array_values(
			array_unique(
				array_filter(
					array_map( 'absint', $this->get_post_array_field( 'reservation_ids' ) )
				)
			)
		);
		if ( empty( $reservation_ids ) ) {
			$this->redirect_with_bulk_message( 'reservation_error', __( 'Please select at least one reservation.', 'foodord' ) );
		}

		$status      = $this->get_bulk_reservation_status( $bulk_action );
		$processed   = 0;
		$skipped     = 0;
		$first_error = '';

		foreach ( $reservation_ids as $reservation_id ) {
			$previous = $this->reservations->get_reservation( $reservation_id );
			if ( ! $previous || $this->reservation_is_awaiting_payment( $previous ) ) {
				++$skipped;
				continue;
			}

			if ( 'delete' === $bulk_action ) {
				$result = $this->reservations->delete_reservation( $reservation_id );
			} else {
				$result = $this->reservations->update_reservation_status( $reservation_id, $status );
			}

			if ( is_wp_error( $result ) ) {
				++$skipped;
				if ( '' === $first_error ) {
					$first_error = $result->get_error_message();
				}
				continue;
			}

			++$processed;
			if ( 'delete' !== $bulk_action ) {
				$this->operations->maybe_send_status_email( $previous, $this->reservations->get_reservation( $reservation_id ) );
			}
		}

		if ( 0 === $processed ) {
			$this->redirect_with_bulk_message(
				'reservation_error',
				'' !== $first_error ? $first_error : __( 'No reservations were processed.', 'foodord' )
			);
		}

		if ( $skipped > 0 ) {
			$detail = sprintf(
				/* translators: 1: number of processed reservations, 2: number of skipped reservations. */
				_n( '%1$d reservation processed. %2$d skipped.', '%1$d reservations processed. %2$d skipped.', $processed, 'foodord' ),
				$processed,
				$skipped
			);
		} else {
			$detail = sprintf(
				/* translators: %d: number of processed reservations. */
				_n( '%d reservation processed.', '%d reservations processed.', $processed, 'foodord' ),
				$processed
			);
		}

		$this->redirect_with_bulk_message( 'reservation_bulk_completed', $detail );
	}

	/**
	 * Get available reservation bulk actions.
	 *
	 * @return array<string,string>
	 */
	private function get_bulk_reservation_actions(): array {
		return array(
			'mark_pending'   => __( 'Mark as pending', 'foodord' ),
			'confirm'        => __( 'Confirm', 'foodord' ),
			'mark_completed' => __( 'Mark as completed', 'foodord' ),
			'cancel'         => __( 'Cancel', 'foodord' ),
			'mark_no_show'   => __( 'Mark as no-show', 'foodord' ),
			'delete'         => __( 'Delete permanently', 'foodord' ),
		);
	}

	/**
	 * Resolve a bulk action to a reservation status.
	 *
	 * @param string $bulk_action Bulk action key.
	 */
	private function get_bulk_reservation_status( string $bulk_action ): string {
		$statuses = array(
			'mark_pending'   => 'pending',
			'confirm'        => 'confirmed',
			'mark_completed' => 'completed',
			'cancel'         => 'cancelled',
			'mark_no_show'   => 'no_show',
		);

		return $statuses[ $bulk_action ] ?? '';
	}

	/**
	 * Render Reservations admin page.
	 */
	public function render_page(): void {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'foodord' ) );
		}

		$edit_floor  = $this->get_edit_floor();
		$edit_table  = $this->get_edit_table();
		$floors      = $this->reservations->get_floors();
		$tables      = $this->reservations->get_tables( true );
		$query       = $this->get_reservations_query();
		$results     = $this->reservations->get_reservations( $query );
		$calendar    = $this->get_calendar_period( $query );
		$active_tab  = $edit_floor || $edit_table ? 'tables' : $this->get_active_reservation_tab();
		$quota       = class_exists( 'Foodord_Reservation_Quota' ) ? Foodord_Reservation_Quota::get_status() : array();
		$quota_full  = ! empty( $quota['known'] ) && empty( $quota['allowed'] );
		$license_url = function_exists( 'foodord_get_admin_page_url' )
			? foodord_get_admin_page_url( 'license' )
			: admin_url( 'admin.php?page=foodord-license' );
		?>
		<div class="wrap foodord-reservations-admin">
			<h1 class="foodord-reservations-admin__title"><?php esc_html_e( 'Reservations', 'foodord' ); ?></h1>
			<?php
			if ( function_exists( 'foodord_admin_render_horizontal_menu' ) ) {
				foodord_admin_render_horizontal_menu(
					array(
						'parent_slug' => function_exists( 'foodord_get_admin_parent_slug' ) ? foodord_get_admin_parent_slug() : 'foodord-settings',
					)
				);
			}
			$this->render_notice();
			?>
			<div class="notice is-dismissible foodord-reservations-ajax-notice" data-foodord-reservations-ajax-notice hidden>
				<p class="foodord-reservations-ajax-notice__message" data-foodord-reservations-ajax-notice-message></p>
			</div>

			<?php $this->render_reservation_tabs( $active_tab ); ?>

			<?php if ( 'dashboard' === $active_tab ) : ?>
				<?php $this->render_dashboard( $quota ); ?>
				<?php
				if ( function_exists( 'foodord_admin_render_faq_section' ) ) {
					foodord_admin_render_faq_section( 'reservations-dashboard' );
				}
				?>
			<?php endif; ?>

			<?php if ( 'reservations' === $active_tab ) : ?>
				<section class="foodord-reservations-panel">
					<?php if ( $quota_full ) : ?>
						<div class="notice notice-warning inline">
								<p class="foodord-reservations-quota-notice__message">
								<?php esc_html_e( 'Monthly reservation limit reached', 'foodord' ); ?>
								<a href="<?php echo esc_url( $license_url ); ?>"><?php esc_html_e( 'Open License settings', 'foodord' ); ?></a>
							</p>
						</div>
					<?php endif; ?>
					<div class="foodord-reservations-panel__header">
						<div class="foodord-reservations-panel__heading">
							<h2 class="foodord-reservations-panel__title">
								<span class="dashicons dashicons-calendar-alt foodord-reservations-panel__title-icon" aria-hidden="true"></span>
								<span><?php esc_html_e( 'Reservations', 'foodord' ); ?></span>
							</h2>
							<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Review incoming table reservation requests and update their status.', 'foodord' ); ?></p>
						</div>
						<div class="foodord-reservations-panel__actions">
							<button class="button button-primary foodord-reservations-manual-toggle" type="button" data-foodord-manual-reservation-open <?php disabled( $quota_full ); ?>>
								<span class="foodord-reservations-manual-toggle__icon" aria-hidden="true">+</span>
								<?php esc_html_e( 'Add Reservation', 'foodord' ); ?>
							</button>
							<?php $this->render_reservation_view_switcher( $query, $calendar ); ?>
						</div>
					</div>
					<?php
					$this->render_reservation_filters( $query );
					if ( 'calendar' === $query['view'] ) {
						$calendar_items = $this->reservations->get_reservations_for_range(
							array(
								'date_from' => $calendar['start'],
								'date_to'   => $calendar['end'],
								'status'    => $query['status'],
								'search'    => $query['search'],
							)
						);
						$this->render_reservations_calendar( $calendar_items, $calendar, $query );
					} else {
						$this->render_reservations_list( $results['items'], $query );
						$this->render_pagination( $results, $query );
					}
					?>
				</section>
				<?php $this->render_manual_reservation_modal(); ?>
			<?php endif; ?>

			<?php if ( 'tables' === $active_tab ) : ?>
				<section class="foodord-reservations-panel">
					<div class="foodord-reservations-panel__header">
						<div class="foodord-reservations-panel__heading">
							<h2 class="foodord-reservations-panel__title">
								<span class="dashicons dashicons-location-alt foodord-reservations-panel__title-icon" aria-hidden="true"></span>
								<span><?php esc_html_e( 'Floors', 'foodord' ); ?></span>
							</h2>
							<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Create restaurant areas such as ground floor, terrace, or garden before assigning tables.', 'foodord' ); ?></p>
						</div>
						<?php if ( ! $edit_floor ) : ?>
							<button
								type="button"
								class="button button-primary foodord-reservations-floor-toggle"
								aria-expanded="false"
								aria-controls="foodord-reservation-floor-panel"
								data-foodord-reservations-floor-toggle
							>
								<span class="foodord-reservations-floor-toggle__icon" aria-hidden="true">+</span>
								<?php esc_html_e( 'Add Floor', 'foodord' ); ?>
							</button>
						<?php endif; ?>
					</div>
					<div
						id="foodord-reservation-floor-panel"
						class="foodord-reservations-floor-panel"
						data-add-title="<?php echo esc_attr__( 'Add Floor', 'foodord' ); ?>"
						data-edit-title="<?php echo esc_attr__( 'Edit Floor', 'foodord' ); ?>"
						<?php if ( ! $edit_floor ) : ?>
							hidden
						<?php endif; ?>
						data-foodord-reservations-floor-panel
					>
						<div class="foodord-reservations-floor-panel__header">
							<h3 class="foodord-reservations-floor-panel__title"><?php echo $edit_floor ? esc_html__( 'Edit Floor', 'foodord' ) : esc_html__( 'Add Floor', 'foodord' ); ?></h3>
							<p class="foodord-reservations-floor-panel__description"><?php esc_html_e( 'Create the floors that can hold reservation tables.', 'foodord' ); ?></p>
						</div>
						<?php $this->render_floor_form( $edit_floor ); ?>
					</div>
					<div class="foodord-reservations-list-frame" data-foodord-reservation-floors-list aria-live="polite">
						<?php $this->render_floors_list( $floors, $tables ); ?>
					</div>
				</section>

				<section class="foodord-reservations-panel foodord-reservations-panel--primary">
					<div class="foodord-reservations-panel__header">
						<div class="foodord-reservations-panel__heading">
							<h2 class="foodord-reservations-panel__title">
								<span class="dashicons dashicons-editor-table foodord-reservations-panel__title-icon" aria-hidden="true"></span>
								<span><?php esc_html_e( 'Tables', 'foodord' ); ?></span>
							</h2>
							<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Manage the tables available for reservation holds.', 'foodord' ); ?></p>
						</div>
						<?php if ( ! $edit_table ) : ?>
							<button
								type="button"
								class="button button-primary foodord-reservations-table-toggle"
								aria-expanded="false"
								aria-controls="foodord-reservation-table-panel"
								data-foodord-reservations-table-toggle
								<?php if ( empty( $floors ) ) : ?>
									disabled
								<?php endif; ?>
							>
								<span class="foodord-reservations-table-toggle__icon" aria-hidden="true">+</span>
								<?php esc_html_e( 'Add Table', 'foodord' ); ?>
							</button>
						<?php endif; ?>
					</div>
					<div
						id="foodord-reservation-table-panel"
						class="foodord-reservations-table-panel"
						data-add-title="<?php echo esc_attr__( 'Add Table', 'foodord' ); ?>"
						data-edit-title="<?php echo esc_attr__( 'Edit Table', 'foodord' ); ?>"
						<?php if ( ! $edit_table ) : ?>
							hidden
						<?php endif; ?>
						data-foodord-reservations-table-panel
					>
						<div class="foodord-reservations-table-panel__header">
							<h3 class="foodord-reservations-table-panel__title"><?php echo $edit_table ? esc_html__( 'Edit Table', 'foodord' ) : esc_html__( 'Add Table', 'foodord' ); ?></h3>
							<p class="foodord-reservations-table-panel__description"><?php esc_html_e( 'Create the tables that can be held during reservations.', 'foodord' ); ?></p>
						</div>
						<?php $this->render_table_form( $edit_table, $floors ); ?>
					</div>
					<div class="foodord-reservations-table-filters" data-foodord-reservation-table-filters>
						<?php if ( ! empty( $tables ) ) : ?>
							<?php $this->render_table_filters( $floors ); ?>
						<?php endif; ?>
					</div>
					<div class="foodord-reservations-list-frame" data-foodord-reservation-tables-list aria-live="polite">
						<?php $this->render_tables_list( $tables ); ?>
					</div>
				</section>

				<?php $this->render_table_selection_settings_form(); ?>
				<div class="foodord-reservations-actions-bar">
					<?php submit_button( __( 'Save Changes', 'foodord' ), 'primary', 'submit', false, array( 'form' => 'foodord-reservation-table-selection-form' ) ); ?>
				</div>
			<?php endif; ?>

			<?php if ( 'booking-rules' === $active_tab ) : ?>
				<?php $this->render_booking_rules_form(); ?>
				<div class="foodord-reservations-actions-bar">
					<?php submit_button( __( 'Save Changes', 'foodord' ), 'primary', 'submit', false, array( 'form' => 'foodord-reservation-booking-form' ) ); ?>
				</div>
			<?php endif; ?>

			<?php if ( 'deposit' === $active_tab ) : ?>
				<?php $this->render_deposit_settings_form(); ?>
				<div class="foodord-reservations-actions-bar">
					<?php submit_button( __( 'Save Changes', 'foodord' ), 'primary', 'submit', false, array( 'form' => 'foodord-reservation-deposit-form' ) ); ?>
				</div>
			<?php endif; ?>

			<?php if ( 'preorder' === $active_tab ) : ?>
				<?php $this->render_preorder_settings_form(); ?>
				<div class="foodord-reservations-actions-bar">
					<?php submit_button( __( 'Save Changes', 'foodord' ), 'primary', 'submit', false, array( 'form' => 'foodord-reservation-preorder-form' ) ); ?>
				</div>
			<?php endif; ?>

			<?php if ( 'settings' === $active_tab ) : ?>
				<?php $this->render_banner_settings(); ?>
				<div class="foodord-reservations-actions-bar">
					<?php submit_button( __( 'Save Changes', 'foodord' ), 'primary', 'submit', false, array( 'form' => 'foodord-reservation-settings-form' ) ); ?>
				</div>
			<?php endif; ?>

			<?php if ( 'security' === $active_tab ) : ?>
				<?php $this->render_security_settings(); ?>
				<div class="foodord-reservations-actions-bar">
					<?php submit_button( __( 'Save Changes', 'foodord' ), 'primary', 'submit', false, array( 'form' => 'foodord-reservation-security-form' ) ); ?>
				</div>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Render the Reservations plan dashboard.
	 *
	 * @param array<string,mixed> $quota Current central quota snapshot.
	 */
	private function render_dashboard( array $quota ): void {
		$free_limit      = ! empty( $quota['limit'] ) ? absint( $quota['limit'] ) : 25;
		$pricing_url     = 'https://www.foodord.com/pricing/';
		$video_embed_url = 'https://www.youtube-nocookie.com/embed/hDgV48YJKKs?rel=0';
		?>
		<section class="foodord-reservations-dashboard" data-foodord-reservation-dashboard>
			<header class="foodord-reservations-dashboard__header">
				<p class="foodord-reservations-dashboard__eyebrow"><?php esc_html_e( 'Reservation plans', 'foodord' ); ?></p>
				<h2 class="foodord-reservations-dashboard__title"><?php esc_html_e( 'Choose the plan that matches your reservation volume', 'foodord' ); ?></h2>
				<p class="foodord-reservations-dashboard__description"><?php esc_html_e( 'Start with the essentials, then remove the monthly limit whenever your restaurant needs more capacity.', 'foodord' ); ?></p>
			</header>

			<div class="foodord-reservations-dashboard__billing" role="group" aria-label="<?php echo esc_attr__( 'Billing cycle', 'foodord' ); ?>">
				<button class="foodord-reservations-dashboard__billing-button is-active" type="button" aria-pressed="true" data-foodord-reservation-billing-cycle="monthly">
					<?php esc_html_e( 'Monthly', 'foodord' ); ?>
				</button>
				<button class="foodord-reservations-dashboard__billing-button" type="button" aria-pressed="false" data-foodord-reservation-billing-cycle="yearly">
					<?php esc_html_e( 'Yearly', 'foodord' ); ?>
				</button>
			</div>

			<div class="foodord-reservations-dashboard__plans">
				<article class="foodord-reservations-plan">
					<div class="foodord-reservations-plan__header">
						<p class="foodord-reservations-plan__name"><?php esc_html_e( 'Free', 'foodord' ); ?></p>
						<h3 class="foodord-reservations-plan__title"><?php esc_html_e( 'Essential reservation tools', 'foodord' ); ?></h3>
						<p class="foodord-reservations-plan__description"><?php esc_html_e( 'A practical starting point for restaurants accepting a steady number of bookings.', 'foodord' ); ?></p>
					</div>
					<div class="foodord-reservations-plan__price">
						<span class="foodord-reservations-plan__amount">$0</span>
						<span class="foodord-reservations-plan__period"><?php esc_html_e( 'forever', 'foodord' ); ?></span>
					</div>
					<ul class="foodord-reservations-plan__features">
						<li>
							<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>
							<?php
							echo esc_html(
								sprintf(
									/* translators: %d: monthly reservation allowance. */
									__( '%d online reservations each month', 'foodord' ),
									$free_limit
								)
							);
							?>
						</li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Reservation requests and status management', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Tables, floors, and booking schedules', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Customer email notifications', 'foodord' ); ?></li>
					</ul>
					<div class="foodord-reservations-plan__status">
						<span class="dashicons dashicons-yes-alt" aria-hidden="true"></span>
						<?php esc_html_e( 'Included with FoodOrd', 'foodord' ); ?>
					</div>
				</article>

				<article class="foodord-reservations-plan foodord-reservations-plan--unlimited">
					<div class="foodord-reservations-plan__header">
						<p class="foodord-reservations-plan__name"><?php esc_html_e( 'Unlimited', 'foodord' ); ?></p>
						<h3 class="foodord-reservations-plan__title"><?php esc_html_e( 'Reservations without monthly limits', 'foodord' ); ?></h3>
						<p class="foodord-reservations-plan__description"><?php esc_html_e( 'Built for active restaurants that need room to grow without watching a counter.', 'foodord' ); ?></p>
					</div>
					<div class="foodord-reservations-plan__price" data-foodord-reservation-billing-price="monthly">
						<span class="foodord-reservations-plan__amount">$19</span>
						<span class="foodord-reservations-plan__period"><?php esc_html_e( 'per month', 'foodord' ); ?></span>
					</div>
					<div class="foodord-reservations-plan__price" data-foodord-reservation-billing-price="yearly" hidden>
						<span class="foodord-reservations-plan__amount">$199</span>
						<span class="foodord-reservations-plan__period"><?php esc_html_e( 'per year', 'foodord' ); ?></span>
					</div>
					<ul class="foodord-reservations-plan__features">
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Unlimited online reservations', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Everything available in the Free plan', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Desktop app access for restaurant staff', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Deposit and pre-order workflows', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes-alt" aria-hidden="true"></span><?php esc_html_e( 'Floor plans and customer table selection', 'foodord' ); ?></li>
					</ul>
					<div class="foodord-reservations-plan__action">
						<button class="foodord-reservations-plan__button" type="button" data-foodord-reservation-pricing-url="<?php echo esc_url( $pricing_url ); ?>">
							<?php esc_html_e( 'Select', 'foodord' ); ?>
							<span class="dashicons dashicons-arrow-right-alt2" aria-hidden="true"></span>
						</button>
					</div>
				</article>
			</div>

			<div class="foodord-reservations-dashboard__benefits">
				<div class="foodord-reservations-dashboard__terms">
					<div class="foodord-reservations-dashboard__terms-heading">
						<span class="dashicons dashicons-store" aria-hidden="true"></span>
						<h3 class="foodord-reservations-dashboard__benefits-title"><?php esc_html_e( 'Simple terms for independent restaurants', 'foodord' ); ?></h3>
					</div>
					<ul>
						<li><span class="dashicons dashicons-yes" aria-hidden="true"></span><?php esc_html_e( 'No commission on reservations', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes" aria-hidden="true"></span><?php esc_html_e( 'Use your existing WooCommerce payment methods', 'foodord' ); ?></li>
						<li><span class="dashicons dashicons-yes" aria-hidden="true"></span><?php esc_html_e( 'Cancel your subscription at any time', 'foodord' ); ?></li>
					</ul>
				</div>
				<div class="foodord-reservations-dashboard__assurance">
					<div class="foodord-reservations-dashboard__assurance-heading">
						<span class="dashicons dashicons-shield-alt" aria-hidden="true"></span>
						<h3 class="foodord-reservations-dashboard__benefits-title"><?php esc_html_e( 'Straightforward billing', 'foodord' ); ?></h3>
					</div>
					<p class="foodord-reservations-dashboard__assurance-description"><?php esc_html_e( 'Choose monthly flexibility or save with one annual payment. Your reservation data stays in WordPress.', 'foodord' ); ?></p>
				</div>
			</div>

			<section class="foodord-reservations-dashboard__video-guide" aria-labelledby="foodord-reservations-video-guide-title">
				<div class="foodord-reservations-dashboard__video-copy">
					<p class="foodord-reservations-dashboard__video-eyebrow">
						<span class="dashicons dashicons-video-alt3" aria-hidden="true"></span>
						<?php esc_html_e( 'Quick setup guide', 'foodord' ); ?>
					</p>
					<h3 id="foodord-reservations-video-guide-title" class="foodord-reservations-dashboard__video-title"><?php esc_html_e( 'Create your table reservation page', 'foodord' ); ?></h3>
					<p class="foodord-reservations-dashboard__video-description"><?php esc_html_e( 'Watch this short guide to add the reservation page and prepare it for customer bookings.', 'foodord' ); ?></p>
				</div>
				<div class="foodord-reservations-dashboard__video-media">
					<iframe
						src="<?php echo esc_url( $video_embed_url ); ?>"
						title="<?php echo esc_attr__( 'How to create a table reservation page', 'foodord' ); ?>"
						loading="lazy"
						referrerpolicy="strict-origin-when-cross-origin"
						allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
						allowfullscreen
					></iframe>
				</div>
			</section>

			<footer class="foodord-reservations-dashboard__footer">
				<p class="foodord-reservations-dashboard__footer-note"><?php esc_html_e( 'The Free allowance resets at the beginning of each calendar month. Unlimited access remains active while your subscription is valid.', 'foodord' ); ?></p>
				<p class="foodord-reservations-dashboard__footer-note"><?php esc_html_e( 'Subscriptions renew automatically unless cancelled. Taxes may apply according to your billing location.', 'foodord' ); ?></p>
				<div class="foodord-reservations-dashboard__powered">
					<span><?php esc_html_e( 'Payments powered by', 'foodord' ); ?></span>
					<strong><?php esc_html_e( 'Lemon Squeezy', 'foodord' ); ?></strong>
				</div>
			</footer>
		</section>
		<?php
	}

	/**
	 * Render security settings.
	 */
	private function render_security_settings(): void {
		$settings  = Foodord_Table_Reservations::get_recaptcha_settings();
		$blocklist = Foodord_Table_Reservations::get_security_blocklist();
		?>
		<form id="foodord-reservation-security-form" class="foodord-reservations-security-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" autocomplete="off" data-form-type="other">
			<?php wp_nonce_field( 'foodord_save_reservation_banner' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_banner" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="security" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_security_settings_submitted" value="1" />

			<section class="foodord-reservations-panel foodord-reservations-panel--security">
				<div class="foodord-reservations-panel__header">
					<div class="foodord-reservations-panel__heading">
						<h2 class="foodord-reservations-panel__title">
							<span class="dashicons dashicons-shield-alt foodord-reservations-panel__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Security', 'foodord' ); ?></span>
						</h2>
						<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Configure protection options for table reservations.', 'foodord' ); ?></p>
					</div>
				</div>

				<label class="foodord-reservations-auto-confirm foodord-reservations-security-toggle" for="foodord-reservation-recaptcha-enabled">
					<span class="foodord-reservations-auto-confirm__content">
						<span class="foodord-reservations-auto-confirm__title">
							<span class="dashicons dashicons-shield-alt foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Enable reCAPTCHA', 'foodord' ); ?></span>
						</span>
						<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Protect reservation holds and submissions with Google reCAPTCHA v3.', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__toggle">
						<input
							id="foodord-reservation-recaptcha-enabled"
							class="foodord-reservations-auto-confirm__toggle-input"
							type="checkbox"
							name="reservation_recaptcha_enabled"
							value="1"
							<?php checked( $settings['enabled'] ); ?>
						/>
						<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
					</span>
				</label>

				<div class="foodord-reservations-security-grid">
					<label class="foodord-reservations-field" for="foodord-reservation-recaptcha-site-key">
						<span><?php esc_html_e( 'Site Key', 'foodord' ); ?></span>
						<input id="foodord-reservation-recaptcha-site-key" type="text" name="reservation_recaptcha_site_key" value="<?php echo esc_attr( $settings['site_key'] ); ?>" autocomplete="one-time-code" autocapitalize="none" spellcheck="false" data-1p-ignore data-bwignore data-lpignore="true" data-form-type="other" />
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-recaptcha-secret-key">
						<span><?php esc_html_e( 'Secret Key', 'foodord' ); ?></span>
						<input id="foodord-reservation-recaptcha-secret-key" type="password" name="reservation_recaptcha_secret_key" value="<?php echo esc_attr( $settings['secret_key'] ); ?>" autocomplete="new-password" autocapitalize="none" spellcheck="false" data-1p-ignore data-bwignore data-lpignore="true" data-form-type="other" />
					</label>
				</div>
			</section>

			<section class="foodord-reservations-panel foodord-reservations-panel--security-blocklist">
				<div class="foodord-reservations-panel__header">
					<div class="foodord-reservations-panel__heading">
						<h2 class="foodord-reservations-panel__title">
							<span class="dashicons dashicons-no foodord-reservations-panel__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Reservation Blocklist', 'foodord' ); ?></span>
						</h2>
						<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Block specific email addresses, domains, or IP addresses from creating reservations.', 'foodord' ); ?></p>
					</div>
				</div>

				<div class="foodord-reservations-security-blocklist">
					<label class="foodord-reservations-field" for="foodord-reservation-blocked-emails">
						<span><?php esc_html_e( 'Blocked Emails / Domains', 'foodord' ); ?></span>
						<textarea id="foodord-reservation-blocked-emails" name="reservation_blocked_emails" rows="6" spellcheck="false"><?php echo esc_textarea( implode( "\n", $blocklist['blocked_emails'] ) ); ?></textarea>
						<span class="foodord-reservations-field__description"><?php esc_html_e( 'Enter one email address or domain per line. Use @example.com to block a full domain.', 'foodord' ); ?></span>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-blocked-ips">
						<span><?php esc_html_e( 'Blocked IP Addresses', 'foodord' ); ?></span>
						<textarea id="foodord-reservation-blocked-ips" name="reservation_blocked_ips" rows="6" spellcheck="false"><?php echo esc_textarea( implode( "\n", $blocklist['blocked_ips'] ) ); ?></textarea>
						<span class="foodord-reservations-field__description"><?php esc_html_e( 'Enter one IP address per line.', 'foodord' ); ?></span>
					</label>
				</div>
			</section>
		</form>
		<?php
	}

	/**
	 * Render reservation page banner settings.
	 */
	private function render_banner_settings(): void {
		$image_id           = $this->get_banner_image_id();
		$default_url        = $this->get_default_banner_image_url();
		$is_banner_disabled = $this->is_banner_disabled();
		$image_url          = $is_banner_disabled ? '' : $this->get_banner_image_url( $image_id );
		$preview_url        = '' !== $image_url ? $image_url : $default_url;
		$preview_class      = 'foodord-reservations-banner-form__preview' . ( $is_banner_disabled ? ' is-empty' : '' );
		?>
		<form id="foodord-reservation-settings-form" class="foodord-reservations-banner-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-banner-picker data-default-url="<?php echo esc_url( $default_url ); ?>" data-title="<?php echo esc_attr__( 'Select reservation banner', 'foodord' ); ?>" data-button="<?php echo esc_attr__( 'Use this image', 'foodord' ); ?>">
			<?php wp_nonce_field( 'foodord_save_reservation_banner' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_banner" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="settings" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_general_settings_submitted" value="1" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_banner_image_id" value="<?php echo esc_attr( $image_id ); ?>" data-foodord-reservation-banner-image-id />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_banner_disabled" value="<?php echo esc_attr( $is_banner_disabled ? '1' : '0' ); ?>" data-foodord-reservation-banner-disabled />

			<section class="foodord-reservations-panel foodord-reservations-panel--banner">
				<div class="foodord-reservations-banner-form__body">
					<div class="<?php echo esc_attr( $preview_class ); ?>">
						<img src="<?php echo esc_url( $preview_url ); ?>" alt="" data-foodord-reservation-banner-preview />
						<span class="foodord-reservations-banner-form__placeholder"><?php esc_html_e( 'No banner selected', 'foodord' ); ?></span>
					</div>

					<div class="foodord-reservations-banner-form__content">
						<div class="foodord-reservations-banner-form__heading">
							<h2 class="foodord-reservations-panel__title">
								<span class="dashicons dashicons-format-image foodord-reservations-panel__title-icon" aria-hidden="true"></span>
								<span><?php esc_html_e( 'Reservation page banner', 'foodord' ); ?></span>
							</h2>
							<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Choose the image shown next to the reservation form.', 'foodord' ); ?></p>
						</div>

						<div class="foodord-reservations-banner-form__actions">
							<button type="button" class="button button-secondary" data-foodord-reservation-banner-select>
								<?php esc_html_e( 'Select image', 'foodord' ); ?>
							</button>
							<button type="button" class="button button-secondary" data-foodord-reservation-banner-remove>
								<?php esc_html_e( 'Remove image', 'foodord' ); ?>
							</button>
						</div>
					</div>
				</div>
			</section>

			<div class="foodord-reservations-settings-grid">
				<?php $this->render_auto_confirm_settings(); ?>
				<?php $this->render_customer_management_settings(); ?>
			</div>

			<?php $this->render_customer_cancellation_settings(); ?>
			<?php $this->render_privacy_settings(); ?>
			<?php $this->render_email_content_settings(); ?>

		</form>
		<?php
	}

	/**
	 * Render booking rules form.
	 */
	private function render_booking_rules_form(): void {
		?>
		<form id="foodord-reservation-booking-form" class="foodord-reservations-booking-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
			<?php wp_nonce_field( 'foodord_save_reservation_banner' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_banner" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="booking-rules" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_booking_settings_submitted" value="1" />
			<?php $this->render_booking_settings(); ?>
		</form>
		<?php
	}

	/**
	 * Render deposit settings form.
	 */
	private function render_deposit_settings_form(): void {
		$settings        = Foodord_Table_Reservations::get_deposit_settings();
		$type_options    = Foodord_Table_Reservations::get_deposit_type_options();
		$applicable      = Foodord_Table_Reservations::get_deposit_applicable_options();
		$currency_symbol = function_exists( 'get_woocommerce_currency_symbol' ) ? get_woocommerce_currency_symbol() : '';
		$weekdays        = $this->get_weekday_labels();
		$show_schedule   = 'specific_times' === $settings['applicable'];
		?>
		<form id="foodord-reservation-deposit-form" class="foodord-reservations-deposit-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-deposit-settings>
			<?php wp_nonce_field( 'foodord_save_reservation_banner' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_banner" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="deposit" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_deposit_settings_submitted" value="1" />

			<section class="foodord-reservations-panel foodord-reservations-panel--deposit">
				<label class="foodord-reservations-auto-confirm foodord-reservations-deposit-toggle" for="foodord-reservation-deposit-enabled">
					<span class="foodord-reservations-auto-confirm__content">
						<span class="foodord-reservations-auto-confirm__title">
							<span class="dashicons dashicons-money foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Enable Deposit', 'foodord' ); ?></span>
						</span>
						<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Require an online payment before a reservation is accepted.', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__toggle">
						<input
							id="foodord-reservation-deposit-enabled"
							class="foodord-reservations-auto-confirm__toggle-input"
							type="checkbox"
							name="reservation_deposit_enabled"
							value="1"
							<?php checked( $settings['enabled'] ); ?>
						/>
						<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
					</span>
				</label>

				<div class="foodord-reservations-deposit-grid">
					<label class="foodord-reservations-field" for="foodord-reservation-deposit-type">
						<span><?php esc_html_e( 'Deposit Type', 'foodord' ); ?></span>
						<select id="foodord-reservation-deposit-type" name="reservation_deposit_type">
							<?php foreach ( $type_options as $type => $label ) : ?>
								<option value="<?php echo esc_attr( $type ); ?>" <?php selected( $settings['type'], $type ); ?>>
									<?php echo esc_html( $label ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-deposit-amount">
						<span><?php esc_html_e( 'Deposit Amount', 'foodord' ); ?></span>
						<span class="foodord-reservations-deposit-amount">
							<?php if ( '' !== $currency_symbol ) : ?>
								<span class="foodord-reservations-deposit-amount__currency"><?php echo esc_html( $currency_symbol ); ?></span>
							<?php endif; ?>
							<input id="foodord-reservation-deposit-amount" type="number" name="reservation_deposit_amount" value="<?php echo esc_attr( (string) $settings['amount'] ); ?>" min="0" step="0.01" inputmode="decimal" />
						</span>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-deposit-applicable">
						<span><?php esc_html_e( 'Deposit Applicable', 'foodord' ); ?></span>
						<select id="foodord-reservation-deposit-applicable" name="reservation_deposit_applicable" data-foodord-reservation-deposit-applicable>
							<?php foreach ( $applicable as $key => $label ) : ?>
								<option value="<?php echo esc_attr( $key ); ?>" <?php selected( $settings['applicable'], $key ); ?>>
									<?php echo esc_html( $label ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-deposit-party-size" data-foodord-reservation-deposit-party-size-field>
						<span><?php esc_html_e( 'Deposit Applicable Party Size', 'foodord' ); ?></span>
						<input id="foodord-reservation-deposit-party-size" type="number" name="reservation_deposit_party_size" value="<?php echo esc_attr( (string) $settings['party_size'] ); ?>" min="1" step="1" />
						<span class="foodord-reservations-field__description"><?php esc_html_e( 'Deposit applies when the guest count is this number or higher.', 'foodord' ); ?></span>
					</label>
				</div>
			</section>

			<section
				class="foodord-reservations-panel foodord-reservations-panel--deposit-schedule"
				data-foodord-reservation-deposit-schedule
				<?php if ( ! $show_schedule ) : ?>
					hidden
				<?php endif; ?>
			>
				<div class="foodord-reservations-panel__header">
					<div class="foodord-reservations-panel__heading">
						<h2 class="foodord-reservations-panel__title">
							<span class="dashicons dashicons-clock foodord-reservations-panel__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Specific Days/Times', 'foodord' ); ?></span>
						</h2>
						<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Apply deposits only during selected days and time ranges.', 'foodord' ); ?></p>
					</div>
				</div>
				<div class="foodord-reservations-schedule" data-foodord-reservation-schedule-settings>
					<?php foreach ( $weekdays as $day_index => $day_label ) : ?>
						<?php $this->render_deposit_day( (int) $day_index, (string) $day_label, $settings['schedule'][ $day_index ] ); ?>
					<?php endforeach; ?>
				</div>
			</section>
		</form>
		<?php
	}

	/**
	 * Render reservation pre-order settings.
	 */
	private function render_preorder_settings_form(): void {
		$settings      = Foodord_Table_Reservation_Preorders::get_settings();
		$mode_options  = Foodord_Table_Reservation_Preorders::get_mode_options();
		$applicability = Foodord_Table_Reservation_Preorders::get_applicability_options();
		$weekdays      = $this->get_weekday_labels();
		$show_schedule = 'specific_times' === $settings['applicable'];
		?>
		<form id="foodord-reservation-preorder-form" class="foodord-reservations-preorder-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-preorder-settings>
			<?php wp_nonce_field( 'foodord_save_reservation_banner' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_banner" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="preorder" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_preorder_settings_submitted" value="1" />

			<section class="foodord-reservations-panel foodord-reservations-panel--preorder">
				<label class="foodord-reservations-auto-confirm foodord-reservations-preorder-toggle" for="foodord-reservation-preorder-enabled">
					<span class="foodord-reservations-auto-confirm__content">
						<span class="foodord-reservations-auto-confirm__title">
							<span class="dashicons dashicons-carrot foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Enable Pre-order', 'foodord' ); ?></span>
						</span>
						<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Allow guests to choose and pay for food while making a table reservation.', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__toggle">
						<input
							id="foodord-reservation-preorder-enabled"
							class="foodord-reservations-auto-confirm__toggle-input"
							type="checkbox"
							name="reservation_preorder_enabled"
							value="1"
							<?php checked( $settings['enabled'] ); ?>
						/>
						<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
					</span>
				</label>

				<div class="foodord-reservations-preorder-grid">
					<label class="foodord-reservations-field" for="foodord-reservation-preorder-mode">
						<span><?php esc_html_e( 'Pre-order Mode', 'foodord' ); ?></span>
						<select id="foodord-reservation-preorder-mode" name="reservation_preorder_mode">
							<?php foreach ( $mode_options as $mode => $label ) : ?>
								<option value="<?php echo esc_attr( $mode ); ?>" <?php selected( $settings['mode'], $mode ); ?>>
									<?php echo esc_html( $label ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-preorder-minimum-party-size">
						<span><?php esc_html_e( 'Minimum Party Size', 'foodord' ); ?></span>
						<input id="foodord-reservation-preorder-minimum-party-size" type="number" name="reservation_preorder_minimum_party_size" value="<?php echo esc_attr( (string) $settings['minimum_party_size'] ); ?>" min="1" max="999" step="1" />
						<span class="foodord-reservations-field__description"><?php esc_html_e( 'Show pre-order options when the guest count reaches this number.', 'foodord' ); ?></span>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-preorder-cutoff-hours">
						<span class="foodord-reservations-field__label">
							<?php esc_html_e( 'Pre-order Cutoff', 'foodord' ); ?>
							<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'Defines how long before the reservation time guests must complete their pre-order.', 'foodord' ); ?>">
								<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
							</span>
						</span>
						<select id="foodord-reservation-preorder-cutoff-hours" name="reservation_preorder_cutoff_hours">
							<?php foreach ( Foodord_Table_Reservation_Preorders::get_cutoff_options() as $hours ) : ?>
								<option value="<?php echo esc_attr( $hours ); ?>" <?php selected( $settings['cutoff_hours'], $hours ); ?>>
									<?php
									if ( $hours > 24 && 0 === $hours % 24 ) {
										$days = (int) ( $hours / 24 );
										echo esc_html(
											sprintf(
												/* translators: %d: pre-order cutoff in days. */
												_n( '%d day', '%d days', $days, 'foodord' ),
												$days
											)
										);
									} else {
										echo esc_html(
											sprintf(
												/* translators: %d: pre-order cutoff in hours. */
												_n( '%d hour', '%d hours', $hours, 'foodord' ),
												$hours
											)
										);
									}
									?>
								</option>
							<?php endforeach; ?>
						</select>
					</label>

					<label class="foodord-reservations-field" for="foodord-reservation-preorder-applicable">
						<span><?php esc_html_e( 'Pre-order Availability', 'foodord' ); ?></span>
						<select id="foodord-reservation-preorder-applicable" name="reservation_preorder_applicable" data-foodord-reservation-preorder-applicable>
							<?php foreach ( $applicability as $value => $label ) : ?>
								<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $settings['applicable'], $value ); ?>>
									<?php echo esc_html( $label ); ?>
								</option>
							<?php endforeach; ?>
						</select>
					</label>
				</div>
			</section>

			<section
				class="foodord-reservations-panel foodord-reservations-panel--preorder-schedule"
				data-foodord-reservation-preorder-schedule
				<?php if ( ! $show_schedule ) : ?>
					hidden
				<?php endif; ?>
			>
				<div class="foodord-reservations-panel__header">
					<div class="foodord-reservations-panel__heading">
						<h2 class="foodord-reservations-panel__title">
							<span class="dashicons dashicons-clock foodord-reservations-panel__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Specific Days/Times', 'foodord' ); ?></span>
						</h2>
						<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Offer pre-orders only during selected days and time ranges.', 'foodord' ); ?></p>
					</div>
				</div>
				<div class="foodord-reservations-schedule" data-foodord-reservation-schedule-settings>
					<?php foreach ( $weekdays as $day_index => $day_label ) : ?>
						<?php $this->render_preorder_day( (int) $day_index, (string) $day_label, $settings['schedule'][ $day_index ] ); ?>
					<?php endforeach; ?>
				</div>
			</section>
		</form>
		<?php
	}

	/**
	 * Render floor plan and customer table selection settings.
	 */
	private function render_table_selection_settings_form(): void {
		$settings        = Foodord_Table_Reservations::get_table_selection_settings();
		$floors          = $this->reservations->get_floors();
		$tables          = $this->reservations->get_tables( true );
		$tables_by_floor = array();
		$layouts_json    = wp_json_encode( $settings['layouts'] );

		foreach ( $tables as $table ) {
			$floor_id = absint( $table->floor_id ?? 0 );
			if ( $floor_id <= 0 ) {
				continue;
			}

			if ( ! isset( $tables_by_floor[ $floor_id ] ) ) {
				$tables_by_floor[ $floor_id ] = array();
			}

			$tables_by_floor[ $floor_id ][] = $table;
		}
		?>
		<form id="foodord-reservation-table-selection-form" class="foodord-reservations-table-selection-form<?php echo esc_attr( $settings['enabled'] ? ' is-enabled' : '' ); ?>" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-table-selection>
			<?php wp_nonce_field( 'foodord_save_reservation_banner' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_banner" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_table_selection_settings_submitted" value="1" />
			<textarea class="foodord-reservations-hidden-field" name="reservation_table_selection_layouts" hidden data-foodord-reservation-table-selection-layouts><?php echo esc_textarea( is_string( $layouts_json ) ? $layouts_json : '{}' ); ?></textarea>

			<section class="foodord-reservations-panel foodord-reservations-panel--table-selection">
				<label class="foodord-reservations-auto-confirm" for="foodord-reservation-table-selection-enabled">
					<span class="foodord-reservations-auto-confirm__content">
						<span class="foodord-reservations-auto-confirm__title">
							<span class="dashicons dashicons-layout foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Enable floor plan', 'foodord' ); ?></span>
						</span>
						<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Make configured floor plans available to restaurant staff.', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__toggle">
						<input
							id="foodord-reservation-table-selection-enabled"
							class="foodord-reservations-auto-confirm__toggle-input"
							type="checkbox"
							name="reservation_table_selection_enabled"
							value="1"
							data-foodord-reservation-table-selection-enabled
							<?php checked( $settings['enabled'] ); ?>
						/>
						<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
					</span>
				</label>

				<div
					class="foodord-reservations-table-selection__floor-plans"
					data-foodord-reservation-floor-plans
					<?php if ( ! $settings['enabled'] ) : ?>
						hidden
					<?php endif; ?>
				>
				<label class="foodord-reservations-auto-confirm foodord-reservations-table-selection__frontend-toggle" for="foodord-reservation-table-selection-frontend-enabled">
					<span class="foodord-reservations-auto-confirm__content">
						<span class="foodord-reservations-auto-confirm__title">
							<span class="dashicons dashicons-groups foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Show floor plan to customers', 'foodord' ); ?></span>
						</span>
						<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'When enabled, customers can choose a table from the floor plan during reservation.', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__toggle">
						<input
							id="foodord-reservation-table-selection-frontend-enabled"
							class="foodord-reservations-auto-confirm__toggle-input"
							type="checkbox"
							name="reservation_table_selection_frontend_enabled"
							value="1"
							data-foodord-reservation-table-selection-frontend-enabled
							<?php checked( $settings['frontend_enabled'] ); ?>
						/>
						<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
					</span>
				</label>

				<div class="foodord-reservations-panel__header">
					<div class="foodord-reservations-panel__heading">
						<h2 class="foodord-reservations-panel__title">
							<span class="dashicons dashicons-layout foodord-reservations-panel__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Floor plans', 'foodord' ); ?></span>
						</h2>
						<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Upload an image or build each floor plan on the grid, then position its tables.', 'foodord' ); ?></p>
					</div>
				</div>

				<?php if ( empty( $floors ) ) : ?>
					<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Add a floor and its tables before configuring the floor plan.', 'foodord' ); ?></p>
				<?php else : ?>
					<div class="foodord-reservations-floor-plans" data-foodord-reservation-floor-plans-root>
						<div class="foodord-reservations-floor-plans__tabs" role="tablist" aria-label="<?php echo esc_attr__( 'Floor plans', 'foodord' ); ?>">
							<?php foreach ( $floors as $floor_index => $floor ) : ?>
								<button
									class="foodord-reservations-floor-plans__tab<?php echo esc_attr( 0 === $floor_index ? ' is-active' : '' ); ?>"
									type="button"
									role="tab"
									aria-selected="<?php echo esc_attr( 0 === $floor_index ? 'true' : 'false' ); ?>"
									data-foodord-reservation-floor-plan-tab="<?php echo esc_attr( (string) $floor->id ); ?>"
								>
									<?php echo esc_html( (string) $floor->name ); ?>
								</button>
							<?php endforeach; ?>
						</div>

						<?php foreach ( $floors as $floor_index => $floor ) : ?>
							<?php
							$floor_id     = absint( $floor->id );
							$layout       = $settings['layouts'][ $floor_id ] ?? array();
							$plan_mode    = 'grid' === ( $layout['mode'] ?? 'image' ) ? 'grid' : 'image';
							$grid_density = 'fine' === ( $layout['grid_density'] ?? 'coarse' ) ? 'fine' : 'coarse';
							$image_id     = absint( $layout['image_id'] ?? 0 );
							$image_url    = $image_id > 0 && wp_attachment_is_image( $image_id ) ? wp_get_attachment_image_url( $image_id, 'large' ) : '';
							$shape_labels = array(
								'rectangle' => __( 'Rectangle', 'foodord' ),
								'circle'    => __( 'Circle', 'foodord' ),
								'line'      => __( 'Line', 'foodord' ),
								'text'      => __( 'Text', 'foodord' ),
								'arrow'     => __( 'Arrow', 'foodord' ),
								'plant'     => __( 'Plant', 'foodord' ),
								'door'      => __( 'Door', 'foodord' ),
								'stairs'    => __( 'Stairs', 'foodord' ),
							);
							?>
							<section
								class="foodord-reservations-floor-plan"
								data-foodord-reservation-floor-plan="<?php echo esc_attr( (string) $floor_id ); ?>"
								<?php if ( 0 !== $floor_index ) : ?>
									hidden
								<?php endif; ?>
							>
								<div class="foodord-reservations-floor-plan__mode" role="group" aria-label="<?php echo esc_attr__( 'Floor plan type', 'foodord' ); ?>">
									<button class="foodord-reservations-floor-plan__mode-button<?php echo esc_attr( 'image' === $plan_mode ? ' is-active' : '' ); ?>" type="button" data-foodord-reservation-floor-plan-mode="image" aria-pressed="<?php echo esc_attr( 'image' === $plan_mode ? 'true' : 'false' ); ?>">
										<span class="dashicons dashicons-format-image" aria-hidden="true"></span>
										<?php esc_html_e( 'Image plan', 'foodord' ); ?>
									</button>
									<button class="foodord-reservations-floor-plan__mode-button<?php echo esc_attr( 'grid' === $plan_mode ? ' is-active' : '' ); ?>" type="button" data-foodord-reservation-floor-plan-mode="grid" aria-pressed="<?php echo esc_attr( 'grid' === $plan_mode ? 'true' : 'false' ); ?>">
										<span class="dashicons dashicons-grid-view" aria-hidden="true"></span>
										<?php esc_html_e( 'Grid builder', 'foodord' ); ?>
									</button>
								</div>

								<div
									class="foodord-reservations-floor-plan__image-editor"
									data-foodord-reservation-floor-plan-image-editor
									<?php if ( 'grid' === $plan_mode ) : ?>
										hidden
									<?php endif; ?>
								>
									<div class="foodord-reservations-floor-plan__image-workspace">
										<div class="foodord-reservations-floor-plan__toolbar">
											<p class="foodord-reservations-floor-plan__hint"><?php esc_html_e( 'Upload a floor plan image and drag its table labels into place.', 'foodord' ); ?></p>
											<div class="foodord-reservations-floor-plan__actions">
												<button class="button button-secondary foodord-reservations-floor-plan__image-action" type="button" data-foodord-reservation-floor-plan-select aria-label="<?php echo esc_attr__( 'Select image', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Select image', 'foodord' ); ?>">
													<span class="dashicons dashicons-format-image" aria-hidden="true"></span>
												</button>
												<button class="button button-secondary foodord-reservations-floor-plan__image-action" type="button" data-foodord-reservation-floor-plan-remove aria-label="<?php echo esc_attr__( 'Remove image', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Remove image', 'foodord' ); ?>">
													<span class="dashicons dashicons-trash" aria-hidden="true"></span>
												</button>
											</div>
										</div>

										<div class="foodord-reservations-floor-plan__canvas<?php echo esc_attr( is_string( $image_url ) && '' !== $image_url ? '' : ' is-empty' ); ?>" data-foodord-reservation-floor-plan-canvas>
											<p
												class="foodord-reservations-floor-plan__empty"
												data-foodord-reservation-floor-plan-empty
												<?php if ( is_string( $image_url ) && '' !== $image_url ) : ?>
													hidden
												<?php endif; ?>
											><?php esc_html_e( 'No floor plan image selected.', 'foodord' ); ?></p>
											<img
												class="foodord-reservations-floor-plan__image"
												src="<?php echo esc_url( is_string( $image_url ) ? $image_url : '' ); ?>"
												alt=""
												data-foodord-reservation-floor-plan-image
												<?php if ( ! is_string( $image_url ) || '' === $image_url ) : ?>
													hidden
												<?php endif; ?>
											/>
											<div class="foodord-reservations-floor-plan__markers" data-foodord-reservation-floor-plan-markers>
											<?php foreach ( $tables_by_floor[ $floor_id ] ?? array() as $table ) : ?>
												<?php
												$table_capacity = absint( $table->capacity );
												/* translators: %d: table capacity. */
												$table_capacity_label = sprintf( _n( '%d seat', '%d seats', $table_capacity, 'foodord' ), $table_capacity );
												?>
												<button class="foodord-reservations-floor-plan__marker" type="button" data-foodord-reservation-floor-plan-marker="<?php echo esc_attr( (string) $table->id ); ?>">
													<span class="foodord-reservations-floor-plan__marker-rotation" data-foodord-reservation-image-marker-rotate aria-hidden="true"></span>
													<span class="foodord-reservations-floor-plan__marker-name"><?php echo esc_html( (string) $table->name ); ?></span>
													<small class="foodord-reservations-floor-plan__marker-capacity" aria-label="<?php echo esc_attr( $table_capacity_label ); ?>">
														<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false">
															<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"></path>
															<circle cx="9" cy="7" r="4"></circle>
															<path d="M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75"></path>
														</svg>
														<?php echo esc_html( (string) $table_capacity ); ?>
													</small>
													<span class="foodord-reservations-floor-plan__marker-resize" data-foodord-reservation-image-marker-resize aria-hidden="true"></span>
												</button>
											<?php endforeach; ?>
											</div>
											<div class="foodord-reservations-grid-builder__selection-actions" role="toolbar" aria-label="<?php echo esc_attr__( 'Selected table tools', 'foodord' ); ?>" data-foodord-reservation-image-marker-actions hidden>
											<button class="foodord-reservations-grid-builder__selection-action" type="button" data-foodord-reservation-image-marker-rotate-left aria-label="<?php echo esc_attr__( 'Rotate left', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Rotate left', 'foodord' ); ?>">
													<span class="dashicons dashicons-image-rotate-left" aria-hidden="true"></span>
												</button>
											<button class="foodord-reservations-grid-builder__selection-action" type="button" data-foodord-reservation-image-marker-rotate-right aria-label="<?php echo esc_attr__( 'Rotate right', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Rotate right', 'foodord' ); ?>">
													<span class="dashicons dashicons-image-rotate-right" aria-hidden="true"></span>
												</button>
											</div>
										</div>
									</div>

									<aside class="foodord-reservations-grid-builder__sidebar foodord-reservations-floor-plan__image-sidebar" hidden>
										<div class="foodord-reservations-grid-builder__inspector" data-foodord-reservation-image-marker-inspector hidden>
											<div class="foodord-reservations-grid-builder__inspector-header">
												<strong data-foodord-reservation-image-marker-title><?php esc_html_e( 'Marker settings', 'foodord' ); ?></strong>
											<button class="foodord-reservations-grid-builder__inspector-close" type="button" data-foodord-reservation-image-marker-deselect aria-label="<?php echo esc_attr__( 'Close settings', 'foodord' ); ?>"><span class="dashicons dashicons-no-alt" aria-hidden="true"></span></button>
											</div>
											<div class="foodord-reservations-grid-builder__field">
												<label for="foodord-reservation-image-marker-shape-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Table shape', 'foodord' ); ?></label>
												<select id="foodord-reservation-image-marker-shape-<?php echo esc_attr( (string) $floor_id ); ?>" data-foodord-reservation-image-marker-property="shape">
													<option value="rectangle"><?php esc_html_e( 'Rectangle', 'foodord' ); ?></option>
													<option value="square"><?php esc_html_e( 'Square', 'foodord' ); ?></option>
													<option value="round"><?php esc_html_e( 'Round', 'foodord' ); ?></option>
												</select>
											</div>
											<div class="foodord-reservations-grid-builder__field-grid">
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-image-marker-width-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Width', 'foodord' ); ?></label>
													<input id="foodord-reservation-image-marker-width-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="4" max="60" step="0.01" data-foodord-reservation-image-marker-property="width" />
												</div>
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-image-marker-height-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Height', 'foodord' ); ?></label>
													<input id="foodord-reservation-image-marker-height-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="4" max="60" step="0.01" data-foodord-reservation-image-marker-property="height" />
												</div>
											</div>
											<div class="foodord-reservations-grid-builder__field">
												<label for="foodord-reservation-image-marker-rotation-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Rotation', 'foodord' ); ?></label>
												<input id="foodord-reservation-image-marker-rotation-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="-180" max="180" step="15" data-foodord-reservation-image-marker-property="rotation" />
											</div>
											<div class="foodord-reservations-grid-builder__field-grid">
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-image-marker-fill-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Fill color', 'foodord' ); ?></label>
													<input id="foodord-reservation-image-marker-fill-<?php echo esc_attr( (string) $floor_id ); ?>" type="color" data-foodord-reservation-image-marker-property="fill" />
												</div>
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-image-marker-text-color-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Text color', 'foodord' ); ?></label>
													<input id="foodord-reservation-image-marker-text-color-<?php echo esc_attr( (string) $floor_id ); ?>" type="color" data-foodord-reservation-image-marker-property="text_color" />
												</div>
											</div>
										</div>
									</aside>
								</div>

								<div
									class="foodord-reservations-grid-builder"
									data-foodord-reservation-grid-builder
									<?php if ( 'image' === $plan_mode ) : ?>
										hidden
									<?php endif; ?>
								>
									<div class="foodord-reservations-grid-builder__workspace">
										<div class="foodord-reservations-grid-builder__toolbar">
											<p class="foodord-reservations-floor-plan__hint"><?php esc_html_e( 'Add existing tables and arrange them on the grid.', 'foodord' ); ?></p>
											<div class="foodord-reservations-grid-builder__toolbar-controls">
												<label class="foodord-reservations-grid-builder__snap">
												<input class="foodord-reservations-grid-builder__snap-input" type="checkbox" data-foodord-reservation-grid-snap <?php checked( ! isset( $layout['snap_to_grid'] ) || ! empty( $layout['snap_to_grid'] ) ); ?> />
													<span aria-hidden="true"></span>
													<?php esc_html_e( 'Snap to grid', 'foodord' ); ?>
												</label>
												<div class="foodord-reservations-grid-builder__density" role="group" aria-label="<?php echo esc_attr__( 'Grid density', 'foodord' ); ?>">
													<button class="foodord-reservations-grid-builder__density-button<?php echo esc_attr( 'fine' === $grid_density ? ' is-active' : '' ); ?>" type="button" data-foodord-reservation-grid-density="fine" aria-pressed="<?php echo esc_attr( 'fine' === $grid_density ? 'true' : 'false' ); ?>" aria-label="<?php echo esc_attr__( 'Fine grid', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Fine grid', 'foodord' ); ?>">
														<span class="foodord-reservations-grid-builder__density-icon foodord-reservations-grid-builder__density-icon--fine" aria-hidden="true"></span>
													</button>
													<button class="foodord-reservations-grid-builder__density-button<?php echo esc_attr( 'coarse' === $grid_density ? ' is-active' : '' ); ?>" type="button" data-foodord-reservation-grid-density="coarse" aria-pressed="<?php echo esc_attr( 'coarse' === $grid_density ? 'true' : 'false' ); ?>" aria-label="<?php echo esc_attr__( 'Coarse grid', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Coarse grid', 'foodord' ); ?>">
														<span class="foodord-reservations-grid-builder__density-icon foodord-reservations-grid-builder__density-icon--coarse" aria-hidden="true"></span>
													</button>
												</div>
												<button class="foodord-reservations-grid-builder__reset" type="button" data-foodord-reservation-grid-reset data-confirm-message="<?php echo esc_attr__( 'Reset this grid plan? All table positions and shapes on this floor will be removed.', 'foodord' ); ?>" aria-label="<?php echo esc_attr__( 'Reset grid plan', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Reset grid plan', 'foodord' ); ?>">
													<span class="dashicons dashicons-image-rotate" aria-hidden="true"></span>
												</button>
											</div>
										</div>
										<div class="foodord-reservations-grid-builder__canvas" tabindex="0" data-foodord-reservation-grid-canvas aria-label="<?php echo esc_attr__( 'Floor plan grid', 'foodord' ); ?>">
											<p class="foodord-reservations-grid-builder__empty" data-foodord-reservation-grid-empty><?php esc_html_e( 'Add tables or shapes to start building this floor plan.', 'foodord' ); ?></p>
											<div class="foodord-reservations-grid-builder__objects" data-foodord-reservation-grid-objects></div>
											<div class="foodord-reservations-grid-builder__selection-actions" role="toolbar" aria-label="<?php echo esc_attr__( 'Selected item tools', 'foodord' ); ?>" data-foodord-reservation-grid-selection-actions hidden>
											<button class="foodord-reservations-grid-builder__selection-action" type="button" data-foodord-reservation-grid-rotate-left aria-label="<?php echo esc_attr__( 'Rotate left', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Rotate left', 'foodord' ); ?>">
													<span class="dashicons dashicons-image-rotate-left" aria-hidden="true"></span>
												</button>
											<button class="foodord-reservations-grid-builder__selection-action" type="button" data-foodord-reservation-grid-rotate-right aria-label="<?php echo esc_attr__( 'Rotate right', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Rotate right', 'foodord' ); ?>">
													<span class="dashicons dashicons-image-rotate-right" aria-hidden="true"></span>
												</button>
											<button class="foodord-reservations-grid-builder__selection-action" type="button" data-foodord-reservation-grid-selection-remove aria-label="<?php echo esc_attr__( 'Remove from plan', 'foodord' ); ?>" title="<?php echo esc_attr__( 'Remove from plan', 'foodord' ); ?>">
													<span class="dashicons dashicons-trash" aria-hidden="true"></span>
												</button>
											</div>
										</div>
									</div>

									<aside class="foodord-reservations-grid-builder__sidebar">
										<div class="foodord-reservations-grid-builder__tabs" role="tablist" aria-label="<?php echo esc_attr__( 'Floor plan tools', 'foodord' ); ?>">
											<button class="foodord-reservations-grid-builder__tab is-active" type="button" role="tab" aria-selected="true" data-foodord-reservation-grid-tab="tables"><?php esc_html_e( 'Tables', 'foodord' ); ?></button>
											<button class="foodord-reservations-grid-builder__tab" type="button" role="tab" aria-selected="false" data-foodord-reservation-grid-tab="shapes"><?php esc_html_e( 'Shapes', 'foodord' ); ?></button>
										</div>

										<div class="foodord-reservations-grid-builder__panel" data-foodord-reservation-grid-panel="tables">
											<div class="foodord-reservations-grid-builder__table-list">
												<?php foreach ( $tables_by_floor[ $floor_id ] ?? array() as $table ) : ?>
													<?php
													$table_capacity = absint( $table->capacity );
													/* translators: %d: table capacity. */
													$table_capacity_label = sprintf( _n( '%d seat', '%d seats', $table_capacity, 'foodord' ), $table_capacity );
													?>
													<button
														class="foodord-reservations-grid-builder__table-option"
														type="button"
														data-foodord-reservation-grid-add-table="<?php echo esc_attr( (string) $table->id ); ?>"
														data-table-name="<?php echo esc_attr( (string) $table->name ); ?>"
														data-table-capacity="<?php echo esc_attr( (string) $table_capacity ); ?>"
													>
														<span><strong><?php echo esc_html( (string) $table->name ); ?></strong><small><?php echo esc_html( $table_capacity_label ); ?></small></span>
														<span class="dashicons dashicons-plus-alt2" aria-hidden="true"></span>
													</button>
												<?php endforeach; ?>
											</div>
										</div>

										<div class="foodord-reservations-grid-builder__panel" data-foodord-reservation-grid-panel="shapes" hidden>
											<div class="foodord-reservations-grid-builder__shape-list">
												<?php foreach ( $shape_labels as $shape_key => $shape_label ) : ?>
												<button class="foodord-reservations-grid-builder__shape-option" type="button" data-foodord-reservation-grid-add-object="<?php echo esc_attr( $shape_key ); ?>" data-object-label="<?php echo esc_attr( $shape_label ); ?>">
														<span class="foodord-reservations-grid-builder__shape-icon foodord-reservations-grid-builder__shape-icon--<?php echo esc_attr( $shape_key ); ?>" aria-hidden="true"></span>
														<?php echo esc_html( $shape_label ); ?>
													</button>
												<?php endforeach; ?>
											</div>
										</div>

										<div class="foodord-reservations-grid-builder__inspector" data-foodord-reservation-grid-inspector hidden>
											<div class="foodord-reservations-grid-builder__inspector-header">
												<strong data-foodord-reservation-grid-inspector-title><?php esc_html_e( 'Item settings', 'foodord' ); ?></strong>
											<button class="foodord-reservations-grid-builder__inspector-close" type="button" data-foodord-reservation-grid-deselect aria-label="<?php echo esc_attr__( 'Close settings', 'foodord' ); ?>"><span class="dashicons dashicons-no-alt" aria-hidden="true"></span></button>
											</div>
											<div class="foodord-reservations-grid-builder__field" data-foodord-reservation-grid-field="shape">
												<label for="foodord-reservation-grid-shape-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Table shape', 'foodord' ); ?></label>
												<select id="foodord-reservation-grid-shape-<?php echo esc_attr( (string) $floor_id ); ?>" data-foodord-reservation-grid-property="shape">
													<option value="rectangle"><?php esc_html_e( 'Rectangle', 'foodord' ); ?></option>
													<option value="square"><?php esc_html_e( 'Square', 'foodord' ); ?></option>
													<option value="round"><?php esc_html_e( 'Round', 'foodord' ); ?></option>
													</select>
												</div>
												<div class="foodord-reservations-grid-builder__seat-settings" data-foodord-reservation-grid-seat-settings>
													<span class="foodord-reservations-grid-builder__section-label"><?php esc_html_e( 'Seat layout', 'foodord' ); ?></span>
													<label class="foodord-reservations-grid-builder__seat-toggle" data-foodord-reservation-grid-seat-even-field>
												<input class="foodord-reservations-grid-builder__seat-toggle-input" type="checkbox" data-foodord-reservation-grid-property="seat_mode" />
														<span class="foodord-reservations-grid-builder__seat-toggle-control" aria-hidden="true"></span>
														<span><?php esc_html_e( 'Place seats evenly', 'foodord' ); ?></span>
													</label>
													<div class="foodord-reservations-grid-builder__seat-grid" data-foodord-reservation-grid-seat-sides>
														<div class="foodord-reservations-grid-builder__field">
															<label for="foodord-reservation-grid-seat-top-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Top', 'foodord' ); ?></label>
															<input id="foodord-reservation-grid-seat-top-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="0" max="16" step="1" data-foodord-reservation-grid-property="seat_top" />
														</div>
														<div class="foodord-reservations-grid-builder__field">
															<label for="foodord-reservation-grid-seat-right-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Right', 'foodord' ); ?></label>
															<input id="foodord-reservation-grid-seat-right-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="0" max="16" step="1" data-foodord-reservation-grid-property="seat_right" />
														</div>
														<div class="foodord-reservations-grid-builder__field">
															<label for="foodord-reservation-grid-seat-bottom-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Bottom', 'foodord' ); ?></label>
															<input id="foodord-reservation-grid-seat-bottom-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="0" max="16" step="1" data-foodord-reservation-grid-property="seat_bottom" />
														</div>
														<div class="foodord-reservations-grid-builder__field">
															<label for="foodord-reservation-grid-seat-left-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Left', 'foodord' ); ?></label>
															<input id="foodord-reservation-grid-seat-left-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="0" max="16" step="1" data-foodord-reservation-grid-property="seat_left" />
														</div>
													</div>
												</div>
												<div class="foodord-reservations-grid-builder__field" data-foodord-reservation-grid-field="text">
												<label for="foodord-reservation-grid-text-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Text', 'foodord' ); ?></label>
													<input id="foodord-reservation-grid-text-<?php echo esc_attr( (string) $floor_id ); ?>" type="text" maxlength="80" data-foodord-reservation-grid-property="text" />
												</div>
												<div class="foodord-reservations-grid-builder__field-grid">
													<div class="foodord-reservations-grid-builder__field">
														<label for="foodord-reservation-grid-x-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'X position', 'foodord' ); ?></label>
												<input id="foodord-reservation-grid-x-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="2" max="98" step="0.01" data-foodord-reservation-grid-property="x" />
													</div>
													<div class="foodord-reservations-grid-builder__field">
														<label for="foodord-reservation-grid-y-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Y position', 'foodord' ); ?></label>
												<input id="foodord-reservation-grid-y-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="2" max="98" step="0.01" data-foodord-reservation-grid-property="y" />
													</div>
												</div>
												<div class="foodord-reservations-grid-builder__field-grid">
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-grid-width-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Width', 'foodord' ); ?></label>
											<input id="foodord-reservation-grid-width-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="4" max="60" step="0.01" data-foodord-reservation-grid-property="width" />
												</div>
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-grid-height-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Height', 'foodord' ); ?></label>
											<input id="foodord-reservation-grid-height-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="4" max="60" step="0.01" data-foodord-reservation-grid-property="height" />
												</div>
											</div>
											<div class="foodord-reservations-grid-builder__field">
												<label for="foodord-reservation-grid-rotation-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Rotation', 'foodord' ); ?></label>
												<input id="foodord-reservation-grid-rotation-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="-180" max="180" step="15" data-foodord-reservation-grid-property="rotation" />
											</div>
											<div class="foodord-reservations-grid-builder__flip" data-foodord-reservation-grid-object-flip hidden>
												<span class="foodord-reservations-grid-builder__section-label"><?php esc_html_e( 'Flip', 'foodord' ); ?></span>
												<button class="foodord-reservations-grid-builder__flip-button" type="button" data-foodord-reservation-grid-flip-horizontal aria-pressed="false">
													<span class="dashicons dashicons-image-flip-horizontal" aria-hidden="true"></span>
													<span><?php esc_html_e( 'Flip horizontally', 'foodord' ); ?></span>
												</button>
											</div>
											<div class="foodord-reservations-grid-builder__appearance" data-foodord-reservation-grid-appearance>
												<div class="foodord-reservations-grid-builder__field-grid">
													<div class="foodord-reservations-grid-builder__field">
														<label for="foodord-reservation-grid-fill-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Fill', 'foodord' ); ?></label>
														<input id="foodord-reservation-grid-fill-<?php echo esc_attr( (string) $floor_id ); ?>" type="color" data-foodord-reservation-grid-property="fill" />
													</div>
													<div class="foodord-reservations-grid-builder__field">
														<label for="foodord-reservation-grid-stroke-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Border', 'foodord' ); ?></label>
														<input id="foodord-reservation-grid-stroke-<?php echo esc_attr( (string) $floor_id ); ?>" type="color" data-foodord-reservation-grid-property="stroke" />
													</div>
												</div>
												<div class="foodord-reservations-grid-builder__field">
													<label for="foodord-reservation-grid-border-<?php echo esc_attr( (string) $floor_id ); ?>"><?php esc_html_e( 'Border width', 'foodord' ); ?></label>
													<input id="foodord-reservation-grid-border-<?php echo esc_attr( (string) $floor_id ); ?>" type="number" min="0" max="6" step="1" data-foodord-reservation-grid-property="border_width" />
												</div>
											</div>
											<button class="button button-secondary foodord-reservations-grid-builder__remove" type="button" data-foodord-reservation-grid-remove><?php esc_html_e( 'Remove from plan', 'foodord' ); ?></button>
										</div>
									</aside>
								</div>
							</section>
						<?php endforeach; ?>
					</div>
				<?php endif; ?>
				</div>
			</section>
		</form>
		<?php
	}

	/**
	 * Render automatic confirmation setting.
	 */
	private function render_auto_confirm_settings(): void {
		$enabled = Foodord_Table_Reservations::is_auto_confirm_enabled();
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--auto-confirm">
			<label class="foodord-reservations-auto-confirm" for="foodord-reservation-auto-confirm-enabled">
				<span class="foodord-reservations-auto-confirm__content">
					<span class="foodord-reservations-auto-confirm__title">
						<span class="dashicons dashicons-yes-alt foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Auto-confirm reservations', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Automatically confirm new reservations and send the confirmed email immediately.', 'foodord' ); ?></span>
				</span>
				<span class="foodord-reservations-auto-confirm__toggle">
					<input
						id="foodord-reservation-auto-confirm-enabled"
						class="foodord-reservations-auto-confirm__toggle-input"
						type="checkbox"
						name="reservation_auto_confirm_enabled"
						value="1"
						<?php checked( $enabled ); ?>
					/>
					<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
				</span>
			</label>
		</section>
		<?php
	}

	/**
	 * Render customer reservation management setting.
	 */
	private function render_customer_management_settings(): void {
		$enabled = Foodord_Table_Reservations::is_customer_management_enabled();
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--customer-management">
			<label class="foodord-reservations-auto-confirm" for="foodord-reservation-customer-management-enabled">
				<span class="foodord-reservations-auto-confirm__content">
					<span class="foodord-reservations-auto-confirm__title">
						<span class="dashicons dashicons-admin-links foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Allow customers to manage reservations', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Adds a secure email link customers can use to edit or cancel their reservation.', 'foodord' ); ?></span>
				</span>
				<span class="foodord-reservations-auto-confirm__toggle">
					<input
						id="foodord-reservation-customer-management-enabled"
						class="foodord-reservations-auto-confirm__toggle-input"
						type="checkbox"
						name="reservation_customer_management_enabled"
						value="1"
						<?php checked( $enabled ); ?>
					/>
					<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
				</span>
			</label>
		</section>
		<?php
	}

	/**
	 * Render customer cancellation cutoff setting.
	 */
	private function render_customer_cancellation_settings(): void {
		$selected = Foodord_Table_Reservations::get_customer_cancellation_cutoff_minutes();
		$options  = Foodord_Table_Reservations::get_customer_cancellation_cutoff_options();
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--customer-cancellation">
			<div class="foodord-reservations-panel__header">
				<div class="foodord-reservations-panel__heading">
					<h2 class="foodord-reservations-panel__title">
						<span class="dashicons dashicons-clock foodord-reservations-panel__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Customer Cancellation Window', 'foodord' ); ?></span>
					</h2>
					<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Choose how long before the reservation time customers can cancel online.', 'foodord' ); ?></p>
				</div>
			</div>
			<label class="foodord-reservations-field" for="foodord-reservation-customer-cancellation-cutoff">
				<span><?php esc_html_e( 'Allow cancellations until', 'foodord' ); ?></span>
				<select id="foodord-reservation-customer-cancellation-cutoff" name="reservation_customer_cancellation_cutoff">
					<?php foreach ( $options as $minutes => $label ) : ?>
						<option value="<?php echo esc_attr( $minutes ); ?>" <?php selected( $selected, $minutes ); ?>><?php echo esc_html( $label ); ?></option>
					<?php endforeach; ?>
				</select>
			</label>
		</section>
		<?php
	}

	/**
	 * Render reservation privacy settings.
	 */
	private function render_privacy_settings(): void {
		$settings = Foodord_Table_Reservations::get_privacy_settings();
		$pages    = get_pages(
			array(
				'sort_column' => 'post_title',
				'sort_order'  => 'ASC',
				'post_status' => 'publish',
			)
		);
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--privacy" data-foodord-reservation-privacy-settings>
			<div class="foodord-reservations-panel__header">
				<div class="foodord-reservations-panel__heading">
					<h2 class="foodord-reservations-panel__title">
						<span class="dashicons dashicons-lock foodord-reservations-panel__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Privacy', 'foodord' ); ?></span>
					</h2>
					<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Configure the consent shown on the reservation form and control whether customer IP addresses are stored.', 'foodord' ); ?></p>
				</div>
			</div>

			<label class="foodord-reservations-auto-confirm foodord-reservations-privacy__toggle" for="foodord-reservation-privacy-enabled">
				<span class="foodord-reservations-auto-confirm__content">
					<span class="foodord-reservations-auto-confirm__title"><?php esc_html_e( 'Require privacy consent', 'foodord' ); ?></span>
					<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Customers must accept the privacy statement before making a reservation.', 'foodord' ); ?></span>
				</span>
				<span class="foodord-reservations-auto-confirm__toggle">
					<input
						id="foodord-reservation-privacy-enabled"
						class="foodord-reservations-auto-confirm__toggle-input"
						type="checkbox"
						name="reservation_privacy_enabled"
						value="1"
						data-foodord-reservation-privacy-enabled
						<?php checked( $settings['enabled'] ); ?>
					/>
					<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
				</span>
			</label>

			<div class="foodord-reservations-privacy__fields">
				<label class="foodord-reservations-field foodord-reservations-privacy__statement" for="foodord-reservation-privacy-statement">
					<span><?php esc_html_e( 'Privacy statement', 'foodord' ); ?></span>
					<textarea id="foodord-reservation-privacy-statement" name="reservation_privacy_statement" rows="3" maxlength="500"><?php echo esc_textarea( $settings['statement'] ); ?></textarea>
				</label>

				<label class="foodord-reservations-field" for="foodord-reservation-privacy-page">
					<span><?php esc_html_e( 'Privacy policy page', 'foodord' ); ?></span>
					<select id="foodord-reservation-privacy-page" name="reservation_privacy_page_id">
						<option value="0"><?php esc_html_e( 'Select a page', 'foodord' ); ?></option>
						<?php foreach ( $pages as $page ) : ?>
							<option value="<?php echo esc_attr( $page->ID ); ?>" <?php selected( $settings['privacy_page_id'], $page->ID ); ?>>
								<?php echo esc_html( $page->post_title ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</label>
			</div>

			<label class="foodord-reservations-auto-confirm foodord-reservations-privacy__ip" for="foodord-reservation-privacy-store-ip">
				<span class="foodord-reservations-auto-confirm__content">
					<span class="foodord-reservations-auto-confirm__title"><?php esc_html_e( 'Store customer IP address', 'foodord' ); ?></span>
					<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Stores the customer IP address with the consent record. Enable only when required and disclose this in your privacy policy.', 'foodord' ); ?></span>
				</span>
				<span class="foodord-reservations-auto-confirm__toggle">
					<input
						id="foodord-reservation-privacy-store-ip"
						class="foodord-reservations-auto-confirm__toggle-input"
						type="checkbox"
						name="reservation_privacy_store_ip"
						value="1"
						data-foodord-reservation-privacy-store-ip
						<?php checked( $settings['store_ip'] ); ?>
					/>
					<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
				</span>
			</label>
		</section>
		<?php
	}

	/**
	 * Render customer reservation email content settings.
	 */
	private function render_email_content_settings(): void {
		$settings  = Foodord_Table_Reservation_Emails::get_customer_content_settings();
		$templates = array(
			'pending'   => array(
				'label'               => __( 'Pending reservation', 'foodord' ),
				'subject_placeholder' => __( 'Reservation request received', 'foodord' ),
				'heading_placeholder' => __( 'We received your reservation request', 'foodord' ),
				'message_placeholder' => __( 'Thanks {customer_name}, we have received your reservation request and will review it shortly.', 'foodord' ),
			),
			'confirmed' => array(
				'label'               => __( 'Confirmed reservation', 'foodord' ),
				'subject_placeholder' => __( 'Your reservation is confirmed', 'foodord' ),
				'heading_placeholder' => __( 'Your reservation is confirmed', 'foodord' ),
				'message_placeholder' => __( 'Good news {customer_name}, your reservation is confirmed. We look forward to welcoming you and your guests.', 'foodord' ),
			),
			'updated'   => array(
				'label'               => __( 'Updated reservation', 'foodord' ),
				'subject_placeholder' => __( 'Reservation details updated', 'foodord' ),
				'heading_placeholder' => __( 'Your reservation has been updated', 'foodord' ),
				'message_placeholder' => __( 'Thanks {customer_name}, your reservation details have been updated. Please review the latest information below.', 'foodord' ),
			),
			'cancelled' => array(
				'label'               => __( 'Cancelled reservation', 'foodord' ),
				'subject_placeholder' => __( 'Your reservation has been cancelled', 'foodord' ),
				'heading_placeholder' => __( 'Your reservation has been cancelled', 'foodord' ),
				'message_placeholder' => __( '{customer_name}, your reservation has been cancelled. Please contact us if you have any questions.', 'foodord' ),
			),
		);
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--email-content" data-foodord-reservation-email-content>
			<div class="foodord-reservations-panel__header">
				<div class="foodord-reservations-panel__heading">
					<h2 class="foodord-reservations-panel__title">
						<span class="dashicons dashicons-email-alt foodord-reservations-panel__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Translate Email Content', 'foodord' ); ?></span>
					</h2>
					<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Customize customer-facing reservation emails. Leave fields empty to use the default text.', 'foodord' ); ?></p>
				</div>
				<button type="button" class="button button-secondary" data-foodord-reservation-email-reset>
					<?php esc_html_e( 'Restore defaults', 'foodord' ); ?>
				</button>
			</div>

			<div class="foodord-reservations-email-content__toolbar">
				<label class="foodord-reservations-field" for="foodord-reservation-email-template">
					<span><?php esc_html_e( 'Email template', 'foodord' ); ?></span>
					<select id="foodord-reservation-email-template" data-foodord-reservation-email-template>
						<?php foreach ( $templates as $status => $template ) : ?>
							<option value="<?php echo esc_attr( $status ); ?>"><?php echo esc_html( $template['label'] ); ?></option>
						<?php endforeach; ?>
					</select>
				</label>
				<p class="foodord-reservations-email-content__placeholders">
					<?php esc_html_e( 'Available placeholders: {customer_name}, {restaurant_name}', 'foodord' ); ?>
				</p>
			</div>

			<?php foreach ( $templates as $status => $template ) : ?>
				<div class="foodord-reservations-email-content__template" data-foodord-reservation-email-template-panel="<?php echo esc_attr( $status ); ?>" <?php echo 'pending' !== $status ? 'hidden' : ''; ?>>
					<div class="foodord-reservations-email-content__grid">
						<label class="foodord-reservations-field" for="foodord-reservation-email-<?php echo esc_attr( $status ); ?>-subject">
							<span><?php esc_html_e( 'Email subject', 'foodord' ); ?></span>
							<input id="foodord-reservation-email-<?php echo esc_attr( $status ); ?>-subject" type="text" name="reservation_email_content[<?php echo esc_attr( $status ); ?>][subject]" value="<?php echo esc_attr( $settings[ $status ]['subject'] ); ?>" placeholder="<?php echo esc_attr( $template['subject_placeholder'] ); ?>" maxlength="180" />
						</label>
						<label class="foodord-reservations-field" for="foodord-reservation-email-<?php echo esc_attr( $status ); ?>-heading">
							<span><?php esc_html_e( 'Email heading', 'foodord' ); ?></span>
							<input id="foodord-reservation-email-<?php echo esc_attr( $status ); ?>-heading" type="text" name="reservation_email_content[<?php echo esc_attr( $status ); ?>][heading]" value="<?php echo esc_attr( $settings[ $status ]['heading'] ); ?>" placeholder="<?php echo esc_attr( $template['heading_placeholder'] ); ?>" maxlength="180" />
						</label>
					</div>
					<label class="foodord-reservations-field foodord-reservations-email-content__message" for="foodord-reservation-email-<?php echo esc_attr( $status ); ?>-message">
						<span><?php esc_html_e( 'Message', 'foodord' ); ?></span>
						<textarea id="foodord-reservation-email-<?php echo esc_attr( $status ); ?>-message" name="reservation_email_content[<?php echo esc_attr( $status ); ?>][message]" rows="4" maxlength="600" placeholder="<?php echo esc_attr( $template['message_placeholder'] ); ?>"><?php echo esc_textarea( $settings[ $status ]['message'] ); ?></textarea>
					</label>
				</div>
			<?php endforeach; ?>

			<div class="foodord-reservations-email-content__footer">
				<label class="foodord-reservations-field" for="foodord-reservation-email-footer">
					<span><?php esc_html_e( 'Footer text', 'foodord' ); ?></span>
					<textarea id="foodord-reservation-email-footer" name="reservation_email_content[footer]" rows="3" maxlength="300" placeholder="<?php echo esc_attr__( 'Need help? Please contact {restaurant_name} directly.', 'foodord' ); ?>"><?php echo esc_textarea( $settings['footer'] ); ?></textarea>
				</label>
			</div>
		</section>
		<?php
	}

	/**
	 * Render booking hours and holiday settings.
	 */
	private function render_booking_settings(): void {
		$settings       = Foodord_Table_Reservations::get_booking_settings();
		$weekdays       = $this->get_weekday_labels();
		$holiday_ranges = ! empty( $settings['holiday_ranges'] ) ? $settings['holiday_ranges'] : array();
		$has_holidays   = ! empty( $holiday_ranges );
		?>
		<?php $this->render_booking_limit_settings( $settings ); ?>
		<?php $this->render_capacity_limit_settings( $settings ); ?>

		<section class="foodord-reservations-panel foodord-reservations-panel--booking" data-foodord-reservation-booking-settings>
			<div class="foodord-reservations-panel__header">
				<div class="foodord-reservations-panel__heading">
					<h2 class="foodord-reservations-panel__title">
						<span class="dashicons dashicons-clock foodord-reservations-panel__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Booking hours', 'foodord' ); ?></span>
					</h2>
					<p class="foodord-reservations-panel__description"><?php esc_html_e( 'Set reservation hours for each day and block holiday dates.', 'foodord' ); ?></p>
				</div>
			</div>

			<div class="foodord-reservations-schedule">
				<?php foreach ( $weekdays as $day_index => $day_label ) : ?>
					<?php $this->render_booking_day( (int) $day_index, (string) $day_label, $settings['schedule'][ $day_index ] ); ?>
				<?php endforeach; ?>
			</div>

			<div class="foodord-reservations-booking-block" data-foodord-reservation-holidays>
				<div class="foodord-reservations-booking-block__header">
					<div class="foodord-reservations-booking-block__heading">
						<h3 class="foodord-reservations-booking-block__title">
							<span class="dashicons dashicons-calendar-alt foodord-reservations-booking-block__title-icon" aria-hidden="true"></span>
							<span><?php esc_html_e( 'Holiday dates', 'foodord' ); ?></span>
						</h3>
						<p class="foodord-reservations-booking-block__description"><?php esc_html_e( 'Holiday dates override regular booking hours for the selected dates.', 'foodord' ); ?></p>
					</div>
					<button type="button" class="button button-secondary foodord-reservations-booking-block__add" aria-expanded="<?php echo esc_attr( $has_holidays ? 'true' : 'false' ); ?>" data-foodord-reservation-holiday-add>
						<span class="foodord-reservations-booking-block__add-icon" aria-hidden="true">+</span>
						<span><?php esc_html_e( 'Add holiday', 'foodord' ); ?></span>
					</button>
				</div>

				<div
					class="foodord-reservations-holiday-panel"
					data-foodord-reservation-holiday-panel
					<?php if ( ! $has_holidays ) : ?>
						hidden
					<?php endif; ?>
				>
					<div class="foodord-reservations-holiday-rows" data-foodord-reservation-holiday-rows>
						<?php foreach ( $holiday_ranges as $index => $range ) : ?>
							<?php $this->render_holiday_range_row( (int) $index, (string) $range['from'], (string) $range['to'] ); ?>
						<?php endforeach; ?>
					</div>
				</div>

				<template data-foodord-reservation-holiday-template>
					<?php $this->render_holiday_range_row( '__INDEX__', '', '' ); ?>
				</template>
			</div>
		</section>
		<?php
	}

	/**
	 * Render concurrent reservation capacity settings.
	 *
	 * @param array<string,mixed> $settings Booking settings.
	 */
	private function render_capacity_limit_settings( array $settings ): void {
		$limits           = isset( $settings['capacity_limits'] ) && is_array( $settings['capacity_limits'] )
			? $settings['capacity_limits']
			: array();
		$enabled          = ! empty( $limits['enabled'] );
		$max_reservations = absint( $limits['max_reservations'] ?? 0 );
		$max_guests       = absint( $limits['max_guests'] ?? 0 );
		$admin_override   = ! empty( $limits['admin_override'] );
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--capacity-limits<?php echo esc_attr( $enabled ? ' is-enabled' : '' ); ?>" data-foodord-reservation-capacity-limits>
			<label class="foodord-reservations-auto-confirm foodord-reservations-capacity-limits__toggle" for="foodord-reservation-capacity-limits-enabled">
				<span class="foodord-reservations-auto-confirm__content">
					<span class="foodord-reservations-auto-confirm__title">
						<span class="dashicons dashicons-chart-bar foodord-reservations-auto-confirm__title-icon" aria-hidden="true"></span>
						<span><?php esc_html_e( 'Enable capacity limits', 'foodord' ); ?></span>
					</span>
					<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Limit concurrent reservations and total guests across all tables.', 'foodord' ); ?></span>
				</span>
				<span class="foodord-reservations-auto-confirm__toggle">
					<input
						id="foodord-reservation-capacity-limits-enabled"
						class="foodord-reservations-auto-confirm__toggle-input"
						type="checkbox"
						name="reservation_capacity_limits_enabled"
						value="1"
						data-foodord-reservation-capacity-limits-enabled
						<?php checked( $enabled ); ?>
					/>
					<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
				</span>
			</label>

			<div
				class="foodord-reservations-capacity-limits__fields"
				data-foodord-reservation-capacity-limits-fields
				<?php if ( ! $enabled ) : ?>
					hidden
				<?php endif; ?>
			>
				<label class="foodord-reservations-field" for="foodord-reservation-capacity-max-reservations">
					<span class="foodord-reservations-field__label">
						<?php esc_html_e( 'Maximum reservations', 'foodord' ); ?>
						<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'Limits active reservations that overlap the same time period.', 'foodord' ); ?>">
							<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
						</span>
					</span>
					<input id="foodord-reservation-capacity-max-reservations" type="number" name="reservation_capacity_max_reservations" value="<?php echo esc_attr( (string) $max_reservations ); ?>" min="0" max="10000" step="1" inputmode="numeric" />
				</label>

				<label class="foodord-reservations-field" for="foodord-reservation-capacity-max-guests">
					<span class="foodord-reservations-field__label">
						<?php esc_html_e( 'Maximum guests', 'foodord' ); ?>
						<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'Limits guests across active reservations that overlap the same time period.', 'foodord' ); ?>">
							<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
						</span>
					</span>
					<input id="foodord-reservation-capacity-max-guests" type="number" name="reservation_capacity_max_guests" value="<?php echo esc_attr( (string) $max_guests ); ?>" min="0" max="10000" step="1" inputmode="numeric" />
				</label>

				<p class="foodord-reservations-capacity-limits__hint"><?php esc_html_e( 'Set a field to 0 to leave that limit unrestricted.', 'foodord' ); ?></p>
			</div>

			<label
				class="foodord-reservations-auto-confirm foodord-reservations-capacity-limits__override"
				data-foodord-reservation-capacity-limits-fields
				for="foodord-reservation-capacity-admin-override"
				<?php if ( ! $enabled ) : ?>
					hidden
				<?php endif; ?>
			>
				<span class="foodord-reservations-auto-confirm__content">
					<span class="foodord-reservations-auto-confirm__title"><?php esc_html_e( 'Allow admin override', 'foodord' ); ?></span>
					<span class="foodord-reservations-auto-confirm__description"><?php esc_html_e( 'Allows admins to create manual reservations after a capacity limit has been reached.', 'foodord' ); ?></span>
				</span>
				<span class="foodord-reservations-auto-confirm__toggle">
					<input
						id="foodord-reservation-capacity-admin-override"
						class="foodord-reservations-auto-confirm__toggle-input"
						type="checkbox"
						name="reservation_capacity_admin_override"
						value="1"
						<?php checked( $admin_override ); ?>
					/>
					<span class="foodord-reservations-auto-confirm__toggle-control" aria-hidden="true"></span>
				</span>
			</label>
		</section>
		<?php
	}

	/**
	 * Render maximum advance and late booking settings.
	 *
	 * @param array<string,mixed> $settings Booking settings.
	 */
	private function render_booking_limit_settings( array $settings ): void {
		$maximum_advance_days = absint( $settings['maximum_advance_days'] ?? 0 );
		$late_booking         = sanitize_key( (string) ( $settings['late_booking'] ?? '0' ) );
		?>
		<section class="foodord-reservations-panel foodord-reservations-panel--booking-limits">
			<div class="foodord-reservations-booking-limits__heading">
				<h2 class="foodord-reservations-panel__title">
					<span class="dashicons dashicons-hourglass foodord-reservations-panel__title-icon" aria-hidden="true"></span>
					<span><?php esc_html_e( 'Booking limits', 'foodord' ); ?></span>
				</h2>
				<p class="foodord-reservations-booking-limits__description"><?php esc_html_e( 'Control how far ahead and how close to the selected time customers can book.', 'foodord' ); ?></p>
			</div>
			<div class="foodord-reservations-booking-limits__fields">
				<label class="foodord-reservations-field" for="foodord-reservation-maximum-advance-days">
					<span class="foodord-reservations-field__label">
						<?php esc_html_e( 'Maximum Advance Booking', 'foodord' ); ?>
						<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'Sets how far into the future customers can make a reservation.', 'foodord' ); ?>">
							<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
						</span>
					</span>
					<select id="foodord-reservation-maximum-advance-days" name="reservation_maximum_advance_days">
						<?php foreach ( Foodord_Table_Reservations::get_maximum_advance_booking_options() as $days => $label ) : ?>
							<option value="<?php echo esc_attr( (string) $days ); ?>" <?php selected( $maximum_advance_days, $days ); ?>>
								<?php echo esc_html( $label ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</label>

				<label class="foodord-reservations-field" for="foodord-reservation-late-booking">
					<span class="foodord-reservations-field__label">
						<?php esc_html_e( 'Late Booking', 'foodord' ); ?>
						<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'Sets how close to the reservation time customers can still book.', 'foodord' ); ?>">
							<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
						</span>
					</span>
					<select id="foodord-reservation-late-booking" name="reservation_late_booking">
						<?php foreach ( Foodord_Table_Reservations::get_late_booking_options() as $limit => $label ) : ?>
							<option value="<?php echo esc_attr( $limit ); ?>" <?php selected( $late_booking, $limit ); ?>>
								<?php echo esc_html( $label ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</label>
			</div>
		</section>
		<?php
	}

	/**
	 * Render one weekly booking day.
	 *
	 * @param int    $day_index    Weekday index.
	 * @param string $day_label    Weekday label.
	 * @param array  $day_settings Day settings.
	 */
	private function render_booking_day( int $day_index, string $day_label, array $day_settings ): void {
		$ranges        = ! empty( $day_settings['ranges'] ) ? $day_settings['ranges'] : array(
			array(
				'from'     => '10:00',
				'to'       => '23:00',
				'interval' => 30,
			),
		);
		$enabled       = ! empty( $day_settings['enabled'] );
		$range_summary = $enabled ? $this->format_booking_day_summary( $ranges ) : __( 'Closed', 'foodord' );
		?>
		<div class="foodord-reservations-schedule-day" data-foodord-reservation-schedule-day data-day-index="<?php echo esc_attr( $day_index ); ?>" data-open-label="<?php echo esc_attr__( 'Open', 'foodord' ); ?>" data-closed-label="<?php echo esc_attr__( 'Closed', 'foodord' ); ?>" data-empty-label="<?php echo esc_attr__( 'No hours set', 'foodord' ); ?>">
			<div class="foodord-reservations-schedule-day__header">
				<label class="foodord-reservations-schedule-day__toggle" for="foodord-reservation-day-enabled-<?php echo esc_attr( $day_index ); ?>">
					<input
						class="foodord-reservations-schedule-day__toggle-input"
						id="foodord-reservation-day-enabled-<?php echo esc_attr( $day_index ); ?>"
						type="checkbox"
						name="reservation_booking_schedule[<?php echo esc_attr( $day_index ); ?>][enabled]"
						value="1"
						<?php checked( $enabled ); ?>
						data-foodord-reservation-day-enabled
					/>
					<span class="foodord-reservations-schedule-day__toggle-control" aria-hidden="true"></span>
					<span class="foodord-reservations-schedule-day__toggle-label"><?php echo esc_html( $day_label ); ?></span>
				</label>

				<div class="foodord-reservations-schedule-day__summary">
					<span class="foodord-reservations-schedule-day__badge <?php echo esc_attr( $enabled ? 'is-open' : 'is-closed' ); ?>" data-foodord-reservation-day-status>
						<?php echo esc_html( $enabled ? __( 'Open', 'foodord' ) : __( 'Closed', 'foodord' ) ); ?>
					</span>
					<span class="foodord-reservations-schedule-day__times" data-foodord-reservation-day-summary>
						<?php echo esc_html( $range_summary ); ?>
					</span>
				</div>

				<button
					type="button"
					class="button button-secondary foodord-reservations-schedule-day__details"
					aria-expanded="false"
					data-foodord-reservation-day-details-toggle
				>
					<?php esc_html_e( 'Edit hours', 'foodord' ); ?>
				</button>
			</div>

			<div class="foodord-reservations-schedule-day__body" data-foodord-reservation-day-details hidden>
				<div class="foodord-reservations-time-ranges" data-foodord-reservation-time-range-rows>
					<?php foreach ( $ranges as $index => $range ) : ?>
						<?php $this->render_booking_time_range_row( $day_index, (int) $index, $range ); ?>
					<?php endforeach; ?>
				</div>

				<button type="button" class="button button-secondary foodord-reservations-time-ranges__add" data-foodord-reservation-time-range-add>
					<?php esc_html_e( 'Add time range', 'foodord' ); ?>
				</button>
			</div>

			<template data-foodord-reservation-time-range-template>
				<?php
				$this->render_booking_time_range_row(
					$day_index,
					'__INDEX__',
					array(
						'from'     => '10:00',
						'to'       => '23:00',
						'interval' => 30,
					)
				);
				?>
			</template>
		</div>
		<?php
	}

	/**
	 * Render one weekly deposit day.
	 *
	 * @param int    $day_index    Weekday index.
	 * @param string $day_label    Weekday label.
	 * @param array  $day_settings Day settings.
	 */
	private function render_deposit_day( int $day_index, string $day_label, array $day_settings ): void {
		$ranges        = ! empty( $day_settings['ranges'] ) ? $day_settings['ranges'] : array(
			array(
				'from'     => '18:00',
				'to'       => '23:00',
				'interval' => 30,
			),
		);
		$enabled       = ! empty( $day_settings['enabled'] );
		$range_summary = $enabled ? $this->format_booking_day_summary( $ranges ) : __( 'Inactive', 'foodord' );
		?>
		<div class="foodord-reservations-schedule-day" data-foodord-reservation-schedule-day data-day-index="<?php echo esc_attr( $day_index ); ?>" data-open-label="<?php echo esc_attr__( 'Active', 'foodord' ); ?>" data-closed-label="<?php echo esc_attr__( 'Inactive', 'foodord' ); ?>" data-empty-label="<?php echo esc_attr__( 'No hours set', 'foodord' ); ?>">
			<div class="foodord-reservations-schedule-day__header">
				<label class="foodord-reservations-schedule-day__toggle" for="foodord-reservation-deposit-day-enabled-<?php echo esc_attr( $day_index ); ?>">
					<input
						class="foodord-reservations-schedule-day__toggle-input"
						id="foodord-reservation-deposit-day-enabled-<?php echo esc_attr( $day_index ); ?>"
						type="checkbox"
						name="reservation_deposit_schedule[<?php echo esc_attr( $day_index ); ?>][enabled]"
						value="1"
						<?php checked( $enabled ); ?>
						data-foodord-reservation-day-enabled
					/>
					<span class="foodord-reservations-schedule-day__toggle-control" aria-hidden="true"></span>
					<span class="foodord-reservations-schedule-day__toggle-label"><?php echo esc_html( $day_label ); ?></span>
				</label>

				<div class="foodord-reservations-schedule-day__summary">
					<span class="foodord-reservations-schedule-day__badge <?php echo esc_attr( $enabled ? 'is-open' : 'is-closed' ); ?>" data-foodord-reservation-day-status>
						<?php echo esc_html( $enabled ? __( 'Active', 'foodord' ) : __( 'Inactive', 'foodord' ) ); ?>
					</span>
					<span class="foodord-reservations-schedule-day__times" data-foodord-reservation-day-summary>
						<?php echo esc_html( $range_summary ); ?>
					</span>
				</div>

				<button
					type="button"
					class="button button-secondary foodord-reservations-schedule-day__details"
					aria-expanded="false"
					data-foodord-reservation-day-details-toggle
				>
					<?php esc_html_e( 'Edit hours', 'foodord' ); ?>
				</button>
			</div>

			<div class="foodord-reservations-schedule-day__body" data-foodord-reservation-day-details hidden>
				<div class="foodord-reservations-time-ranges" data-foodord-reservation-time-range-rows>
					<?php foreach ( $ranges as $index => $range ) : ?>
						<?php $this->render_deposit_time_range_row( $day_index, (int) $index, $range ); ?>
					<?php endforeach; ?>
				</div>

				<button type="button" class="button button-secondary foodord-reservations-time-ranges__add" data-foodord-reservation-time-range-add>
					<?php esc_html_e( 'Add time range', 'foodord' ); ?>
				</button>
			</div>

			<template data-foodord-reservation-time-range-template>
				<?php
				$this->render_deposit_time_range_row(
					$day_index,
					'__INDEX__',
					array(
						'from' => '18:00',
						'to'   => '23:00',
					)
				);
				?>
			</template>
		</div>
		<?php
	}

	/**
	 * Render one weekly pre-order day.
	 *
	 * @param int    $day_index    Weekday index.
	 * @param string $day_label    Weekday label.
	 * @param array  $day_settings Day settings.
	 */
	private function render_preorder_day( int $day_index, string $day_label, array $day_settings ): void {
		$ranges        = ! empty( $day_settings['ranges'] ) ? $day_settings['ranges'] : array(
			array(
				'from' => '18:00',
				'to'   => '23:00',
			),
		);
		$enabled       = ! empty( $day_settings['enabled'] );
		$range_summary = $enabled ? $this->format_booking_day_summary( $ranges ) : __( 'Inactive', 'foodord' );
		?>
		<div class="foodord-reservations-schedule-day" data-foodord-reservation-schedule-day data-day-index="<?php echo esc_attr( $day_index ); ?>" data-open-label="<?php echo esc_attr__( 'Active', 'foodord' ); ?>" data-closed-label="<?php echo esc_attr__( 'Inactive', 'foodord' ); ?>" data-empty-label="<?php echo esc_attr__( 'No hours set', 'foodord' ); ?>">
			<div class="foodord-reservations-schedule-day__header">
				<label class="foodord-reservations-schedule-day__toggle" for="foodord-reservation-preorder-day-enabled-<?php echo esc_attr( $day_index ); ?>">
					<input
						class="foodord-reservations-schedule-day__toggle-input"
						id="foodord-reservation-preorder-day-enabled-<?php echo esc_attr( $day_index ); ?>"
						type="checkbox"
						name="reservation_preorder_schedule[<?php echo esc_attr( $day_index ); ?>][enabled]"
						value="1"
						<?php checked( $enabled ); ?>
						data-foodord-reservation-day-enabled
					/>
					<span class="foodord-reservations-schedule-day__toggle-control" aria-hidden="true"></span>
					<span class="foodord-reservations-schedule-day__toggle-label"><?php echo esc_html( $day_label ); ?></span>
				</label>

				<div class="foodord-reservations-schedule-day__summary">
					<span class="foodord-reservations-schedule-day__badge <?php echo esc_attr( $enabled ? 'is-open' : 'is-closed' ); ?>" data-foodord-reservation-day-status>
						<?php echo esc_html( $enabled ? __( 'Active', 'foodord' ) : __( 'Inactive', 'foodord' ) ); ?>
					</span>
					<span class="foodord-reservations-schedule-day__times" data-foodord-reservation-day-summary>
						<?php echo esc_html( $range_summary ); ?>
					</span>
				</div>

				<button
					type="button"
					class="button button-secondary foodord-reservations-schedule-day__details"
					aria-expanded="false"
					data-foodord-reservation-day-details-toggle
				>
					<?php esc_html_e( 'Edit hours', 'foodord' ); ?>
				</button>
			</div>

			<div class="foodord-reservations-schedule-day__body" data-foodord-reservation-day-details hidden>
				<div class="foodord-reservations-time-ranges" data-foodord-reservation-time-range-rows>
					<?php foreach ( $ranges as $index => $range ) : ?>
						<?php $this->render_preorder_time_range_row( $day_index, (int) $index, $range ); ?>
					<?php endforeach; ?>
				</div>

				<button type="button" class="button button-secondary foodord-reservations-time-ranges__add" data-foodord-reservation-time-range-add>
					<?php esc_html_e( 'Add time range', 'foodord' ); ?>
				</button>
			</div>

			<template data-foodord-reservation-time-range-template>
				<?php
				$this->render_preorder_time_range_row(
					$day_index,
					'__INDEX__',
					array(
						'from' => '18:00',
						'to'   => '23:00',
					)
				);
				?>
			</template>
		</div>
		<?php
	}

	/**
	 * Format a compact summary for a booking day.
	 *
	 * @param array<int,array{from:string,to:string,interval:int}> $ranges Time ranges.
	 */
	private function format_booking_day_summary( array $ranges ): string {
		$parts = array();
		foreach ( $ranges as $range ) {
			if ( empty( $range['from'] ) || empty( $range['to'] ) ) {
				continue;
			}

			$parts[] = (string) $range['from'] . '-' . (string) $range['to'];
		}

		return ! empty( $parts ) ? implode( ', ', $parts ) : __( 'No hours set', 'foodord' );
	}

	/**
	 * Render one booking time range row.
	 *
	 * @param int        $day_index Weekday index.
	 * @param int|string $index     Row index.
	 * @param array      $range     Time range.
	 */
	private function render_booking_time_range_row( int $day_index, $index, array $range ): void {
		$index_attr = (string) $index;
		$from       = isset( $range['from'] ) ? (string) $range['from'] : '';
		$to         = isset( $range['to'] ) ? (string) $range['to'] : '';
		$interval   = isset( $range['interval'] ) ? absint( $range['interval'] ) : 30;
		?>
		<div class="foodord-reservations-time-range-row" data-foodord-reservation-time-range-row>
			<label class="foodord-reservations-field" for="foodord-reservation-range-from-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'From', 'foodord' ); ?></span>
				<input id="foodord-reservation-range-from-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" type="time" name="reservation_booking_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][from]" value="<?php echo esc_attr( $from ); ?>" />
			</label>

			<label class="foodord-reservations-field" for="foodord-reservation-range-to-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'To', 'foodord' ); ?></span>
				<input id="foodord-reservation-range-to-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" type="time" name="reservation_booking_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][to]" value="<?php echo esc_attr( $to ); ?>" />
			</label>

			<label class="foodord-reservations-field" for="foodord-reservation-range-interval-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span class="foodord-reservations-field__label">
					<?php esc_html_e( 'Slot interval', 'foodord' ); ?>
					<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'Shows reservation times every selected number of minutes.', 'foodord' ); ?>">
						<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
					</span>
				</span>
				<select id="foodord-reservation-range-interval-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" name="reservation_booking_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][interval]">
					<?php foreach ( Foodord_Table_Reservations::get_slot_interval_options() as $slot_interval ) : ?>
						<option value="<?php echo esc_attr( $slot_interval ); ?>" <?php selected( $interval, $slot_interval ); ?>>
							<?php
							echo esc_html(
								sprintf(
									/* translators: %d: time slot interval in minutes. */
									_n( '%d minute', '%d minutes', $slot_interval, 'foodord' ),
									$slot_interval
								)
							);
							?>
						</option>
					<?php endforeach; ?>
				</select>
			</label>

			<button type="button" class="button button-secondary foodord-reservations-time-range-row__remove" data-foodord-reservation-time-range-remove>
				<?php esc_html_e( 'Remove', 'foodord' ); ?>
			</button>
		</div>
		<?php
	}

	/**
	 * Render one deposit time range row.
	 *
	 * @param int        $day_index Weekday index.
	 * @param int|string $index     Row index.
	 * @param array      $range     Time range.
	 */
	private function render_deposit_time_range_row( int $day_index, $index, array $range ): void {
		$index_attr = (string) $index;
		$from       = isset( $range['from'] ) ? (string) $range['from'] : '';
		$to         = isset( $range['to'] ) ? (string) $range['to'] : '';
		?>
		<div class="foodord-reservations-time-range-row foodord-reservations-time-range-row--deposit" data-foodord-reservation-time-range-row>
			<label class="foodord-reservations-field" for="foodord-reservation-deposit-range-from-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'From', 'foodord' ); ?></span>
				<input id="foodord-reservation-deposit-range-from-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" type="time" name="reservation_deposit_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][from]" value="<?php echo esc_attr( $from ); ?>" />
			</label>

			<label class="foodord-reservations-field" for="foodord-reservation-deposit-range-to-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'To', 'foodord' ); ?></span>
				<input id="foodord-reservation-deposit-range-to-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" type="time" name="reservation_deposit_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][to]" value="<?php echo esc_attr( $to ); ?>" />
			</label>

			<button type="button" class="button button-secondary foodord-reservations-time-range-row__remove" data-foodord-reservation-time-range-remove>
				<?php esc_html_e( 'Remove', 'foodord' ); ?>
			</button>
		</div>
		<?php
	}

	/**
	 * Render one pre-order time range row.
	 *
	 * @param int        $day_index Weekday index.
	 * @param int|string $index     Row index.
	 * @param array      $range     Time range.
	 */
	private function render_preorder_time_range_row( int $day_index, $index, array $range ): void {
		$index_attr = (string) $index;
		$from       = isset( $range['from'] ) ? (string) $range['from'] : '';
		$to         = isset( $range['to'] ) ? (string) $range['to'] : '';
		?>
		<div class="foodord-reservations-time-range-row foodord-reservations-time-range-row--preorder" data-foodord-reservation-time-range-row>
			<label class="foodord-reservations-field" for="foodord-reservation-preorder-range-from-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'From', 'foodord' ); ?></span>
				<input id="foodord-reservation-preorder-range-from-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" type="time" name="reservation_preorder_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][from]" value="<?php echo esc_attr( $from ); ?>" />
			</label>

			<label class="foodord-reservations-field" for="foodord-reservation-preorder-range-to-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'To', 'foodord' ); ?></span>
				<input id="foodord-reservation-preorder-range-to-<?php echo esc_attr( $day_index ); ?>-<?php echo esc_attr( $index_attr ); ?>" type="time" name="reservation_preorder_schedule[<?php echo esc_attr( $day_index ); ?>][ranges][<?php echo esc_attr( $index_attr ); ?>][to]" value="<?php echo esc_attr( $to ); ?>" />
			</label>

			<button type="button" class="button button-secondary foodord-reservations-time-range-row__remove" data-foodord-reservation-time-range-remove>
				<?php esc_html_e( 'Remove', 'foodord' ); ?>
			</button>
		</div>
		<?php
	}

	/**
	 * Render one holiday range row.
	 *
	 * @param int|string $index Row index.
	 * @param string     $from  Start date.
	 * @param string     $to    End date.
	 */
	private function render_holiday_range_row( $index, string $from, string $to ): void {
		$index_attr  = (string) $index;
		$placeholder = $this->get_date_placeholder();
		?>
		<div class="foodord-reservations-holiday-row" data-foodord-reservation-holiday-row>
			<label class="foodord-reservations-field foodord-reservations-field--date" for="foodord-reservation-holiday-from-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'From', 'foodord' ); ?></span>
				<input id="foodord-reservation-holiday-from-<?php echo esc_attr( $index_attr ); ?>" type="text" inputmode="numeric" autocomplete="off" name="reservation_holiday_ranges[<?php echo esc_attr( $index_attr ); ?>][from]" value="<?php echo esc_attr( $this->format_date( $from ) ); ?>" placeholder="<?php echo esc_attr( $placeholder ); ?>" form="foodord-reservation-booking-form" data-foodord-reservation-admin-date />
			</label>

			<label class="foodord-reservations-field foodord-reservations-field--date" for="foodord-reservation-holiday-to-<?php echo esc_attr( $index_attr ); ?>">
				<span><?php esc_html_e( 'To', 'foodord' ); ?></span>
				<input id="foodord-reservation-holiday-to-<?php echo esc_attr( $index_attr ); ?>" type="text" inputmode="numeric" autocomplete="off" name="reservation_holiday_ranges[<?php echo esc_attr( $index_attr ); ?>][to]" value="<?php echo esc_attr( $this->format_date( $to ) ); ?>" placeholder="<?php echo esc_attr( $placeholder ); ?>" form="foodord-reservation-booking-form" data-foodord-reservation-admin-date />
			</label>

			<button type="button" class="button button-secondary foodord-reservations-holiday-row__remove" data-foodord-reservation-holiday-remove>
				<?php esc_html_e( 'Remove', 'foodord' ); ?>
			</button>
		</div>
		<?php
	}

	/**
	 * Get localized weekday labels indexed with PHP weekday numbers.
	 *
	 * @return array<int,string>
	 */
	private function get_weekday_labels(): array {
		global $wp_locale;

		$weekday_order = $this->get_weekday_order();
		if ( ! is_object( $wp_locale ) || ! method_exists( $wp_locale, 'get_weekday' ) ) {
			$fallback = array(
				1 => __( 'Monday', 'foodord' ),
				2 => __( 'Tuesday', 'foodord' ),
				3 => __( 'Wednesday', 'foodord' ),
				4 => __( 'Thursday', 'foodord' ),
				5 => __( 'Friday', 'foodord' ),
				6 => __( 'Saturday', 'foodord' ),
				0 => __( 'Sunday', 'foodord' ),
			);

			$labels = array();
			foreach ( $weekday_order as $day_index ) {
				$labels[ $day_index ] = $fallback[ $day_index ];
			}

			return $labels;
		}

		$labels = array();
		foreach ( $weekday_order as $day_index ) {
			$labels[ $day_index ] = $wp_locale->get_weekday( $day_index );
		}

		return $labels;
	}

	/**
	 * Get weekday indexes ordered by the WordPress week start setting.
	 *
	 * @return int[]
	 */
	private function get_weekday_order(): array {
		$start = $this->get_week_start_day();
		$order = array();

		for ( $offset = 0; $offset < 7; $offset++ ) {
			$order[] = ( $start + $offset ) % 7;
		}

		return $order;
	}

	/**
	 * Get localized weekday abbreviations in the configured week order.
	 *
	 * @return string[]
	 */
	private function get_weekday_abbreviations(): array {
		global $wp_locale;

		$labels = $this->get_weekday_labels();
		if ( ! is_object( $wp_locale ) || ! method_exists( $wp_locale, 'get_weekday_abbrev' ) ) {
			return array_values(
				array_map(
					static function ( $label ) {
						$label = (string) $label;

						return function_exists( 'mb_substr' ) ? mb_substr( $label, 0, 3 ) : substr( $label, 0, 3 );
					},
					$labels
				)
			);
		}

		$abbreviations = array();
		foreach ( $labels as $label ) {
			$abbreviations[] = $wp_locale->get_weekday_abbrev( $label );
		}

		return $abbreviations;
	}

	/**
	 * Render table create/edit form.
	 *
	 * @param object|null       $edit_table Current table being edited.
	 * @param array<int,object> $floors Floors available for table assignment.
	 */
	private function render_table_form( $edit_table, array $floors ): void {
		$duration = Foodord_Table_Reservations::sanitize_reservation_duration_minutes( $edit_table->reservation_duration_minutes ?? 90 );
		$floor_id = $edit_table ? absint( $edit_table->floor_id ?? 0 ) : absint( $floors[0]->id ?? 0 );
		?>
		<form id="foodord-reservation-table-form" class="foodord-reservations-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
			<?php wp_nonce_field( 'foodord_save_reservation_table' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_table" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="table_id" value="<?php echo esc_attr( $edit_table ? (int) $edit_table->id : 0 ); ?>" />

			<div class="foodord-reservations-fields foodord-reservations-fields--table">
				<label class="foodord-reservations-field" for="foodord-reservation-table-floor">
					<span><?php esc_html_e( 'Floor', 'foodord' ); ?></span>
					<select id="foodord-reservation-table-floor" name="floor_id" required>
						<?php foreach ( $floors as $floor ) : ?>
							<option value="<?php echo esc_attr( (int) $floor->id ); ?>" <?php selected( $floor_id, (int) $floor->id ); ?>>
								<?php echo esc_html( (string) $floor->name ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</label>

				<label class="foodord-reservations-field" for="foodord-reservation-table-name">
					<span><?php esc_html_e( 'Table name', 'foodord' ); ?></span>
					<input id="foodord-reservation-table-name" type="text" name="table_name" value="<?php echo esc_attr( $edit_table ? (string) $edit_table->name : '' ); ?>" required />
				</label>

				<label class="foodord-reservations-field" for="foodord-reservation-table-capacity">
					<span><?php esc_html_e( 'Capacity', 'foodord' ); ?></span>
					<input id="foodord-reservation-table-capacity" type="number" min="1" step="1" name="table_capacity" value="<?php echo esc_attr( $edit_table ? (int) $edit_table->capacity : 2 ); ?>" required />
				</label>

				<label class="foodord-reservations-field" for="foodord-reservation-duration-minutes">
					<span class="foodord-reservations-field__label">
						<?php esc_html_e( 'Reservation duration', 'foodord' ); ?>
						<span class="foodord-reservations-tooltip" tabindex="0" role="img" aria-label="<?php echo esc_attr__( 'How long this table stays blocked for each reservation.', 'foodord' ); ?>">
							<span class="dashicons dashicons-editor-help" aria-hidden="true"></span>
						</span>
					</span>
					<select id="foodord-reservation-duration-minutes" name="reservation_duration_minutes" required>
						<?php foreach ( Foodord_Table_Reservations::get_reservation_duration_options() as $duration_option ) : ?>
							<option value="<?php echo esc_attr( $duration_option ); ?>" <?php selected( $duration, $duration_option ); ?>>
								<?php echo esc_html( $this->format_reservation_duration_option( $duration_option ) ); ?>
							</option>
						<?php endforeach; ?>
					</select>
				</label>

			</div>

		</form>

		<div class="foodord-reservations-form__actions">
			<?php
			submit_button(
				$edit_table ? __( 'Save', 'foodord' ) : __( 'Add', 'foodord' ),
				'primary',
				'submit',
				false,
				array(
					'form'                    => 'foodord-reservation-table-form',
					'data-foodord-add-label'  => __( 'Add', 'foodord' ),
					'data-foodord-save-label' => __( 'Save', 'foodord' ),
				)
			);
			?>
			<button
				type="button"
				class="button button-secondary"
				data-foodord-reservations-table-cancel
				<?php if ( $edit_table ) : ?>
					data-cancel-url="<?php echo esc_url( $this->get_tab_url( 'tables' ) ); ?>"
				<?php endif; ?>
			>
				<?php esc_html_e( 'Cancel', 'foodord' ); ?>
			</button>
		</div>
		<?php
	}

	/**
	 * Format a reservation duration for an admin option label.
	 *
	 * @param int $duration Duration in minutes.
	 */
	private function format_reservation_duration_option( int $duration ): string {
		$hours   = intdiv( $duration, 60 );
		$minutes = $duration % 60;
		$parts   = array();

		if ( $hours > 0 ) {
			$parts[] = sprintf(
				/* translators: %d: number of hours. */
				_n( '%d hour', '%d hours', $hours, 'foodord' ),
				$hours
			);
		}

		if ( $minutes > 0 ) {
			$parts[] = sprintf(
				/* translators: %d: number of minutes. */
				_n( '%d minute', '%d minutes', $minutes, 'foodord' ),
				$minutes
			);
		}

		return implode( ' ', $parts );
	}

	/**
	 * Render floor create/edit form.
	 *
	 * @param object|null $edit_floor Current floor being edited.
	 */
	private function render_floor_form( $edit_floor ): void {
		?>
		<form class="foodord-reservations-form foodord-reservations-form--floor" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
			<?php wp_nonce_field( 'foodord_save_reservation_floor' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_save_reservation_floor" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="floor_id" value="<?php echo esc_attr( $edit_floor ? (int) $edit_floor->id : 0 ); ?>" />

			<div class="foodord-reservations-fields foodord-reservations-fields--floor">
				<label class="foodord-reservations-field" for="foodord-reservation-floor-name">
					<span><?php esc_html_e( 'Floor name', 'foodord' ); ?></span>
					<input id="foodord-reservation-floor-name" type="text" name="floor_name" value="<?php echo esc_attr( $edit_floor ? (string) $edit_floor->name : '' ); ?>" required />
				</label>

				<div class="foodord-reservations-form__inline-actions">
					<?php
					submit_button(
						$edit_floor ? __( 'Save', 'foodord' ) : __( 'Add', 'foodord' ),
						'primary',
						'submit',
						false,
						array(
							'data-foodord-add-label'  => __( 'Add', 'foodord' ),
							'data-foodord-save-label' => __( 'Save', 'foodord' ),
						)
					);
					?>
					<?php if ( $edit_floor ) : ?>
						<a class="foodord-reservations-cancel-link" href="<?php echo esc_url( $this->get_tab_url( 'tables' ) ); ?>">
							<?php esc_html_e( 'Cancel', 'foodord' ); ?>
						</a>
					<?php else : ?>
						<button type="button" class="button button-secondary" data-foodord-reservation-floor-cancel>
							<?php esc_html_e( 'Cancel', 'foodord' ); ?>
						</button>
					<?php endif; ?>
				</div>
			</div>
		</form>
		<?php
	}

	/**
	 * Render floors list.
	 *
	 * @param array<int,object> $floors Floors.
	 * @param array<int,object> $tables Reservation tables.
	 */
	private function render_floors_list( array $floors, array $tables ): void {
		if ( empty( $floors ) ) {
			echo '<p class="foodord-reservations-empty">' . esc_html__( 'No floors have been added yet.', 'foodord' ) . '</p>';
			return;
		}

		$table_counts = array_fill_keys( array_map( 'absint', wp_list_pluck( $floors, 'id' ) ), 0 );
		foreach ( $tables as $table ) {
			$floor_id = absint( $table->floor_id ?? 0 );
			if ( isset( $table_counts[ $floor_id ] ) ) {
				++$table_counts[ $floor_id ];
			}
		}

		$table_filter_query = $this->get_table_filter_query_args( $this->get_table_list_filters() );
		$pagination         = $this->paginate_management_items( $floors, 'reservation_floor_page' );
		$floors             = $pagination['items'];
		?>
		<div class="foodord-reservations-table-scroll foodord-reservations-table-scroll--compact" role="region" aria-label="<?php esc_attr_e( 'Floors', 'foodord' ); ?>" tabindex="0">
			<table class="widefat foodord-reservations-table foodord-reservations-table--floors">
			<thead>
				<tr>
					<th scope="col"><?php esc_html_e( 'Floor', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Tables', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Actions', 'foodord' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<?php foreach ( $floors as $floor ) : ?>
					<tr
						data-foodord-reservation-floor-row
						data-floor-id="<?php echo esc_attr( (int) $floor->id ); ?>"
						data-floor-name="<?php echo esc_attr( (string) $floor->name ); ?>"
					>
						<td><?php echo esc_html( (string) $floor->name ); ?></td>
						<td><?php echo esc_html( (string) ( $table_counts[ absint( $floor->id ) ] ?? 0 ) ); ?></td>
						<td class="foodord-reservations-table__actions">
							<div class="foodord-reservations-actions">
								<form class="foodord-reservations-action-form" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
									<input class="foodord-reservations-hidden-field" type="hidden" name="page" value="<?php echo esc_attr( $this->get_page_slug() ); ?>" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_action" value="edit_floor" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="floor_id" value="<?php echo esc_attr( (int) $floor->id ); ?>" />
									<?php submit_button( __( 'Edit', 'foodord' ), 'secondary small', 'submit', false ); ?>
								</form>
								<form class="foodord-reservations-action-form foodord-reservations-action-form--delete" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-table-delete-form data-confirm-message="<?php echo esc_attr__( 'Are you sure you want to delete this floor?', 'foodord' ); ?>">
									<?php wp_nonce_field( 'foodord_delete_reservation_floor' ); ?>
									<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_delete_reservation_floor" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="floor_id" value="<?php echo esc_attr( (int) $floor->id ); ?>" />
									<?php submit_button( __( 'Delete', 'foodord' ), 'delete small', 'submit', false ); ?>
								</form>
							</div>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
			</table>
		</div>
		<?php $this->render_management_pagination( $pagination, 'reservation_floor_page', 'reservation_table_page', $table_filter_query ); ?>
		<?php
	}

	/**
	 * Render a compact status badge.
	 *
	 * @param string $status Status key.
	 * @param string $label  Status label.
	 */
	private function render_status_badge( string $status, string $label ): void {
		$class_name = sanitize_html_class( str_replace( '_', '-', $status ) );
		?>
		<span class="foodord-reservations-status foodord-reservations-status--<?php echo esc_attr( $class_name ); ?>">
			<?php echo esc_html( $label ); ?>
		</span>
		<?php
	}

	/**
	 * Get deposit summary for the reservations admin list.
	 *
	 * @param object $reservation Reservation row.
	 * @return array{text:string,order_url:string,refund_notice:string}
	 */
	private function get_reservation_deposit_admin_summary( $reservation ): array {
		$amount   = isset( $reservation->deposit_amount ) ? (float) $reservation->deposit_amount : 0.0;
		$order_id = isset( $reservation->order_id ) ? absint( $reservation->order_id ) : 0;
		$order    = $order_id > 0 && function_exists( 'wc_get_order' ) ? wc_get_order( $order_id ) : false;
		$preorder = class_exists( 'Foodord_Table_Reservation_Deposits' ) && Foodord_Table_Reservation_Deposits::is_preorder_order( $order );
		if ( $amount <= 0 && ! $preorder ) {
			return array(
				'text'          => '',
				'order_url'     => '',
				'refund_notice' => '',
			);
		}

		$payment_status = isset( $reservation->payment_status ) ? sanitize_key( (string) $reservation->payment_status ) : '';
		$status_labels  = array(
			'requires_payment' => __( 'Payment required', 'foodord' ),
			'paid'             => __( 'Paid', 'foodord' ),
			'expired'          => __( 'Expired', 'foodord' ),
			'failed'           => __( 'Failed', 'foodord' ),
			'cancelled'        => __( 'Cancelled', 'foodord' ),
		);
		$status_label   = $status_labels[ $payment_status ] ?? __( 'Payment required', 'foodord' );
		if ( 'requires_payment' === $payment_status && $this->reservation_is_awaiting_payment( $reservation ) ) {
			$status_label = __( 'Customer is paying now', 'foodord' );
		}

		if ( $preorder && $amount > 0 ) {
			$text = sprintf(
				/* translators: 1: deposit amount, 2: payment status. */
				__( 'Pre-order + deposit: %1$s · %2$s', 'foodord' ),
				Foodord_Table_Reservations::format_money( $amount ),
				$status_label
			);
		} elseif ( $preorder ) {
			$text = sprintf(
				/* translators: %s: payment status. */
				__( 'Pre-order · %s', 'foodord' ),
				$status_label
			);
		} else {
			$text = sprintf(
				/* translators: 1: deposit amount, 2: payment status. */
				__( 'Deposit: %1$s · %2$s', 'foodord' ),
				Foodord_Table_Reservations::format_money( $amount ),
				$status_label
			);
		}

		$reservation_status = isset( $reservation->status ) ? Foodord_Table_Reservations::sanitize_status( (string) $reservation->status ) : '';
		$refund_notice      = '';
		if (
			'cancelled' === $reservation_status
			&& 'paid' === $payment_status
			&& $order instanceof WC_Order
			&& (float) $order->get_remaining_refund_amount() > 0
		) {
			$refund_notice = __( 'This payment is not refunded automatically. Process any required refund from the WooCommerce order.', 'foodord' );
		}

		return array(
			'text'          => $text,
			'order_url'     => $this->get_reservation_deposit_order_url( $order_id ),
			'refund_notice' => $refund_notice,
		);
	}

	/**
	 * Get WooCommerce admin order URL for a reservation deposit order.
	 *
	 * @param int $order_id WooCommerce order ID.
	 */
	private function get_reservation_deposit_order_url( int $order_id ): string {
		if ( $order_id <= 0 || ! function_exists( 'wc_get_order' ) ) {
			return '';
		}

		$order = wc_get_order( $order_id );
		if ( ! $order || ! is_a( $order, 'WC_Order' ) || ! method_exists( $order, 'get_edit_order_url' ) ) {
			return '';
		}

		$url = $order->get_edit_order_url();

		return is_string( $url ) ? $url : '';
	}

	/**
	 * Render the reservations view switcher.
	 *
	 * @param array<string,mixed> $query    Current query args.
	 * @param array<string,mixed> $calendar Calendar period metadata.
	 */
	private function render_reservation_view_switcher( array $query, array $calendar ): void {
		$views = array(
			'list'     => __( 'List', 'foodord' ),
			'calendar' => __( 'Calendar', 'foodord' ),
		);
		?>
		<form class="foodord-reservations-view-switcher" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
			<?php
			$this->render_hidden_field( 'page', $this->get_page_slug() );
			$this->render_hidden_field( 'reservation_tab', 'reservations' );
			$this->render_hidden_field( 'reservation_status', (string) $query['status'] );
			$this->render_hidden_field( 'reservation_date', (string) $query['date'] );
			$this->render_hidden_field( 'reservation_search', (string) $query['search'] );
			$this->render_hidden_field( 'reservation_month', (string) $calendar['month'] );
			?>
			<div class="foodord-reservations-view-switcher__buttons" role="group" aria-label="<?php echo esc_attr__( 'Reservation view', 'foodord' ); ?>">
				<?php foreach ( $views as $view => $label ) : ?>
					<button
						type="submit"
						name="reservation_view"
						value="<?php echo esc_attr( $view ); ?>"
						class="button foodord-reservations-view-switcher__button <?php echo esc_attr( $query['view'] === $view ? 'is-active' : '' ); ?>"
						aria-pressed="<?php echo esc_attr( $query['view'] === $view ? 'true' : 'false' ); ?>"
					>
						<?php echo esc_html( $label ); ?>
					</button>
				<?php endforeach; ?>
			</div>
		</form>
		<?php
	}

	/**
	 * Render a hidden form field.
	 *
	 * @param string $name  Field name.
	 * @param string $value Field value.
	 */
	private function render_hidden_field( string $name, string $value ): void {
		if ( '' === $value ) {
			return;
		}
		?>
		<input class="foodord-reservations-hidden-field" type="hidden" name="<?php echo esc_attr( $name ); ?>" value="<?php echo esc_attr( $value ); ?>" />
		<?php
	}

	/**
	 * Render manual reservation modal.
	 */
	private function render_manual_reservation_modal(): void {
		$statuses = array_intersect_key(
			Foodord_Table_Reservations::get_statuses(),
			array(
				'pending'   => true,
				'confirmed' => true,
			)
		);
		?>
		<div class="foodord-reservations-modal" data-foodord-manual-reservation-modal hidden>
			<div class="foodord-reservations-modal__overlay" data-foodord-manual-reservation-close></div>
			<div class="foodord-reservations-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="foodord-manual-reservation-title" tabindex="-1">
					<div class="foodord-reservations-modal__header">
						<div class="foodord-reservations-modal__heading">
						<h2 id="foodord-manual-reservation-title" class="foodord-reservations-modal__title"><?php esc_html_e( 'Add Reservation', 'foodord' ); ?></h2>
						<p class="foodord-reservations-modal__description"><?php esc_html_e( 'Create a reservation manually for phone or in-person requests.', 'foodord' ); ?></p>
					</div>
					<button class="foodord-reservations-modal__close" type="button" data-foodord-manual-reservation-close aria-label="<?php echo esc_attr__( 'Close', 'foodord' ); ?>">
						<span class="dashicons dashicons-no-alt" aria-hidden="true"></span>
					</button>
				</div>

				<form class="foodord-reservations-manual-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
					<?php wp_nonce_field( 'foodord_create_manual_reservation' ); ?>
					<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_create_manual_reservation" />
					<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="reservations" />
					<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_actual_date" value="" data-foodord-manual-reservation-actual-date />

					<div class="foodord-reservations-manual-form__grid">
						<label class="foodord-reservations-field foodord-reservations-field--date" for="foodord-manual-reservation-date">
							<span><?php esc_html_e( 'Date', 'foodord' ); ?></span>
							<input id="foodord-manual-reservation-date" class="foodord-reservations-manual-form__control" type="text" inputmode="numeric" autocomplete="off" name="reservation_date" placeholder="<?php echo esc_attr( $this->get_date_placeholder() ); ?>" data-foodord-reservation-admin-date data-foodord-reservation-min-today required />
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-time">
							<span><?php esc_html_e( 'Time', 'foodord' ); ?></span>
							<select id="foodord-manual-reservation-time" class="foodord-reservations-manual-form__control" name="reservation_time" data-foodord-manual-reservation-time required disabled>
								<option value=""><?php esc_html_e( 'Select time', 'foodord' ); ?></option>
							</select>
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-party-size">
							<span><?php esc_html_e( 'Guests', 'foodord' ); ?></span>
							<input id="foodord-manual-reservation-party-size" class="foodord-reservations-manual-form__control" type="number" name="party_size" min="1" step="1" value="1" required />
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-table">
							<span><?php esc_html_e( 'Table', 'foodord' ); ?></span>
							<select id="foodord-manual-reservation-table" class="foodord-reservations-manual-form__control" name="table_id" data-foodord-manual-reservation-table required disabled>
								<option value=""><?php esc_html_e( 'Select table', 'foodord' ); ?></option>
							</select>
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-duration">
							<span><?php esc_html_e( 'Duration', 'foodord' ); ?></span>
							<select id="foodord-manual-reservation-duration" class="foodord-reservations-manual-form__control" name="duration_minutes" data-foodord-manual-reservation-duration required disabled>
								<option value=""><?php esc_html_e( 'Select duration', 'foodord' ); ?></option>
							</select>
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-status">
							<span><?php esc_html_e( 'Reservation Status', 'foodord' ); ?></span>
							<select id="foodord-manual-reservation-status" class="foodord-reservations-manual-form__control" name="reservation_status">
								<?php foreach ( $statuses as $status => $label ) : ?>
									<option value="<?php echo esc_attr( $status ); ?>" <?php selected( 'confirmed', $status ); ?>>
										<?php echo esc_html( $label ); ?>
									</option>
								<?php endforeach; ?>
							</select>
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-name">
							<span><?php esc_html_e( 'Name', 'foodord' ); ?></span>
							<input id="foodord-manual-reservation-name" class="foodord-reservations-manual-form__control" type="text" name="customer_name" autocomplete="name" required />
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-email">
							<span><?php esc_html_e( 'Email', 'foodord' ); ?></span>
							<input id="foodord-manual-reservation-email" class="foodord-reservations-manual-form__control" type="email" name="customer_email" autocomplete="email" required />
						</label>

						<label class="foodord-reservations-field" for="foodord-manual-reservation-phone">
							<span><?php esc_html_e( 'Phone', 'foodord' ); ?></span>
							<input id="foodord-manual-reservation-phone" class="foodord-reservations-manual-form__control" type="tel" name="customer_phone" autocomplete="tel" required />
						</label>

						<div class="foodord-reservations-manual-form__note" data-foodord-manual-reservation-note-wrapper>
							<button class="foodord-reservations-manual-form__note-toggle" type="button" aria-expanded="false" aria-controls="foodord-manual-reservation-note-panel" data-foodord-manual-reservation-note-toggle>
								<span id="foodord-manual-reservation-note-label"><?php esc_html_e( 'Additional Request', 'foodord' ); ?></span>
							</button>
							<div id="foodord-manual-reservation-note-panel" class="foodord-reservations-manual-form__note-panel" data-foodord-manual-reservation-note-panel hidden>
								<div class="foodord-reservations-field foodord-reservations-field--full">
										<textarea id="foodord-manual-reservation-note" class="foodord-reservations-manual-form__control" name="customer_note" rows="3" aria-labelledby="foodord-manual-reservation-note-label"></textarea>
								</div>
							</div>
						</div>
					</div>

					<label class="foodord-reservations-manual-form__notify" for="foodord-manual-reservation-notification">
							<input id="foodord-manual-reservation-notification" class="foodord-reservations-manual-form__checkbox" type="checkbox" name="send_notification" value="1" />
						<span><?php esc_html_e( 'Send customer notification', 'foodord' ); ?></span>
					</label>

					<div class="foodord-reservations-modal__footer">
						<button class="button button-primary foodord-reservations-manual-form__submit" type="submit" data-foodord-manual-reservation-submit><span class="foodord-reservations-manual-form__submit-label"><?php esc_html_e( 'Create Reservation', 'foodord' ); ?></span></button>
						<button class="button" type="button" data-foodord-manual-reservation-close><?php esc_html_e( 'Cancel', 'foodord' ); ?></button>
					</div>
				</form>
			</div>
		</div>
		<?php
	}

	/**
	 * Render reservation filters.
	 *
	 * @param array<string,mixed> $query Current query args.
	 */
	private function render_reservation_filters( array $query ): void {
		$statuses = Foodord_Table_Reservations::get_statuses();
		?>
		<form class="foodord-reservations-filter" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
			<input class="foodord-reservations-hidden-field" type="hidden" name="page" value="<?php echo esc_attr( $this->get_page_slug() ); ?>" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="reservations" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_view" value="<?php echo esc_attr( (string) $query['view'] ); ?>" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_month" value="<?php echo esc_attr( (string) $query['month'] ); ?>" />
			<label class="foodord-reservations-filter__field" for="foodord-reservation-filter-status">
				<span><?php esc_html_e( 'Status', 'foodord' ); ?></span>
				<select id="foodord-reservation-filter-status" name="reservation_status">
					<option value=""><?php esc_html_e( 'All statuses', 'foodord' ); ?></option>
					<?php foreach ( $statuses as $status_key => $status_label ) : ?>
						<option value="<?php echo esc_attr( $status_key ); ?>" <?php selected( $query['status'], $status_key ); ?>>
							<?php echo esc_html( $status_label ); ?>
						</option>
					<?php endforeach; ?>
				</select>
			</label>

			<label class="foodord-reservations-filter__field foodord-reservations-filter__field--date" for="foodord-reservation-filter-date">
				<span><?php esc_html_e( 'Date', 'foodord' ); ?></span>
				<input id="foodord-reservation-filter-date" type="text" inputmode="numeric" autocomplete="off" name="reservation_date" value="<?php echo esc_attr( $this->format_date( (string) $query['date'] ) ); ?>" placeholder="<?php echo esc_attr( $this->get_date_placeholder() ); ?>" data-foodord-reservation-admin-date />
			</label>

			<label class="foodord-reservations-filter__field foodord-reservations-filter__field--search" for="foodord-reservation-filter-search">
				<span><?php esc_html_e( 'Search reservations', 'foodord' ); ?></span>
				<input id="foodord-reservation-filter-search" type="search" name="reservation_search" value="<?php echo esc_attr( (string) $query['search'] ); ?>" placeholder="<?php echo esc_attr__( 'Search reservations', 'foodord' ); ?>" />
			</label>

			<div class="foodord-reservations-filter__actions">
				<?php submit_button( __( 'Filter', 'foodord' ), 'secondary', 'submit', false ); ?>
				<button class="button foodord-reservations-filter__reset" type="button" data-foodord-reservation-filter-reset>
					<?php esc_html_e( 'Reset', 'foodord' ); ?>
				</button>
			</div>
		</form>
		<?php
	}

	/**
	 * Render floor and search filters for the Tables list.
	 *
	 * @param array<int,object> $floors Available floors.
	 */
	private function render_table_filters( array $floors ): void {
		$filters    = $this->get_table_list_filters();
		$floor_page = $this->get_management_list_page( 'reservation_floor_page' );
		?>
		<form class="foodord-reservations-filter foodord-reservations-filter--tables" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
			<input class="foodord-reservations-hidden-field" type="hidden" name="page" value="<?php echo esc_attr( $this->get_page_slug() ); ?>" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
			<?php if ( $floor_page > 1 ) : ?>
				<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_floor_page" value="<?php echo esc_attr( $floor_page ); ?>" />
			<?php endif; ?>

			<label class="foodord-reservations-filter__field" for="foodord-reservation-table-filter-floor">
				<span><?php esc_html_e( 'Floor', 'foodord' ); ?></span>
				<select id="foodord-reservation-table-filter-floor" class="foodord-reservations-filter__control" name="reservation_table_floor">
					<option value="0"><?php esc_html_e( 'All floors', 'foodord' ); ?></option>
					<?php foreach ( $floors as $floor ) : ?>
						<option value="<?php echo esc_attr( (int) $floor->id ); ?>" <?php selected( $filters['floor_id'], (int) $floor->id ); ?>>
							<?php echo esc_html( (string) $floor->name ); ?>
						</option>
					<?php endforeach; ?>
				</select>
			</label>

			<label class="foodord-reservations-filter__field foodord-reservations-filter__field--search" for="foodord-reservation-table-filter-search">
				<span><?php esc_html_e( 'Search tables', 'foodord' ); ?></span>
				<input id="foodord-reservation-table-filter-search" class="foodord-reservations-filter__control" type="search" name="reservation_table_search" value="<?php echo esc_attr( $filters['search'] ); ?>" placeholder="<?php echo esc_attr__( 'Search tables', 'foodord' ); ?>" />
			</label>

			<div class="foodord-reservations-filter__actions">
				<?php submit_button( __( 'Filter', 'foodord' ), 'secondary', 'submit', false ); ?>
			</div>
		</form>
		<?php
	}

	/**
	 * Render reservation bulk action controls.
	 *
	 * @param array<string,mixed> $query   Current list query.
	 * @param string              $form_id Bulk form ID.
	 */
	private function render_reservation_bulk_actions( array $query, string $form_id ): void {
		?>
		<form
			id="<?php echo esc_attr( $form_id ); ?>"
			class="foodord-reservations-bulk-actions"
			method="post"
			action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>"
			data-foodord-reservation-bulk-form
			data-delete-confirm-message="<?php echo esc_attr__( 'Are you sure you want to permanently delete the selected reservations?', 'foodord' ); ?>"
		>
			<?php wp_nonce_field( 'foodord_bulk_reservation_action' ); ?>
			<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_bulk_reservation_action" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="reservations" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_return_status" value="<?php echo esc_attr( (string) $query['status'] ); ?>" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_return_date" value="<?php echo esc_attr( (string) $query['date'] ); ?>" />
			<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_return_search" value="<?php echo esc_attr( (string) $query['search'] ); ?>" />

			<label class="screen-reader-text" for="foodord-reservations-bulk-action"><?php esc_html_e( 'Bulk actions', 'foodord' ); ?></label>
			<select id="foodord-reservations-bulk-action" name="bulk_action" data-foodord-reservation-bulk-action required>
				<option value=""><?php esc_html_e( 'Bulk actions', 'foodord' ); ?></option>
				<?php foreach ( $this->get_bulk_reservation_actions() as $action => $label ) : ?>
					<option value="<?php echo esc_attr( $action ); ?>"><?php echo esc_html( $label ); ?></option>
				<?php endforeach; ?>
			</select>
			<?php submit_button( __( 'Apply', 'foodord' ), 'secondary action', 'submit', false ); ?>
		</form>
		<?php
	}

	/**
	 * Render reservations list.
	 *
	 * @param array<int,object>   $reservations Reservations.
	 * @param array<string,mixed> $query        Current list query.
	 */
	private function render_reservations_list( array $reservations, array $query ): void {
		if ( empty( $reservations ) ) {
			echo '<p class="foodord-reservations-empty">' . esc_html__( 'No reservations found.', 'foodord' ) . '</p>';
			return;
		}

		$statuses = Foodord_Table_Reservations::get_statuses();
		$form_id  = 'foodord-reservations-bulk-form';
		$this->render_reservation_bulk_actions( $query, $form_id );
		?>
		<div class="foodord-reservations-table-scroll foodord-reservations-table-scroll--reservations" role="region" aria-label="<?php esc_attr_e( 'Reservations', 'foodord' ); ?>" tabindex="0">
			<table class="widefat foodord-reservations-table foodord-reservations-table--main">
			<thead>
				<tr>
					<td class="manage-column column-cb check-column">
						<input id="foodord-reservations-select-all" class="foodord-reservations-table__select-all" type="checkbox" data-foodord-reservation-select-all />
						<label class="screen-reader-text" for="foodord-reservations-select-all"><?php esc_html_e( 'Select all', 'foodord' ); ?></label>
					</td>
					<th scope="col"><?php esc_html_e( 'Code', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Reservation Time', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Table', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Guests', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Customer', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Status', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Actions', 'foodord' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<?php foreach ( $reservations as $reservation ) : ?>
					<?php
					$status        = Foodord_Table_Reservations::sanitize_status( (string) $reservation->status );
					$status_label  = $statuses[ $status ] ?? $status;
					$created_at    = $this->format_datetime_from_gmt( (string) $reservation->created_at_gmt );
					$cancel_reason = isset( $reservation->cancellation_reason ) ? Foodord_Table_Reservations::sanitize_cancellation_reason( (string) $reservation->cancellation_reason ) : '';
					$deposit       = $this->get_reservation_deposit_admin_summary( $reservation );
					$is_locked     = $this->reservation_is_awaiting_payment( $reservation );
					if ( $is_locked ) {
						$status_label = __( 'Customer is paying now', 'foodord' );
					}
					$can_send_mail = ! $is_locked && $this->can_send_customer_status_email( $reservation );
					$row_class     = 'pending' === $status ? 'foodord-reservations-row foodord-reservations-row--pending' : 'foodord-reservations-row';
					?>
					<tr class="<?php echo esc_attr( $row_class ); ?>">
						<th class="check-column" scope="row">
							<input
								id="foodord-reservation-select-<?php echo esc_attr( (int) $reservation->id ); ?>"
								type="checkbox"
								name="reservation_ids[]"
								value="<?php echo esc_attr( (int) $reservation->id ); ?>"
								form="<?php echo esc_attr( $form_id ); ?>"
								data-foodord-reservation-select
								<?php disabled( $is_locked ); ?>
							/>
							<label class="screen-reader-text" for="foodord-reservation-select-<?php echo esc_attr( (int) $reservation->id ); ?>">
								<?php
								echo esc_html(
									sprintf(
										/* translators: %s: reservation code. */
										__( 'Select reservation %s', 'foodord' ),
										(string) $reservation->reservation_code
									)
								);
								?>
							</label>
						</th>
						<td>
							<strong class="foodord-reservations-code"><?php echo esc_html( (string) $reservation->reservation_code ); ?></strong>
							<?php if ( '' !== $created_at ) : ?>
								<span class="foodord-reservations-code-meta">
									<?php esc_html_e( 'Created', 'foodord' ); ?> <?php echo esc_html( $created_at ); ?>
								</span>
							<?php endif; ?>
							<?php if ( '' !== $deposit['text'] ) : ?>
								<span class="foodord-reservations-code-meta">
									<?php echo esc_html( $deposit['text'] ); ?>
									<?php if ( '' !== $deposit['order_url'] ) : ?>
										<a class="foodord-reservations-code-link" href="<?php echo esc_url( $deposit['order_url'] ); ?>">
											<?php esc_html_e( 'View order', 'foodord' ); ?>
										</a>
									<?php endif; ?>
								</span>
							<?php endif; ?>
							<?php if ( '' !== $deposit['refund_notice'] ) : ?>
								<span class="foodord-reservations-code-meta foodord-reservations-code-meta--refund">
									<?php echo esc_html( $deposit['refund_notice'] ); ?>
								</span>
							<?php endif; ?>
						</td>
						<td>
							<?php echo esc_html( $this->format_date( (string) $reservation->reservation_date ) ); ?>
							<br />
							<?php echo esc_html( $this->format_time( (string) $reservation->reservation_time ) ); ?>
						</td>
						<td>
							<?php
							echo esc_html(
								$this->format_table_location(
									(string) ( $reservation->floor_name ?? '' ),
									(string) $reservation->table_name
								)
							);
							?>
						</td>
						<td><?php echo esc_html( (string) absint( $reservation->party_size ) ); ?></td>
						<td>
							<div class="foodord-reservations-customer">
								<strong><?php echo esc_html( (string) $reservation->customer_name ); ?></strong>
								<span><?php echo esc_html( (string) $reservation->customer_email ); ?></span>
								<span><?php echo esc_html( (string) $reservation->customer_phone ); ?></span>
								<?php if ( $can_send_mail ) : ?>
									<form class="foodord-reservations-customer-email-form" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
									<?php wp_nonce_field( 'foodord_resend_reservation_status_email' ); ?>
									<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_resend_reservation_status_email" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="reservations" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_id" value="<?php echo esc_attr( (int) $reservation->id ); ?>" />
										<button class="foodord-reservations-customer-email" type="submit"><?php esc_html_e( 'Send Email', 'foodord' ); ?></button>
									</form>
								<?php endif; ?>
							</div>
						</td>
						<td><?php $this->render_status_badge( $status, $status_label ); ?></td>
						<td class="foodord-reservations-table__actions">
							<div class="foodord-reservations-actions">
								<?php if ( ! $is_locked ) : ?>
									<form class="foodord-reservations-action-form foodord-reservations-action-form--status" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-status-form data-foodord-reservation-refund-warning="<?php echo esc_attr( isset( $reservation->payment_status ) && 'paid' === (string) $reservation->payment_status && '' !== $deposit['order_url'] ? '1' : '0' ); ?>">
										<?php wp_nonce_field( 'foodord_update_reservation_status' ); ?>
										<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_update_reservation_status" />
										<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="reservations" />
										<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_id" value="<?php echo esc_attr( (int) $reservation->id ); ?>" />
										<input class="foodord-reservations-hidden-field" type="hidden" name="cancellation_reason" value="<?php echo esc_attr( $cancel_reason ); ?>" data-foodord-reservation-cancellation-reason-value />
										<div class="foodord-reservations-action-form__row">
											<label class="screen-reader-text" for="foodord-reservation-status-<?php echo esc_attr( (int) $reservation->id ); ?>">
												<?php esc_html_e( 'Reservation status', 'foodord' ); ?>
											</label>
											<select id="foodord-reservation-status-<?php echo esc_attr( (int) $reservation->id ); ?>" class="foodord-reservations-status-select" name="reservation_status" data-foodord-reservation-status-select>
												<?php foreach ( $statuses as $status_key => $label ) : ?>
													<option value="<?php echo esc_attr( $status_key ); ?>" <?php selected( $status, $status_key ); ?>>
														<?php echo esc_html( $label ); ?>
													</option>
												<?php endforeach; ?>
											</select>
											<?php submit_button( __( 'Update', 'foodord' ), 'secondary small', 'submit', false ); ?>
										</div>
									</form>
								<?php endif; ?>
							</div>
						</td>
					</tr>
					<?php if ( '' !== (string) $reservation->customer_note ) : ?>
						<tr class="foodord-reservations-note-row">
							<td colspan="9">
								<span class="foodord-reservations-note-row__label"><?php esc_html_e( 'Additional Request', 'foodord' ); ?>:</span>
								<?php echo esc_html( (string) $reservation->customer_note ); ?>
							</td>
						</tr>
					<?php endif; ?>
					<?php if ( '' !== $cancel_reason ) : ?>
						<tr class="foodord-reservations-note-row foodord-reservations-note-row--cancellation">
							<td colspan="9">
								<span class="foodord-reservations-note-row__label"><?php esc_html_e( 'Cancellation reason', 'foodord' ); ?>:</span>
								<?php echo esc_html( $cancel_reason ); ?>
							</td>
						</tr>
					<?php endif; ?>
				<?php endforeach; ?>
			</tbody>
			</table>
		</div>
		<div class="foodord-reservations-modal foodord-reservations-cancellation-modal" data-foodord-reservation-cancellation-modal hidden>
			<div class="foodord-reservations-modal__overlay" data-foodord-reservation-cancellation-modal-close></div>
			<div class="foodord-reservations-modal__dialog foodord-reservations-cancellation-modal__dialog" role="dialog" aria-modal="true" aria-labelledby="foodord-reservation-cancellation-modal-title">
				<div class="foodord-reservations-modal__header">
					<div class="foodord-reservations-modal__heading">
						<h2 id="foodord-reservation-cancellation-modal-title" class="foodord-reservations-modal__title"><?php esc_html_e( 'Cancel reservation?', 'foodord' ); ?></h2>
						<p class="foodord-reservations-modal__description"><?php esc_html_e( 'Add an optional reason before cancelling this reservation.', 'foodord' ); ?></p>
					</div>
					<button type="button" class="foodord-reservations-modal__close" data-foodord-reservation-cancellation-modal-close aria-label="<?php echo esc_attr__( 'Close', 'foodord' ); ?>">
						<span class="dashicons dashicons-no-alt" aria-hidden="true"></span>
					</button>
				</div>
				<div class="foodord-reservations-cancellation-modal__body">
					<p class="foodord-reservations-cancellation-modal__refund" data-foodord-reservation-cancellation-refund hidden>
						<?php esc_html_e( 'This payment is not refunded automatically. Process any required refund from the WooCommerce order.', 'foodord' ); ?>
					</p>
					<label class="foodord-reservations-cancellation-reason" for="foodord-reservation-cancellation-modal-reason">
						<span><?php esc_html_e( 'Cancellation reason (optional)', 'foodord' ); ?></span>
						<textarea id="foodord-reservation-cancellation-modal-reason" rows="4" maxlength="500" data-foodord-reservation-cancellation-modal-reason></textarea>
					</label>
					<div class="foodord-reservations-modal__footer">
						<button type="button" class="button button-secondary" data-foodord-reservation-cancellation-modal-close>
							<?php esc_html_e( 'Keep reservation', 'foodord' ); ?>
						</button>
						<button type="button" class="button button-primary" data-foodord-reservation-cancellation-modal-confirm>
							<?php esc_html_e( 'Confirm cancellation', 'foodord' ); ?>
						</button>
					</div>
				</div>
			</div>
		</div>
		<?php
	}

	/**
	 * Render reservations in a monthly calendar.
	 *
	 * @param array<int,object>   $reservations Reservations.
	 * @param array<string,mixed> $calendar     Calendar period metadata.
	 * @param array<string,mixed> $query        Current query args.
	 */
	private function render_reservations_calendar( array $reservations, array $calendar, array $query ): void {
		$grouped        = $this->group_reservations_by_date( $reservations );
		$weekday_labels = $this->get_weekday_abbreviations();
		$today          = current_time( 'Y-m-d' );
		?>
		<div class="foodord-reservations-calendar">
			<div class="foodord-reservations-calendar__toolbar">
				<?php $this->render_calendar_month_button( (string) $calendar['previous'], __( 'Previous month', 'foodord' ), $query, 'previous' ); ?>
				<h3 class="foodord-reservations-calendar__title"><?php echo esc_html( (string) $calendar['label'] ); ?></h3>
				<?php $this->render_calendar_month_button( (string) $calendar['next'], __( 'Next month', 'foodord' ), $query, 'next' ); ?>
			</div>

			<div class="foodord-reservations-calendar__weekdays">
				<?php foreach ( $weekday_labels as $weekday_label ) : ?>
					<span class="foodord-reservations-calendar__weekday"><?php echo esc_html( $weekday_label ); ?></span>
				<?php endforeach; ?>
			</div>

			<div class="foodord-reservations-calendar__grid">
				<?php for ( $empty_index = 0; $empty_index < (int) $calendar['offset']; $empty_index++ ) : ?>
					<div class="foodord-reservations-calendar__day foodord-reservations-calendar__day--empty" aria-hidden="true"></div>
				<?php endfor; ?>

				<?php for ( $day = 1; $day <= (int) $calendar['days']; $day++ ) : ?>
					<?php
					$date       = sprintf( '%s-%02d', (string) $calendar['month'], $day );
					$items      = $grouped[ $date ] ?? array();
					$is_today   = $today === $date;
					$is_current = (string) $query['date'] === $date;
					$day_class  = 'foodord-reservations-calendar__day';
					$day_class .= $is_today ? ' is-today' : '';
					$day_class .= $is_current ? ' is-selected' : '';
					?>
					<div class="<?php echo esc_attr( $day_class ); ?>">
						<div class="foodord-reservations-calendar__day-header">
							<span class="foodord-reservations-calendar__day-number"><?php echo esc_html( (string) $day ); ?></span>
							<?php if ( ! empty( $items ) ) : ?>
								<span class="foodord-reservations-calendar__day-count">
									<?php echo esc_html( (string) count( $items ) ); ?>
								</span>
							<?php endif; ?>
						</div>

						<?php if ( ! empty( $items ) ) : ?>
							<div class="foodord-reservations-calendar__events">
								<?php foreach ( array_slice( $items, 0, 3 ) as $reservation ) : ?>
									<?php $this->render_calendar_reservation( $reservation ); ?>
								<?php endforeach; ?>

								<?php if ( count( $items ) > 3 ) : ?>
									<span class="foodord-reservations-calendar__more">
										<?php
										echo esc_html(
											sprintf(
												/* translators: %d: remaining reservation count. */
												__( '+ %d more', 'foodord' ),
												count( $items ) - 3
											)
										);
										?>
									</span>
								<?php endif; ?>
							</div>
						<?php endif; ?>
					</div>
				<?php endfor; ?>
			</div>

			<?php if ( empty( $reservations ) ) : ?>
				<p class="foodord-reservations-calendar__empty"><?php esc_html_e( 'No reservations this month.', 'foodord' ); ?></p>
			<?php endif; ?>
		</div>
		<?php
	}

	/**
	 * Render a calendar reservation card.
	 *
	 * @param object $reservation Reservation row.
	 */
	private function render_calendar_reservation( $reservation ): void {
		$statuses     = Foodord_Table_Reservations::get_statuses();
		$status       = Foodord_Table_Reservations::sanitize_status( (string) $reservation->status );
		$status_label = $statuses[ $status ] ?? $status;
		$class_name   = sanitize_html_class( str_replace( '_', '-', $status ) );
		$party_size   = absint( $reservation->party_size );
		?>
		<article class="foodord-reservations-calendar-event foodord-reservations-calendar-event--<?php echo esc_attr( $class_name ); ?>">
			<div class="foodord-reservations-calendar-event__top">
				<span class="foodord-reservations-calendar-event__time"><?php echo esc_html( $this->format_time( (string) $reservation->reservation_time ) ); ?></span>
				<span class="foodord-reservations-calendar-event__guests">
					<?php
					echo esc_html(
						sprintf(
							/* translators: %d: guest count. */
							_n( '%d guest', '%d guests', $party_size, 'foodord' ),
							$party_size
						)
					);
					?>
				</span>
			</div>
			<strong class="foodord-reservations-calendar-event__customer"><?php echo esc_html( (string) $reservation->customer_name ); ?></strong>
			<span class="foodord-reservations-calendar-event__table">
				<?php
				echo esc_html(
					$this->format_table_location(
						(string) ( $reservation->floor_name ?? '' ),
						(string) $reservation->table_name
					)
				);
				?>
			</span>
			<span class="foodord-reservations-calendar-event__status"><?php echo esc_html( $status_label ); ?></span>
		</article>
		<?php
	}

	/**
	 * Render a month navigation button.
	 *
	 * @param string              $month     Target month in Y-m.
	 * @param string              $label     Accessible button label.
	 * @param array<string,mixed> $query     Current query args.
	 * @param string              $direction Navigation direction.
	 */
	private function render_calendar_month_button( string $month, string $label, array $query, string $direction ): void {
		?>
		<form class="foodord-reservations-calendar__nav-form" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
			<?php
			$this->render_hidden_field( 'page', $this->get_page_slug() );
			$this->render_hidden_field( 'reservation_tab', 'reservations' );
			$this->render_hidden_field( 'reservation_view', 'calendar' );
			$this->render_hidden_field( 'reservation_status', (string) $query['status'] );
			$this->render_hidden_field( 'reservation_search', (string) $query['search'] );
			$this->render_hidden_field( 'reservation_month', $month );
			?>
			<button type="submit" class="button button-secondary foodord-reservations-calendar__nav-button foodord-reservations-calendar__nav-button--<?php echo esc_attr( sanitize_html_class( $direction ) ); ?>" aria-label="<?php echo esc_attr( $label ); ?>">
				<span class="foodord-reservations-calendar__nav-icon" aria-hidden="true"><?php echo esc_html( 'previous' === $direction ? '<' : '>' ); ?></span>
			</button>
		</form>
		<?php
	}

	/**
	 * Group reservations by reservation date.
	 *
	 * @param array<int,object> $reservations Reservations.
	 * @return array<string,array<int,object>>
	 */
	private function group_reservations_by_date( array $reservations ): array {
		$grouped = array();
		foreach ( $reservations as $reservation ) {
			$date = isset( $reservation->reservation_date ) ? (string) $reservation->reservation_date : '';
			if ( '' === $date ) {
				continue;
			}

			if ( ! isset( $grouped[ $date ] ) ) {
				$grouped[ $date ] = array();
			}

			$grouped[ $date ][] = $reservation;
		}

		return $grouped;
	}

	/**
	 * Get the active Tables list filters.
	 *
	 * @return array{floor_id:int,search:string}
	 */
	private function get_table_list_filters(): array {
		$floor_id = absint( $this->get_post_text_field( 'reservation_table_floor' ) );
		if ( $floor_id <= 0 ) {
			$floor_id = absint( $this->get_query_text_field( 'reservation_table_floor' ) );
		}

		$search = $this->get_post_text_field( 'reservation_table_search' );
		if ( '' === $search ) {
			$search = $this->get_query_text_field( 'reservation_table_search' );
		}

		return array(
			'floor_id' => $floor_id,
			'search'   => $search,
		);
	}

	/**
	 * Filter reservation tables before pagination.
	 *
	 * @param array<int,object>                 $tables  Reservation tables.
	 * @param array{floor_id:int,search:string} $filters Active filters.
	 * @return array<int,object>
	 */
	private function filter_table_list( array $tables, array $filters ): array {
		return array_values(
			array_filter(
				$tables,
				static function ( $table ) use ( $filters ): bool {
					if ( $filters['floor_id'] > 0 && absint( $table->floor_id ?? 0 ) !== $filters['floor_id'] ) {
						return false;
					}

					if ( '' === $filters['search'] ) {
						return true;
					}

					$table_name = (string) ( $table->name ?? '' );

					return function_exists( 'mb_stripos' )
						? false !== mb_stripos( $table_name, $filters['search'] )
						: false !== stripos( $table_name, $filters['search'] );
				}
			)
		);
	}

	/**
	 * Get non-empty Tables filter query arguments.
	 *
	 * @param array{floor_id:int,search:string} $filters Active filters.
	 * @return array<string,int|string>
	 */
	private function get_table_filter_query_args( array $filters ): array {
		$query_args = array();

		if ( $filters['floor_id'] > 0 ) {
			$query_args['reservation_table_floor'] = $filters['floor_id'];
		}

		if ( '' !== $filters['search'] ) {
			$query_args['reservation_table_search'] = $filters['search'];
		}

		return $query_args;
	}

	/**
	 * Paginate a floor or table collection.
	 *
	 * @param array<int,object> $items    Items to paginate.
	 * @param string            $page_key Request key for the current page.
	 * @return array{items:array<int,object>,total:int,page:int,per_page:int,total_pages:int}
	 */
	private function paginate_management_items( array $items, string $page_key ): array {
		$total       = count( $items );
		$total_pages = max( 1, (int) ceil( $total / self::MANAGEMENT_ITEMS_PER_PAGE ) );
		$page        = min( $this->get_management_list_page( $page_key ), $total_pages );
		$offset      = ( $page - 1 ) * self::MANAGEMENT_ITEMS_PER_PAGE;

		return array(
			'items'       => array_values( array_slice( $items, $offset, self::MANAGEMENT_ITEMS_PER_PAGE ) ),
			'total'       => $total,
			'page'        => $page,
			'per_page'    => self::MANAGEMENT_ITEMS_PER_PAGE,
			'total_pages' => $total_pages,
		);
	}

	/**
	 * Read a floor or table list page from the current request.
	 *
	 * @param string $page_key Request key.
	 */
	private function get_management_list_page( string $page_key ): int {
		$page = absint( $this->get_post_text_field( $page_key ) );
		if ( $page <= 0 ) {
			$page = absint( $this->get_query_text_field( $page_key ) );
		}

		return max( 1, $page );
	}

	/**
	 * Render pagination for a floor or table list.
	 *
	 * @param array{total:int,page:int,per_page:int,total_pages:int} $results           Paginated result metadata.
	 * @param string                                                 $page_key          Current list page key.
	 * @param string                                                 $preserve_page_key Other list page key.
	 * @param array<string,int|string>                               $query_args         Additional query arguments.
	 */
	private function render_management_pagination( array $results, string $page_key, string $preserve_page_key, array $query_args = array() ): void {
		$base_url      = $this->get_tab_url( 'tables' );
		$preserve_page = $this->get_management_list_page( $preserve_page_key );

		if ( $preserve_page > 1 ) {
			$base_url = add_query_arg( $preserve_page_key, $preserve_page, $base_url );
		}
		if ( ! empty( $query_args ) ) {
			$base_url = add_query_arg( $query_args, $base_url );
		}

		$this->render_pagination_links( $results, $base_url, $page_key );
	}

	/**
	 * Render simple pagination controls.
	 *
	 * @param array{total:int,page:int,per_page:int,total_pages:int} $results Query result metadata.
	 * @param array<string,mixed>                                    $query   Current query args.
	 */
	private function render_pagination( array $results, array $query ): void {
		$base_url = add_query_arg(
			array(
				'page'            => $this->get_page_slug(),
				'reservation_tab' => 'reservations',
			),
			admin_url( 'admin.php' )
		);

		foreach ( array( 'status', 'date', 'search' ) as $query_key ) {
			if ( '' === (string) $query[ $query_key ] ) {
				continue;
			}

			$base_url = add_query_arg( 'reservation_' . $query_key, (string) $query[ $query_key ], $base_url );
		}

		$this->render_pagination_links( $results, $base_url, 'reservation_page' );
	}

	/**
	 * Render pagination links using the Reservations table design.
	 *
	 * @param array{total:int,page:int,per_page:int,total_pages:int} $results  Paginated result metadata.
	 * @param string                                                 $base_url Base admin URL.
	 * @param string                                                 $page_key Page query key.
	 */
	private function render_pagination_links( array $results, string $base_url, string $page_key ): void {
		if ( $results['total_pages'] <= 1 ) {
			return;
		}

		$links = paginate_links(
			array(
				'base'      => add_query_arg( $page_key, '%#%', $base_url ),
				'current'   => (int) $results['page'],
				'total'     => (int) $results['total_pages'],
				'prev_text' => __( 'Previous', 'foodord' ),
				'next_text' => __( 'Next', 'foodord' ),
				'type'      => 'array',
			)
		);

		if ( empty( $links ) || ! is_array( $links ) ) {
			return;
		}
		?>
		<div class="tablenav bottom foodord-reservations-pagination">
			<div class="tablenav-pages">
				<span class="displaying-num">
					<?php
					echo esc_html(
						sprintf(
							/* translators: %d: item count. */
							_n( '%d item', '%d items', (int) $results['total'], 'foodord' ),
							(int) $results['total']
						)
					);
					?>
				</span>
				<span class="pagination-links">
					<?php foreach ( $links as $link ) : ?>
						<?php echo wp_kses_post( $link ); ?>
					<?php endforeach; ?>
				</span>
			</div>
		</div>
		<?php
	}

	/**
	 * Render tables list.
	 *
	 * @param array<int,object> $tables Reservation tables.
	 */
	private function render_tables_list( array $tables ): void {
		if ( empty( $tables ) ) {
			echo '<p class="foodord-reservations-empty">' . esc_html__( 'No tables have been added yet.', 'foodord' ) . '</p>';
			return;
		}

		$filters = $this->get_table_list_filters();
		$tables  = $this->filter_table_list( $tables, $filters );
		if ( empty( $tables ) ) {
			echo '<p class="foodord-reservations-empty">' . esc_html__( 'No tables match the current filters.', 'foodord' ) . '</p>';
			return;
		}

		$filter_query = $this->get_table_filter_query_args( $filters );
		$pagination   = $this->paginate_management_items( $tables, 'reservation_table_page' );
		$tables       = $pagination['items'];
		?>
		<div class="foodord-reservations-table-scroll foodord-reservations-table-scroll--compact" role="region" aria-label="<?php esc_attr_e( 'Tables', 'foodord' ); ?>" tabindex="0">
			<table class="widefat foodord-reservations-table foodord-reservations-table--tables">
			<thead>
				<tr>
					<th scope="col"><?php esc_html_e( 'Table', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Capacity', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Duration', 'foodord' ); ?></th>
					<th scope="col"><?php esc_html_e( 'Actions', 'foodord' ); ?></th>
				</tr>
			</thead>
			<tbody>
				<?php foreach ( $tables as $table ) : ?>
					<tr
						data-foodord-reservation-table-row
						data-table-id="<?php echo esc_attr( (int) $table->id ); ?>"
						data-table-floor-id="<?php echo esc_attr( (int) $table->floor_id ); ?>"
						data-table-name="<?php echo esc_attr( (string) $table->name ); ?>"
						data-table-capacity="<?php echo esc_attr( (int) $table->capacity ); ?>"
						data-table-duration="<?php echo esc_attr( Foodord_Table_Reservations::sanitize_reservation_duration_minutes( $table->reservation_duration_minutes ?? 90 ) ); ?>"
					>
						<td>
							<?php
							echo esc_html(
								$this->format_table_location(
									(string) ( $table->floor_name ?? '' ),
									(string) $table->name
								)
							);
							?>
						</td>
						<td><?php echo esc_html( (string) absint( $table->capacity ) ); ?></td>
						<td>
							<?php
							echo esc_html(
								sprintf(
									/* translators: %d: duration in minutes. */
									__( '%d min', 'foodord' ),
									Foodord_Table_Reservations::sanitize_reservation_duration_minutes( $table->reservation_duration_minutes ?? 90 )
								)
							);
							?>
						</td>
						<td class="foodord-reservations-table__actions">
							<div class="foodord-reservations-actions">
								<form class="foodord-reservations-action-form" method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>">
									<input class="foodord-reservations-hidden-field" type="hidden" name="page" value="<?php echo esc_attr( $this->get_page_slug() ); ?>" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_action" value="edit_table" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="table_id" value="<?php echo esc_attr( (int) $table->id ); ?>" />
									<?php submit_button( __( 'Edit', 'foodord' ), 'secondary small', 'submit', false ); ?>
								</form>
								<form class="foodord-reservations-action-form foodord-reservations-action-form--delete" method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" data-foodord-reservation-table-delete-form data-confirm-message="<?php echo esc_attr__( 'Are you sure you want to delete this table?', 'foodord' ); ?>">
									<?php wp_nonce_field( 'foodord_delete_reservation_table' ); ?>
									<input class="foodord-reservations-hidden-field" type="hidden" name="action" value="foodord_delete_reservation_table" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="reservation_tab" value="tables" />
									<input class="foodord-reservations-hidden-field" type="hidden" name="table_id" value="<?php echo esc_attr( (int) $table->id ); ?>" />
									<?php submit_button( __( 'Delete', 'foodord' ), 'delete small', 'submit', false ); ?>
								</form>
							</div>
						</td>
					</tr>
				<?php endforeach; ?>
			</tbody>
			</table>
		</div>
		<?php $this->render_management_pagination( $pagination, 'reservation_table_page', 'reservation_floor_page', $filter_query ); ?>
		<?php
	}

	/**
	 * Get table currently being edited.
	 *
	 * @return object|null
	 */
	private function get_edit_table() {
		$action = $this->get_query_text_field( 'reservation_action' );
		if ( 'edit_table' !== $action ) {
			return null;
		}

		$table_id = absint( filter_input( INPUT_GET, 'table_id', FILTER_SANITIZE_NUMBER_INT ) );

		return $this->reservations->get_table( $table_id );
	}

	/**
	 * Get floor currently being edited.
	 *
	 * @return object|null
	 */
	private function get_edit_floor() {
		$action = $this->get_query_text_field( 'reservation_action' );
		if ( 'edit_floor' !== $action ) {
			return null;
		}

		$floor_id = absint( filter_input( INPUT_GET, 'floor_id', FILTER_SANITIZE_NUMBER_INT ) );

		return $this->reservations->get_floor( $floor_id );
	}

	/**
	 * Format a floor/table display label.
	 *
	 * @param string $floor_name Floor name.
	 * @param string $table_name Table name.
	 */
	private function format_table_location( string $floor_name, string $table_name ): string {
		if ( '' === $table_name ) {
			return __( 'Table deleted', 'foodord' );
		}

		if ( '' === $floor_name ) {
			return $table_name;
		}

		return $floor_name . ' - ' . $table_name;
	}

	/**
	 * Render admin notices.
	 */
	private function render_notice(): void {
		$notice = $this->get_pending_notice();
		if ( empty( $notice ) ) {
			return;
		}

		$message = isset( $notice['message'] ) ? sanitize_key( $notice['message'] ) : '';
		if ( '' === $message ) {
			return;
		}

		$detail = isset( $notice['detail'] ) && is_string( $notice['detail'] ) ? sanitize_text_field( $notice['detail'] ) : '';
		$type   = 'success';
		$text   = '';

		switch ( $message ) {
			case 'floor_saved':
				$text = __( 'Floor saved.', 'foodord' );
				break;
			case 'floor_deleted':
				$text = __( 'Floor deleted.', 'foodord' );
				break;
			case 'table_saved':
				$text = __( 'Table saved.', 'foodord' );
				break;
			case 'table_deleted':
				$text = __( 'Table deleted.', 'foodord' );
				break;
			case 'banner_saved':
				$text = __( 'Settings saved.', 'foodord' );
				break;
			case 'banner_error':
				$type = 'error';
				$text = __( 'Please select a valid image.', 'foodord' );
				break;
			case 'table_selection_error':
				$type = 'error';
				$text = '' !== $detail ? $detail : __( 'Unable to save floor plan.', 'foodord' );
				break;
			case 'reservation_updated':
				$text = __( 'Reservation updated.', 'foodord' );
				break;
			case 'reservation_created':
				$text = __( 'Reservation created.', 'foodord' );
				break;
			case 'reservation_email_sent':
				$text = __( 'Reservation email sent.', 'foodord' );
				break;
			case 'reservation_bulk_completed':
				$text = '' !== $detail ? $detail : __( 'Bulk action completed.', 'foodord' );
				break;
			case 'reservation_error':
				$type = 'error';
				$text = '' !== $detail ? $detail : __( 'Unable to complete the action.', 'foodord' );
				break;
			case 'floor_error':
				$type = 'error';
				$text = '' !== $detail ? $detail : __( 'Unable to complete the action.', 'foodord' );
				break;
			case 'table_error':
				$type = 'error';
				$text = '' !== $detail ? $detail : __( 'Unable to complete the action.', 'foodord' );
				break;
		}

		if ( '' === $text ) {
			return;
		}
		?>
		<div class="notice notice-<?php echo esc_attr( $type ); ?> is-dismissible">
			<p class="foodord-reservations-notice__message"><?php echo esc_html( $text ); ?></p>
		</div>
		<?php
	}

	/**
	 * Retrieve and clear the pending one-time notice.
	 *
	 * @return array{message:string,detail:string}|array{}
	 */
	private function get_pending_notice(): array {
		$key    = $this->get_notice_transient_key();
		$notice = get_transient( $key );

		delete_transient( $key );

		return is_array( $notice ) ? $notice : array();
	}

	/**
	 * Store a one-time notice for the current admin user.
	 *
	 * @param string $message Message key.
	 * @param string $detail  Optional detail text.
	 */
	private function store_notice( string $message, string $detail = '' ): void {
		set_transient(
			$this->get_notice_transient_key(),
			array(
				'message' => sanitize_key( $message ),
				'detail'  => sanitize_text_field( $detail ),
			),
			5 * MINUTE_IN_SECONDS
		);
	}

	/**
	 * Get the notice transient key for the current admin user.
	 */
	private function get_notice_transient_key(): string {
		return self::NOTICE_TRANSIENT_PREFIX . absint( get_current_user_id() );
	}

	/**
	 * Redirect back to the page with a message.
	 *
	 * @param string $message Message key.
	 * @param string $detail  Optional detail text.
	 */
	private function redirect_with_message( string $message, string $detail = '' ): void {
		$tab = $this->get_post_text_field( 'reservation_tab' );
		$url = '' !== $tab ? $this->get_tab_url( $tab ) : $this->get_page_url();

		$this->store_notice( $message, $detail );
		wp_safe_redirect( $url );
		exit;
	}

	/**
	 * Redirect after a bulk action while preserving list filters.
	 *
	 * @param string $message Message key.
	 * @param string $detail  Optional detail text.
	 */
	private function redirect_with_bulk_message( string $message, string $detail = '' ): void {
		$url    = $this->get_tab_url( 'reservations' );
		$status = sanitize_key( $this->get_post_text_field( 'reservation_return_status' ) );
		$date   = Foodord_Table_Reservations::normalize_date_input( $this->get_post_text_field( 'reservation_return_date' ) );
		$search = $this->get_post_text_field( 'reservation_return_search' );

		if ( in_array( $status, Foodord_Table_Reservations::get_status_keys(), true ) ) {
			$url = add_query_arg( 'reservation_status', $status, $url );
		}
		if ( '' !== $date ) {
			$url = add_query_arg( 'reservation_date', $date, $url );
		}
		if ( '' !== $search ) {
			$url = add_query_arg( 'reservation_search', $search, $url );
		}

		$this->store_notice( $message, $detail );
		wp_safe_redirect( $url );
		exit;
	}

	/**
	 * Read a sanitized text field from POST.
	 *
	 * @param string $key Field key.
	 * @return string
	 */
	private function get_post_text_field( string $key ): string {
		$value = filter_input( INPUT_POST, $key );

		return is_string( $value ) ? sanitize_text_field( wp_unslash( $value ) ) : '';
	}

	/**
	 * Read a sanitized textarea field from POST.
	 *
	 * @param string $key Field key.
	 * @return string
	 */
	private function get_post_textarea_field( string $key ): string {
		$value = filter_input( INPUT_POST, $key );

		return is_string( $value ) ? sanitize_textarea_field( wp_unslash( $value ) ) : '';
	}

	/**
	 * Read an object-like JSON payload from POST.
	 *
	 * @param string $key Field key.
	 * @return array<string|int,mixed>
	 */
	private function get_post_json_array_field( string $key ): array {
		$value = $this->get_post_textarea_field( $key );
		if ( '' === $value ) {
			return array();
		}

		$decoded = json_decode( $value, true );

		return is_array( $decoded ) ? $decoded : array();
	}

	/**
	 * Read the optional cancellation reason from POST.
	 *
	 * @return string
	 */
	private function get_post_cancellation_reason(): string {
		$value = filter_input( INPUT_POST, 'cancellation_reason' );

		return is_string( $value ) ? Foodord_Table_Reservations::sanitize_cancellation_reason( wp_unslash( $value ) ) : '';
	}

	/**
	 * Read an array field from POST.
	 *
	 * @param string $key Field key.
	 * @return array<int|string,mixed>
	 */
	private function get_post_array_field( string $key ): array {
		$value = filter_input( INPUT_POST, $key, FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
		if ( ! is_array( $value ) ) {
			return array();
		}

		$value = wp_unslash( $value );

		return is_array( $value ) ? map_deep( $value, 'sanitize_text_field' ) : array();
	}

	/**
	 * Read customer email content settings from POST.
	 *
	 * Values are sanitized against a strict field whitelist by the email service.
	 *
	 * @return array<string,mixed>
	 */
	private function get_post_email_content_settings(): array {
		$value = filter_input( INPUT_POST, 'reservation_email_content', FILTER_SANITIZE_FULL_SPECIAL_CHARS, FILTER_REQUIRE_ARRAY );
		if ( ! is_array( $value ) ) {
			return array();
		}

		return map_deep(
			wp_unslash( $value ),
			static function ( $field ): string {
				return sanitize_textarea_field( html_entity_decode( (string) $field, ENT_QUOTES | ENT_HTML5, 'UTF-8' ) );
			}
		);
	}

	/**
	 * Read a sanitized text field from query string.
	 *
	 * @param string $key Field key.
	 * @return string
	 */
	private function get_query_text_field( string $key ): string {
		$value = filter_input( INPUT_GET, $key, FILTER_SANITIZE_FULL_SPECIAL_CHARS );

		return is_string( $value ) ? sanitize_text_field( wp_unslash( $value ) ) : '';
	}

	/**
	 * Get the configured reservation banner image ID.
	 */
	private function get_banner_image_id(): int {
		$image_id = absint( get_option( self::OPTION_BANNER_IMAGE_ID, 0 ) );

		return $image_id > 0 && wp_attachment_is_image( $image_id ) ? $image_id : 0;
	}

	/**
	 * Check whether the reservation banner is disabled.
	 */
	private function is_banner_disabled(): bool {
		return '1' === (string) get_option( self::OPTION_BANNER_DISABLED, '1' );
	}

	/**
	 * Get the reservation banner image URL.
	 *
	 * @param int $image_id Attachment ID.
	 */
	private function get_banner_image_url( int $image_id ): string {
		if ( $image_id > 0 ) {
			$image_url = wp_get_attachment_image_url( $image_id, 'large' );
			if ( is_string( $image_url ) && '' !== $image_url ) {
				return $image_url;
			}
		}

		return $this->get_default_banner_image_url();
	}

	/**
	 * Get the default reservation banner image URL.
	 */
	private function get_default_banner_image_url(): string {
		return FOODORD_URL . 'public/images/table-reservations-banner.png';
	}

	/**
	 * Get reservation list filters.
	 *
	 * @return array{status:string,date:string,search:string,view:string,month:string,page:int,per_page:int}
	 */
	private function get_reservations_query(): array {
		$status = $this->get_query_text_field( 'reservation_status' );
		if ( '' !== $status && ! in_array( $status, Foodord_Table_Reservations::get_status_keys(), true ) ) {
			$status = '';
		}

		$date = Foodord_Table_Reservations::normalize_date_input( $this->get_query_text_field( 'reservation_date' ) );

		$view = $this->get_query_text_field( 'reservation_view' );
		if ( ! in_array( $view, array( 'list', 'calendar' ), true ) ) {
			$view = 'list';
		}

		$month = $this->get_query_text_field( 'reservation_month' );
		if ( '' !== $month && ! preg_match( '/^\d{4}-\d{2}$/', $month ) ) {
			$month = '';
		}

		return array(
			'status'   => $status,
			'date'     => $date,
			'search'   => $this->get_query_text_field( 'reservation_search' ),
			'view'     => $view,
			'month'    => $month,
			'page'     => max( 1, absint( filter_input( INPUT_GET, 'reservation_page', FILTER_SANITIZE_NUMBER_INT ) ) ),
			'per_page' => 10,
		);
	}

	/**
	 * Get the calendar period for the current query.
	 *
	 * @param array<string,mixed> $query Current query args.
	 * @return array{month:string,start:string,end:string,label:string,previous:string,next:string,days:int,offset:int}
	 */
	private function get_calendar_period( array $query ): array {
		$month = (string) $query['month'];
		if ( '' !== (string) $query['date'] ) {
			$month = substr( (string) $query['date'], 0, 7 );
		}

		if ( '' === $month || ! preg_match( '/^\d{4}-\d{2}$/', $month ) ) {
			$month = current_time( 'Y-m' );
		}

		$timezone = wp_timezone();
		$first    = DateTimeImmutable::createFromFormat( '!Y-m-d', $month . '-01', $timezone );
		if ( ! $first instanceof DateTimeImmutable ) {
			$first = new DateTimeImmutable( current_time( 'Y-m-01' ), $timezone );
		}

		$last   = $first->modify( 'last day of this month' );
		$offset = ( (int) $first->format( 'w' ) - $this->get_week_start_day() + 7 ) % 7;

		return array(
			'month'    => $first->format( 'Y-m' ),
			'start'    => $first->format( 'Y-m-d' ),
			'end'      => $last instanceof DateTimeImmutable ? $last->format( 'Y-m-d' ) : $first->format( 'Y-m-d' ),
			'label'    => wp_date( 'F Y', $first->getTimestamp(), $timezone ),
			'previous' => $first->modify( '-1 month' )->format( 'Y-m' ),
			'next'     => $first->modify( '+1 month' )->format( 'Y-m' ),
			'days'     => (int) $first->format( 't' ),
			'offset'   => $offset,
		);
	}

	/**
	 * Get the WordPress week start day as a PHP weekday index.
	 */
	private function get_week_start_day(): int {
		$start = absint( get_option( 'start_of_week', 1 ) );

		return $start >= 0 && $start <= 6 ? $start : 1;
	}

	/**
	 * Format a GMT datetime for display in the site's timezone.
	 *
	 * @param string $datetime Datetime in Y-m-d H:i:s GMT format.
	 * @return string
	 */
	private function format_datetime_from_gmt( string $datetime ): string {
		if ( '' === $datetime || '0000-00-00 00:00:00' === $datetime ) {
			return '';
		}

		$format    = trim( (string) get_option( 'date_format', 'F j, Y' ) . ' ' . (string) get_option( 'time_format', 'g:i a' ) );
		$formatted = get_date_from_gmt( $datetime, $format );

		return is_string( $formatted ) && '' !== $formatted ? $formatted : $datetime;
	}

	/**
	 * Format reservation date for display.
	 *
	 * @param string $date Date in Y-m-d format.
	 * @return string
	 */
	private function format_date( string $date ): string {
		return Foodord_Table_Reservations::format_display_date( $date );
	}

	/**
	 * Get a readable date placeholder based on the WordPress date format.
	 */
	private function get_date_placeholder(): string {
		return Foodord_Table_Reservations::get_date_placeholder();
	}

	/**
	 * Format reservation time for display.
	 *
	 * @param string $time Time in H:i:s format.
	 * @return string
	 */
	private function format_time( string $time ): string {
		$timestamp = strtotime( '1970-01-01 ' . $time );

		return $timestamp ? date_i18n( get_option( 'time_format' ), $timestamp ) : $time;
	}
}
