<?php
/**
 * Tutor single-booking administration interface.
 *
 * @package TutorHelper_Bookings
 */

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

/**
 * Renders and processes the free tutor single-booking form.
 */
final class TutorHelper_Tutor_Booking_Admin {

	/**
	 * Booking Hub tab identifier.
	 *
	 * @var string
	 */
	const TAB_KEY = 'add-booking';

	/**
	 * admin-post.php action used to save a tutor booking.
	 *
	 * @var string
	 */
	const SAVE_ACTION =
		'tutorhelper_save_tutor_booking';

    /**
     * admin-post.php action used to update a tutor booking.
     *
     * @var string
     */
    const UPDATE_ACTION =
        'tutorhelper_update_tutor_booking';

    /**
     * Nonce field used for booking updates.
     *
     * @var string
     */
    const UPDATE_NONCE_FIELD =
        'tutorhelper_tutor_booking_update_nonce';

    /**
     * Query argument identifying form mode.
     *
     * @var string
     */
    const MODE_ARGUMENT = 'mode';

    /**
     * Edit form mode.
     *
     * @var string
     */
    const MODE_EDIT = 'edit';

    /**
     * Query argument storing the calendar view to return to.
     *
     * @var string
     */
    const RETURN_VIEW_ARGUMENT =
        'calendar_view';

    /**
     * Query argument storing the calendar date to return to.
     *
     * @var string
     */
    const RETURN_DATE_ARGUMENT =
        'calendar_date';


    /**
     * AJAX action used to search TutorHelper students.
     *
     * @var string
     */
    const STUDENT_SEARCH_ACTION =
        'tutorhelper_search_booking_students';

    
    /**
     * AJAX action used to evaluate proposed booking conditions.
     *
     * @var string
     */
    const CONDITION_CHECK_ACTION =
        'tutorhelper_check_booking_conditions';

    /**
     * Nonce action used for booking-condition checks.
     *
     * @var string
     */
    const CONDITION_CHECK_NONCE =
        'tutorhelper_booking_condition_check';

    /**
     * AJAX action used to resolve a tutor booking preview price.
     *
     * @var string
     */
    const PRICE_PREVIEW_ACTION =
        'tutorhelper_tutor_booking_price_preview';

    /**
     * Nonce action used for booking price previews.
     *
     * @var string
     */
    const PRICE_PREVIEW_NONCE =
        'tutorhelper_tutor_booking_price_preview';

	/**
	 * Nonce field name.
	 *
	 * @var string
	 */
	const NONCE_FIELD =
		'tutorhelper_tutor_booking_nonce';

	/**
	 * Query argument used for form notices.
	 *
	 * @var string
	 */
	const NOTICE_ARGUMENT =
		'tutor_booking_notice';

	/**
	 * Query argument containing a saved booking ID.
	 *
	 * @var string
	 */
	const BOOKING_ARGUMENT =
		'tutor_booking_id';

  

	/**
	 * Register WordPress hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_filter(
			'tutorhelper_booking_hub_tabs',
			array(
				__CLASS__,
				'register_tab',
			)
		);

		add_action(
			'tutorhelper_booking_hub_render_tab',
			array(
				__CLASS__,
				'render_tab',
			),
			10,
			2
		);

		add_action(
			'admin_post_' . self::SAVE_ACTION,
			array(
				__CLASS__,
				'handle_save',
			)
		);

        add_action(
            'admin_post_' . self::UPDATE_ACTION,
            array(
                __CLASS__,
                'handle_update',
            )
        );

        add_action(
            'wp_ajax_' . self::STUDENT_SEARCH_ACTION,
            array(
                __CLASS__,
                'handle_student_search',
            )
        );

        add_action(
            'wp_ajax_' . self::CONDITION_CHECK_ACTION,
            array(
                __CLASS__,
                'handle_condition_check',
            )
        );

        add_action(
            'wp_ajax_' . self::PRICE_PREVIEW_ACTION,
            array(
                __CLASS__,
                'handle_price_preview',
            )
        );

	}

	/**
	 * Add the free single-booking tab to the Booking Hub.
	 *
	 * @param array $tabs Existing Booking Hub tabs.
	 *
	 * @return array
	 */
	public static function register_tab(
		$tabs
	) {
		$tabs = is_array( $tabs )
			? $tabs
			: array();

		$booking_tab = array(
			'label' => __(
				'Add Booking',
				'tutorhelper-bookings'
			),

			'icon' =>
				'dashicons-calendar-alt',

			'status' =>
				'available',

			'description' => __(
				'Create a single tutor-managed booking.',
				'tutorhelper-bookings'
			),
		);

		/*
		 * Position the form after Calendar when possible.
		 */
		$positioned_tabs = array();

		foreach ( $tabs as $key => $tab ) {
			$positioned_tabs[ $key ] =
				$tab;

			if ( 'calendar' === $key ) {
				$positioned_tabs[
					self::TAB_KEY
				] = $booking_tab;
			}
		}

		if (
			! isset(
				$positioned_tabs[
					self::TAB_KEY
				]
			)
		) {
			$positioned_tabs[
				self::TAB_KEY
			] = $booking_tab;
		}

		return $positioned_tabs;
	}

    /**
     * Return the resolved price for the tutor booking preview.
     *
     * This endpoint is advisory only. Booking save and update services
     * independently resolve the final authoritative price.
     *
     * @return void
     */
    public static function handle_price_preview() {

        if (
            ! current_user_can(
                TutorHelper_Booking_Hub::CAPABILITY
            )
        ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'You are not allowed to preview booking prices.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

        check_ajax_referer(
            self::PRICE_PREVIEW_NONCE,
            'nonce'
        );

        $student_user_id = isset(
            $_POST['student_user_id']
        )
            ? absint(
                wp_unslash(
                    $_POST['student_user_id']
                )
            )
            : 0;

        $booking_type_id = isset(
            $_POST['booking_type_id']
        )
            ? absint(
                wp_unslash(
                    $_POST['booking_type_id']
                )
            )
            : 0;

        $duration_minutes = isset(
            $_POST['duration_minutes']
        )
            ? absint(
                wp_unslash(
                    $_POST['duration_minutes']
                )
            )
            : 0;

        if (
            ! $student_user_id
            || ! $booking_type_id
            || ! $duration_minutes
        ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'The booking price cannot be calculated yet.',
                        'tutorhelper-bookings'
                    ),
                ),
                400
            );
        }

        $student =
            TutorHelper_Students::get_student(
                $student_user_id
            );

        if ( ! $student instanceof WP_User ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'The selected student could not be found.',
                        'tutorhelper-bookings'
                    ),
                ),
                400
            );
        }

        $pricing =
            TutorHelper_Booking_Records::resolve_pricing(
                $student_user_id,
                $booking_type_id,
                $duration_minutes
            );

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

        $currency =
            TutorHelper_Currency::get_currency();

        wp_send_json_success(
            array(
                'priceMinorUnits' =>
                    absint(
                        $pricing['price_minor_units']
                    ),

                'formattedPrice' =>
                    TutorHelper_Currency::format_minor_units(
                        $pricing['price_minor_units'],
                        $currency
                    ),

                'pricingBasis' =>
                    sanitize_key(
                        $pricing['pricing_basis']
                    ),
            )
        );
    }

	/**
	 * Render this module's Booking Hub tab.
	 *
	 * @param string $selected_tab Selected tab key.
	 * @param array  $tab          Tab definition.
	 *
	 * @return void
	 */
	public static function render_tab(
		$selected_tab,
		$tab
	) {
		unset( $tab );

		if (
			self::TAB_KEY
				!== $selected_tab
		) {
			return;
		}

		if (
			! current_user_can(
				TutorHelper_Booking_Hub::
					CAPABILITY
			)
		) {
			return;
		}

		self::render_notices();
		self::render_form();
	}

	/**
	 * Return the Add Booking tab URL.
	 *
	 * @param array $arguments Optional query arguments.
	 *
	 * @return string
	 */
	private static function get_tab_url(
		$arguments = array()
	) {
		$arguments = array_merge(
			array(
				'page' =>
					TutorHelper_Booking_Hub::
						PAGE_SLUG,

				'tab' =>
					self::TAB_KEY,
			),
			is_array( $arguments )
				? $arguments
				: array()
		);

		return add_query_arg(
			$arguments,
			admin_url( 'admin.php' )
		);
	}

    /**
     * Return a supported originating calendar view.
     *
     * @param string $method Request source: get or post.
     *
     * @return string
     */
    private static function get_return_view(
        $method = 'get'
    ) {
        $source = 'post' === $method
            ? $_POST // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            : $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.

        if (
            ! isset(
                $source[
                    self::RETURN_VIEW_ARGUMENT
                ]
            )
            || is_array(
                $source[
                    self::RETURN_VIEW_ARGUMENT
                ]
            )
        ) {
            return '';
        }

        $view = sanitize_key(
            wp_unslash(
                $source[
                    self::RETURN_VIEW_ARGUMENT
                ]
            )
        );

        return in_array(
            $view,
            array(
                'week',
                'month',
            ),
            true
        )
            ? $view
            : '';
    }

    /**
     * Return a valid originating calendar date.
     *
     * @param string $method Request source: get or post.
     *
     * @return string
     */
    private static function get_return_date(
        $method = 'get'
    ) {
        $source = 'post' === $method
            ? $_POST // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            : $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.

        if (
            ! isset(
                $source[
                    self::RETURN_DATE_ARGUMENT
                ]
            )
            || is_array(
                $source[
                    self::RETURN_DATE_ARGUMENT
                ]
            )
        ) {
            return '';
        }

        $value = sanitize_text_field(
            wp_unslash(
                $source[
                    self::RETURN_DATE_ARGUMENT
                ]
            )
        );

        $date =
            DateTimeImmutable::createFromFormat(
                '!Y-m-d',
                $value,
                new DateTimeZone( 'UTC' )
            );

        $errors =
            DateTimeImmutable::getLastErrors();

        if (
            false === $date
            || (
                is_array( $errors )
                && (
                    0 < $errors['warning_count']
                    || 0 < $errors['error_count']
                )
            )
            || $date->format( 'Y-m-d' )
                !== $value
        ) {
            return '';
        }

        return $value;
    }


    /**
     * Return the URL for editing one booking.
     *
     * @param int    $booking_id  Booking ID.
     * @param string $notice      Optional notice code.
     * @param string $return_view Optional calendar view.
     * @param string $return_date Optional calendar date.
     *
     * @return string
     */
    private static function get_edit_url(
        $booking_id,
        $notice = '',
        $return_view = '',
        $return_date = ''
    ) {
        $arguments = array(
            self::MODE_ARGUMENT =>
                self::MODE_EDIT,

            self::BOOKING_ARGUMENT =>
                absint( $booking_id ),
        );

        if ( '' !== $notice ) {
            $arguments[
                self::NOTICE_ARGUMENT
            ] = sanitize_key(
                $notice
            );
        }

        if (
            in_array(
                $return_view,
                array(
                    'week',
                    'month',
                ),
                true
            )
        ) {
            $arguments[
                self::RETURN_VIEW_ARGUMENT
            ] = $return_view;
        }

        if ( '' !== $return_date ) {
            $arguments[
                self::RETURN_DATE_ARGUMENT
            ] = $return_date;
        }

        return self::get_tab_url(
            $arguments
        );
    }

    


    /**
     * Return the Booking Hub calendar URL.
     *
     * @param object|null $booking Optional booking for date targeting.
     * @param string      $view    Optional calendar view.
     * @param string      $date    Optional selected calendar date.
     *
     * @return string
     */
    private static function get_calendar_url(
        $booking = null,
        $view = '',
        $date = ''
    ) {
        $arguments = array(
            'page' =>
                TutorHelper_Booking_Hub::
                    PAGE_SLUG,

            'tab' =>
                'calendar',
        );

        if (
            in_array(
                $view,
                array(
                    'week',
                    'month',
                ),
                true
            )
        ) {
            $arguments['view'] =
                $view;
        }

        if ( '' !== $date ) {
            $arguments['date'] =
                $date;
        } elseif (
            is_object( $booking )
            && ! empty(
                $booking->booking_start
            )
        ) {
            try {
                $utc =
                    new DateTimeZone(
                        'UTC'
                    );

                $timezone =
                    new DateTimeZone(
                        $booking->timezone
                            ? $booking->timezone
                            : wp_timezone()
                                ->getName()
                    );

                $booking_date =
                    new DateTimeImmutable(
                        $booking
                            ->booking_start,
                        $utc
                    );

                $arguments['date'] =
                    $booking_date
                        ->setTimezone(
                            $timezone
                        )
                        ->format(
                            'Y-m-d'
                        );
            } catch ( Exception $exception ) {
                // Calendar can safely use its normal selected date.
            }
        }

        return add_query_arg(
            $arguments,
            admin_url( 'admin.php' )
        );
    }


	/**
	 * Return a safe redirect URL after submission.
	 *
	 * @param string $notice    Notice code.
	 * @param int    $booking_id Optional booking ID.
	 *
	 * @return string
	 */
	private static function get_redirect_url(
		$notice,
		$booking_id = 0
	) {
		$arguments = array(
			self::NOTICE_ARGUMENT =>
				sanitize_key( $notice ),
		);

		if ( $booking_id ) {
			$arguments[
				self::BOOKING_ARGUMENT
			] = absint( $booking_id );
		}

		return self::get_tab_url(
			$arguments
		);
	}

	/**
	 * Verify a tutor booking write request.
	 *
	 * @return void
	 */
	private static function verify_request() {
		if (
			! current_user_can(
				TutorHelper_Booking_Hub::
					CAPABILITY
			)
		) {
			wp_die(
                esc_html__(
                    'You are not allowed to create bookings.',
                    'tutorhelper-bookings'
                ),
                esc_html__(
                    'Permission denied',
                    'tutorhelper-bookings'
                ),
                array(
                    'response' => 403,
                )
            );
		}

	}


    /**
     * Read one scalar AJAX request value.
     *
     * @param string $key Request key.
     *
     * @return string
     */
    private static function get_ajax_value(
        $key
    ) {
        if (
            ! isset( $_POST[ $key ] ) // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            || is_array( $_POST[ $key ] ) // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
        ) {
            return '';
        }

        return sanitize_text_field(
            wp_unslash(
                $_POST[ $key ] // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            )
        );
    }

    /**
     * Return presentation-safe condition data.
     *
     * @param array $conditions Evaluator conditions.
     *
     * @return array
     */
    private static function prepare_condition_response(
        $conditions
    ) {
        $prepared = array();

        if ( ! is_array( $conditions ) ) {
            return $prepared;
        }

        foreach ( $conditions as $condition ) {
            if ( ! is_array( $condition ) ) {
                continue;
            }

            $code = isset(
                $condition['code']
            )
                ? sanitize_key(
                    $condition['code']
                )
                : '';

            $severity = isset(
                $condition['severity']
            )
                ? sanitize_key(
                    $condition['severity']
                )
                : '';

            $message = isset(
                $condition['message']
            )
                ? sanitize_text_field(
                    $condition['message']
                )
                : '';

            if (
                '' === $code
                || '' === $severity
                || '' === $message
            ) {
                continue;
            }

            if (
                ! in_array(
                    $severity,
                    array(
                        TutorHelper_Booking_Conditions::
                            SEVERITY_INFO,

                        TutorHelper_Booking_Conditions::
                            SEVERITY_WARNING,

                        TutorHelper_Booking_Conditions::
                            SEVERITY_BLOCKING,
                    ),
                    true
                )
            ) {
                continue;
            }

            $prepared[] = array(
                'code' =>
                    $code,

                'severity' =>
                    $severity,

                'message' =>
                    $message,
            );
        }

        return $prepared;
    }


    /**
     * Evaluate a proposed tutor booking via AJAX.
     *
     * This endpoint is advisory. Final save enforcement remains in the
     * booking save and update services.
     *
     * @return void
     */
    public static function handle_condition_check() {
        if (
            ! current_user_can(
                TutorHelper_Booking_Hub::
                    CAPABILITY
            )
        ) {
            wp_send_json_error(
                array(
                    'code' =>
                        'tutorhelper_booking_conditions_forbidden',

                    'message' => __(
                        'You are not allowed to evaluate bookings.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

        check_ajax_referer(
            self::CONDITION_CHECK_NONCE,
            'nonce'
        );

        $booking_type_id = absint(
            self::get_ajax_value(
                'booking_type_id'
            )
        );

        $booking_date =
            self::get_ajax_value(
                'booking_date'
            );

        $start_time =
            self::get_ajax_value(
                'start_time'
            );

        $end_time =
            self::get_ajax_value(
                'end_time'
            );

        $timezone =
            self::get_ajax_value(
                'timezone'
            );

        $location_type =
            sanitize_key(
                self::get_ajax_value(
                    'location_type'
                )
            );

        $exclude_booking_id = absint(
            self::get_ajax_value(
                'exclude_booking_id'
            )
        );

        /*
        * The exclusion ID is supplied by the edit form so a booking does not
        * conflict with itself. Never allow AJAX input to exclude a booking
        * belonging to another tutor.
        */

        if ( $exclude_booking_id ) {
            $excluded_booking =
                TutorHelper_Booking_Records::
                    get_by_id(
                        $exclude_booking_id
                    );

            if (
                ! $excluded_booking
                || get_current_user_id()
                    !== absint(
                        $excluded_booking
                            ->tutor_user_id
                    )
            ) {
                wp_send_json_error(
                    array(
                        'code' =>
                            'tutorhelper_booking_conditions_exclusion_forbidden',

                        'message' =>
                            __(
                                'You are not allowed to exclude this booking from the availability check.',
                                'tutorhelper-bookings'
                            ),
                    ),
                    403
                );
            }
        }

        /*
        * Incomplete form values are not exceptional. The browser should
        * simply wait until all required condition fields are available.
        */
        if (
            ! $booking_type_id
            || '' === $booking_date
            || '' === $start_time
            || '' === $end_time
            || '' === $location_type
        ) {
            wp_send_json_success(
                array(
                    'complete' =>
                        false,

                    'canTutorSave' =>
                        true,

                    'conditions' =>
                        array(),
                )
            );
        }

        if ( '' === $timezone ) {
            $timezone =
                wp_timezone()
                    ->getName();
        }

        $evaluation =
            TutorHelper_Booking_Conditions::
                evaluate(
                    array(
                        'tutor_user_id' =>
                            get_current_user_id(),

                        'booking_type_id' =>
                            $booking_type_id,

                        'booking_start' =>
                            $booking_date
                            . ' '
                            . $start_time,

                        'booking_end' =>
                            $booking_date
                            . ' '
                            . $end_time,

                        'timezone' =>
                            $timezone,

                        'location_type' =>
                            $location_type,

                        'exclude_booking_id' =>
                            $exclude_booking_id,
                    )
                );

        if ( is_wp_error( $evaluation ) ) {
            wp_send_json_error(
                array(
                    'code' =>
                        sanitize_key(
                            $evaluation
                                ->get_error_code()
                        ),

                    'message' =>
                        sanitize_text_field(
                            $evaluation
                                ->get_error_message()
                        ),
                ),
                400
            );
        }

        $conditions =
            self::prepare_condition_response(
                isset(
                    $evaluation['conditions']
                )
                    ? $evaluation['conditions']
                    : array()
            );

        wp_send_json_success(
            array(
                'complete' =>
                    true,

                'canTutorSave' =>
                    ! empty(
                        $evaluation[
                            'can_tutor_save'
                        ]
                    ),

                'isFullyPubliclyBookable' =>
                    ! empty(
                        $evaluation[
                            'is_fully_publicly_bookable'
                        ]
                    ),

                'hasWarnings' =>
                    ! empty(
                        $evaluation[
                            'warnings'
                        ]
                    ),

                'hasBlockingConditions' =>
                    ! empty(
                        $evaluation[
                            'blocking_conditions'
                        ]
                    ),

                'conditions' =>
                    $conditions,
            )
        );
    }


	/**
     * Read and sanitise one scalar POST value.
     *
     * @param string $key Request field key.
     *
     * @return string
     */
    private static function get_post_value(
        $key
    ) {
        if (
            ! isset( $_POST[ $key ] ) // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            || is_array(
                $_POST[ $key ] // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            )
        ) {
            return '';
        }

        return sanitize_text_field(
            wp_unslash(
                $_POST[ $key ] // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            )
        );
    }

    /**
     * Return a positive booking ID from the current request.
     *
     * @param string $method Request source: get or post.
     *
     * @return int
     */
    private static function get_request_booking_id(
        $method = 'get'
    ) {
        $source = 'post' === $method
            ? $_POST // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
            : $_GET; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.

        if (
            ! isset(
                $source[
                    self::BOOKING_ARGUMENT
                ]
            )
            || is_array(
                $source[
                    self::BOOKING_ARGUMENT
                ]
            )
        ) {
            return 0;
        }

        return absint(
            wp_unslash(
                $source[
                    self::BOOKING_ARGUMENT
                ]
            )
        );
    }

    /**
     * Determine whether the current form request is edit mode.
     *
     * @return bool
     */
    private static function is_edit_mode() {
        $mode = isset(
            $_GET[ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
                self::MODE_ARGUMENT
            ]
        )
        && ! is_array(
            $_GET[ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
                self::MODE_ARGUMENT
            ]
        )
            ? sanitize_key(
                wp_unslash(
                    $_GET[ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Request value is read only after the calling admin/AJAX action has completed capability and nonce verification; value is sanitized before use.
                        self::MODE_ARGUMENT
                    ]
                )
            )
            : '';

        return self::MODE_EDIT === $mode
            && 0 < self::get_request_booking_id();
    }


    /**
     * Retrieve an editable booking belonging to the current tutor.
     *
     * @param int $booking_id Booking ID.
     *
     * @return object|WP_Error
     */
    private static function get_editable_booking(
        $booking_id
    ) {
        $booking_id = absint(
            $booking_id
        );

        if ( ! $booking_id ) {
            return new WP_Error(
                'tutorhelper_booking_update_id_missing',
                __(
                    'A booking is required.',
                    'tutorhelper-bookings'
                )
            );
        }

        $booking =
            TutorHelper_Booking_Records::get_by_id(
                $booking_id
            );

        if ( ! $booking ) {
            return new WP_Error(
                'tutorhelper_booking_update_not_found',
                __(
                    'The booking could not be found.',
                    'tutorhelper-bookings'
                )
            );
        }

        if (
            get_current_user_id()
                !== absint(
                    $booking->tutor_user_id
                )
        ) {
            return new WP_Error(
                'tutorhelper_booking_update_forbidden',
                __(
                    'You are not allowed to edit this booking.',
                    'tutorhelper-bookings'
                )
            );
        }

        if (
            TutorHelper_Booking_Records::
                STATUS_CANCELLED
                === sanitize_key(
                    $booking->status
                )
        ) {
            return new WP_Error(
                'tutorhelper_booking_update_cancelled',
                __(
                    'A cancelled booking cannot be edited.',
                    'tutorhelper-bookings'
                )
            );
        }

        return $booking;
    }


    /**
     * Build local editable datetime values from a stored booking.
     *
     * @param object $booking Booking record.
     *
     * @return array|WP_Error
     */
    private static function get_booking_local_values(
        $booking
    ) {
        $timezone_name =
            sanitize_text_field(
                $booking->timezone
            );

        if ( '' === $timezone_name ) {
            $timezone_name =
                wp_timezone()->getName();
        }

        try {
            $timezone =
                new DateTimeZone(
                    $timezone_name
                );

            $utc =
                new DateTimeZone( 'UTC' );

            $start =
                DateTimeImmutable::createFromFormat(
                    '!Y-m-d H:i:s',
                    $booking->booking_start,
                    $utc
                );

            $end =
                DateTimeImmutable::createFromFormat(
                    '!Y-m-d H:i:s',
                    $booking->booking_end,
                    $utc
                );
        } catch ( Exception $exception ) {
            return new WP_Error(
                'tutorhelper_booking_update_datetime_invalid',
                __(
                    'The stored booking date or timezone is invalid.',
                    'tutorhelper-bookings'
                )
            );
        }

        if (
            false === $start
            || false === $end
        ) {
            return new WP_Error(
                'tutorhelper_booking_update_datetime_invalid',
                __(
                    'The stored booking date or time is invalid.',
                    'tutorhelper-bookings'
                )
            );
        }

        $local_start =
            $start->setTimezone(
                $timezone
            );

        $local_end =
            $end->setTimezone(
                $timezone
            );

        return array(
            'timezone' =>
                $timezone->getName(),

            'booking_date' =>
                $local_start->format(
                    'Y-m-d'
                ),

            'start_time' =>
                $local_start->format(
                    'H:i'
                ),

            'end_time' =>
                $local_end->format(
                    'H:i'
                ),
        );
    }


    /**
     * Build values used by create and edit form modes.
     *
     * @param object|null $booking Existing booking in edit mode.
     *
     * @return array|WP_Error
     */
    private static function get_form_state(
        $booking = null
    ) {
        if ( ! $booking ) {
            return array(
                'booking_id' =>
                    0,

                'student_user_id' =>
                    0,

                'student_name' =>
                    '',

                'student_email' =>
                    '',

                'student_username' =>
                    '',

                'booking_type_id' =>
                    0,

                'booking_date' =>
                    wp_date(
                        'Y-m-d',
                        null,
                        wp_timezone()
                    ),

                'start_time' =>
                    '',

                'end_time' =>
                    '',

                'timezone' =>
                    wp_timezone()
                        ->getName(),

                'status' =>
                    TutorHelper_Booking_Records::
                        STATUS_CONFIRMED,

                'location_type' =>
                    'online',

                'location_details' =>
                    '',

                'notes' =>
                    '',
            );
        }

        $local_values =
            self::get_booking_local_values(
                $booking
            );

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

        $student =
            get_user_by(
                'id',
                absint(
                    $booking->student_user_id
                )
            );

        return array(
            'booking_id' =>
                absint(
                    $booking->id
                ),

            'student_user_id' =>
                absint(
                    $booking->student_user_id
                ),

            /*
            * Prefer booking snapshots for historical identity display.
            */
            'student_name' =>
                sanitize_text_field(
                    $booking->student_name
                ),

            'student_email' =>
                sanitize_email(
                    $booking->student_email
                ),

            'student_username' =>
                $student instanceof WP_User
                    ? sanitize_user(
                        $student->user_login
                    )
                    : '',

            'booking_type_id' =>
                absint(
                    $booking->booking_type_id
                ),

            'booking_date' =>
                $local_values[
                    'booking_date'
                ],

            'start_time' =>
                $local_values[
                    'start_time'
                ],

            'end_time' =>
                $local_values[
                    'end_time'
                ],

            'timezone' =>
                $local_values[
                    'timezone'
                ],

            'status' =>
                sanitize_key(
                    $booking->status
                ),

            'location_type' =>
                sanitize_key(
                    $booking->location_type
                ),

            'location_details' =>
                sanitize_textarea_field(
                    $booking->location_details
                ),

            'notes' =>
                sanitize_textarea_field(
                    $booking->notes
                ),
        );
    }





    /**
     * Search TutorHelper students for the Add Booking form.
     *
     * @return void
     */
    public static function handle_student_search() {
        if (
            ! current_user_can(
                TutorHelper_Booking_Hub::CAPABILITY
            )
        ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'You are not allowed to search students.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

        check_ajax_referer(
            self::STUDENT_SEARCH_ACTION,
            'nonce'
        );

        $search = isset( $_POST['search'] )
            && ! is_array( $_POST['search'] )
                ? trim(
                    sanitize_text_field(
                        wp_unslash(
                            $_POST['search']
                        )
                    )
                )
                : '';

        if ( strlen( $search ) < 2 ) {
            wp_send_json_success(
                array(
                    'students' => array(),
                )
            );
        }

        $result =
            TutorHelper_Students::get_students(
                array(
                    'search' =>
                        $search,

                    'page' =>
                        1,

                    'per_page' =>
                        20,

                    'orderby' =>
                        'display_name',

                    'order' =>
                        'ASC',
                )
            );

        $students = array();

        if (
            isset( $result['students'] )
            && is_array(
                $result['students']
            )
        ) {
            foreach (
                $result['students'] as $student
            ) {
                if (
                    ! $student instanceof WP_User
                ) {
                    continue;
                }

                $students[] = array(
                    'id' =>
                        absint( $student->ID ),

                    'name' =>
                        sanitize_text_field(
                            $student->display_name
                        ),

                    'email' =>
                        sanitize_email(
                            $student->user_email
                        ),

                    'username' =>
                        sanitize_user(
                            $student->user_login
                        ),
                );
            }
        }

        wp_send_json_success(
            array(
                'students' =>
                    $students,
            )
        );
    }



	/**
	 * Process the tutor single-booking form.
	 *
	 * @return void
	 */
	public static function handle_save() {
		self::verify_request();

        check_admin_referer(
            self::SAVE_ACTION,
            self::NONCE_FIELD
        );

		$data = array(
			'student_user_id' =>
				self::get_post_value(
					'student_user_id'
				),

			'booking_type_id' =>
				self::get_post_value(
					'booking_type_id'
				),

			'booking_date' =>
				self::get_post_value(
					'booking_date'
				),

			'start_time' =>
				self::get_post_value(
					'start_time'
				),

			'end_time' =>
				self::get_post_value(
					'end_time'
				),

			'timezone' =>
				self::get_post_value(
					'timezone'
				),

			'status' =>
				self::get_post_value(
					'status'
				),

			'location_type' =>
				self::get_post_value(
					'location_type'
				),

			'location_details' =>
				self::get_post_value(
					'location_details'
				),

			'notes' =>
				self::get_post_value(
					'notes'
				),
		);

		/**
         * Filters the result of an Add Booking submission
         * before Core creates its normal single booking.
         *
         * Returning null leaves the request to Core.
         * Extensions may return the same array|WP_Error
         * result contract used by the Core save service.
         *
         * @param null|array|WP_Error $result        Save result.
         * @param array               $data          Core booking data.
         * @param int                 $tutor_user_id Current tutor ID.
         */
        $result = apply_filters(
            'tutorhelper_tutor_booking_create_result',
            null,
            $data,
            get_current_user_id()
        );

        if ( null === $result ) {
            $result =
                TutorHelper_Tutor_Booking_Save::save(
                    $data,
                    get_current_user_id()
                );
        }

		if ( is_wp_error( $result ) ) {
			TutorHelper_Logger::warning(
				'Tutor booking form submission was rejected.',
				array(
					'tutor_user_id' =>
						get_current_user_id(),

					'error_code' =>
						$result
							->get_error_code(),
				)
			);

			wp_safe_redirect(
				self::get_redirect_url(
					$result
						->get_error_code()
				)
			);

			exit;
		}

		$booking_id = isset(
			$result['booking_id']
		)
			? absint(
				$result['booking_id']
			)
			: 0;

		$notice = isset(
            $result['notice']
        )
            ? sanitize_key(
                $result['notice']
            )
            : 'saved';

        wp_safe_redirect(
            self::get_redirect_url(
                $notice,
                $booking_id
            )
        );

		exit;
	}


    /**
     * Process an individual tutor booking update.
     *
     * @return void
     */
    public static function handle_update() {
        if (
            ! current_user_can(
                TutorHelper_Booking_Hub::
                    CAPABILITY
            )
        ) {
            wp_die(
                esc_html__(
                    'You are not allowed to edit bookings.',
                    'tutorhelper-bookings'
                ),
                esc_html__(
                    'Permission denied',
                    'tutorhelper-bookings'
                ),
                array(
                    'response' => 403,
                )
            );
        }

        check_admin_referer(
            self::UPDATE_ACTION,
            self::UPDATE_NONCE_FIELD
        );

        $booking_id =
            self::get_request_booking_id(
                'post'
            );

        $data = array(
            'booking_type_id' =>
                self::get_post_value(
                    'booking_type_id'
                ),

            'booking_date' =>
                self::get_post_value(
                    'booking_date'
                ),

            'start_time' =>
                self::get_post_value(
                    'start_time'
                ),

            'end_time' =>
                self::get_post_value(
                    'end_time'
                ),

            'timezone' =>
                self::get_post_value(
                    'timezone'
                ),

            'status' =>
                self::get_post_value(
                    'status'
                ),

            'cancellation_reason' =>
                self::get_post_value(
                    'cancellation_reason'
                ),

            'location_type' =>
                self::get_post_value(
                    'location_type'
                ),

            'location_details' =>
                self::get_post_value(
                    'location_details'
                ),

            'notes' =>
                self::get_post_value(
                    'notes'
                ),
        );

        $return_view =
            self::get_return_view(
                'post'
            );

        $return_date =
            self::get_return_date(
                'post'
            );

        $result =
            TutorHelper_Tutor_Booking_Update::
                update(
                    $booking_id,
                    $data,
                    get_current_user_id()
                );

        if ( is_wp_error( $result ) ) {
            TutorHelper_Logger::warning(
                'Tutor booking update form was rejected.',
                array(
                    'booking_id' =>
                        $booking_id,

                    'tutor_user_id' =>
                        get_current_user_id(),

                    'error_code' =>
                        $result
                            ->get_error_code(),
                )
            );

            wp_safe_redirect(
                self::get_edit_url(
                    $booking_id,
                    $result->get_error_code(),
                    $return_view,
                    $return_date
                )
            );

            exit;
        }

        if (
            is_object( $result )
            && isset( $result->status )
            && TutorHelper_Booking_Records::
                STATUS_CANCELLED
            === sanitize_key(
                $result->status
            )
        ) {
            wp_safe_redirect(
                self::get_calendar_url(
                    $result,
                    $return_view,
                    $return_date
                )
            );

            exit;
        }

        wp_safe_redirect(
            self::get_edit_url(
                $booking_id,
                'updated',
                $return_view,
                $return_date
            )
        );

        exit;
    }



	/**
	 * Return user-facing notice definitions.
	 *
	 * The key is an internal error or success code. Request content is
	 * never rendered directly.
	 *
	 * @return array
	 */
	private static function get_notice_messages() {
		$messages = array(
			'saved' => array(
				'type' =>
					'success',

				'message' => __(
					'The booking was created successfully.',
					'tutorhelper-bookings'
				),
			),

            'updated' => array(
                'type' =>
                    'success',

                'message' => __(
                    'The booking was updated successfully.',
                    'tutorhelper-bookings'
                ),
            ),

            'tutorhelper_booking_update_id_missing' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'A booking was not selected.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_booking_update_not_found' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'The booking could not be found.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_booking_update_forbidden' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'You are not allowed to edit this booking.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_booking_update_cancelled' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'A cancelled booking cannot be edited.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_booking_update_failed' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'The booking could not be updated.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_booking_update_datetime_invalid' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'The stored booking date or timezone is invalid.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_tutor_booking_cancel_reason_required' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'Enter a reason for cancelling this lesson.',
                        'tutorhelper-bookings'
                    ),
                ),

			'tutorhelper_tutor_booking_tutor_missing' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'A tutor account was not available.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_tutor_not_found' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'The tutor account could not be found.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_student_missing' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Select a student.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_student_not_found' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'The selected TutorHelper student could not be found.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_type_missing' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Select a Booking Type.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_booking_type_not_found' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'The selected Booking Type could not be found.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_booking_type_inactive' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'The selected Booking Type is not active.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_date_invalid' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Enter a valid booking date.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_start_time_invalid' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Enter a valid start time.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_end_time_invalid' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Enter a valid end time.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_end_before_start' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'The end time must be after the start time.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_status_invalid' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Select a valid booking status.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_tutor_booking_location_invalid' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'Select a valid booking location.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_booking_time_conflict' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'You already have another booking during this time.',
						'tutorhelper-bookings'
					),
				),

			'tutorhelper_booking_create_failed' =>
				array(
					'type' =>
						'error',

					'message' => __(
						'The booking could not be created.',
						'tutorhelper-bookings'
					),
				),
            
            'tutorhelper_tutor_booking_tutor_leave' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'This booking cannot be saved because you are marked as unavailable on the selected date.',
                        'tutorhelper-bookings'
                    ),
                ),

            'tutorhelper_tutor_booking_conditions_blocked' =>
                array(
                    'type' =>
                        'error',

                    'message' => __(
                        'This booking cannot be saved because one or more booking conditions prevent it.',
                        'tutorhelper-bookings'
                    ),
                ),
		);
        
        /**
         * Filters Add Booking admin notice definitions.
         *
         * Extensions may add notices for additional booking
         * creation workflows.
         *
         * @param array $messages Notice definitions.
         */
        return apply_filters(
            'tutorhelper_tutor_booking_notice_messages',
            $messages
        );
	}

	/**
	 * Render a form notice from a whitelisted code.
	 *
	 * @return void
	 */
	private static function render_notices() {
		$notice_code = isset(
			$_GET[ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only request state used for navigation or feedback; value is sanitized and no state change occurs.
				self::NOTICE_ARGUMENT
			]
		)
			? sanitize_key(
				wp_unslash(
					$_GET[ // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only request state used for navigation or feedback; value is sanitized and no state change occurs.
						self::NOTICE_ARGUMENT
					]
				)
			)
			: '';

		if ( '' === $notice_code ) {
			return;
		}

		$messages =
			self::get_notice_messages();

		$notice = isset(
			$messages[ $notice_code ]
		)
			? $messages[ $notice_code ]
			: array(
				'type' =>
					'error',

				'message' => __(
					'The booking could not be created. Check the details and try again.',
					'tutorhelper-bookings'
				),
			);

		$notice_class =
			'success' === $notice['type']
				? 'notice-success'
				: 'notice-error';

		?>
		<div
			class="notice <?php
				echo esc_attr(
					$notice_class
				);
			?> is-dismissible"
		>
			<p>
				<?php
				echo esc_html(
					$notice['message']
				);
				?>
			</p>
		</div>
		<?php
	}

	

	/**
	 * Return active Booking Types.
	 *
	 * @return array
	 */
	private static function get_booking_types() {
		return TutorHelper_Booking_Types::
			get_active();
	}

	/**
	 * Render the free tutor single-booking form.
	 *
	 * @return void
	 */
	private static function render_form() {
        $edit_mode =
            self::is_edit_mode();

        $booking = null;

        if ( $edit_mode ) {
            $booking =
                self::get_editable_booking(
                    self::get_request_booking_id()
                );

            if ( is_wp_error( $booking ) ) {
                self::render_edit_error(
                    $booking
                );

                return;
            }
        }

        $form_state =
            self::get_form_state(
                $booking
            );

        if ( is_wp_error( $form_state ) ) {
            self::render_edit_error(
                $form_state
            );

            return;
        }

        $booking_types =
            self::get_booking_types();

        $form_action =
            $edit_mode
                ? self::UPDATE_ACTION
                : self::SAVE_ACTION;

        $nonce_field =
            $edit_mode
                ? self::UPDATE_NONCE_FIELD
                : self::NONCE_FIELD;

		?>
		<section class="tutorhelper-tutor-booking">
			<header class="tutorhelper-tutor-booking__header">
				<div>
					<h2>
						<?php
						echo esc_html(
                            $edit_mode
                                ? __(
                                    'Edit booking',
                                    'tutorhelper-bookings'
                                )
                                : __(
                                    'Create a booking',
                                    'tutorhelper-bookings'
                                )
                        );
						?>
					</h2>

					<p>
						<?php
						echo esc_html(
                            $edit_mode
                                ? __(
                                    'Update this tutor-managed lesson. The student attached to the booking cannot be changed.',
                                    'tutorhelper-bookings'
                                )
                                : __(
                                    'Create one tutor-managed lesson. Public availability restrictions will not prevent you choosing a different time or location.',
                                    'tutorhelper-bookings'
                                )
                        );
						?>
					</p>
				</div>
			</header>

			

			<?php if ( empty( $booking_types ) ) : ?>
				<div class="notice notice-warning inline">
					<p>
						<?php
						echo esc_html__(
							'Create and activate a Booking Type before adding a booking.',
							'tutorhelper-bookings'
						);
						?>
					</p>
				</div>
			<?php endif; ?>

			<form
                method="post"
                action="<?php
                    echo esc_url(
                        admin_url(
                            'admin-post.php'
                        )
                    );
                ?>"
                class="tutorhelper-tutor-booking__form"
                data-mode="<?php
                    echo esc_attr(
                        $edit_mode
                            ? self::MODE_EDIT
                            : 'create'
                    );
                ?>"
                data-cancelled-status="<?php
                    echo esc_attr(
                        TutorHelper_Booking_Records::
                            STATUS_CANCELLED
                    );
                ?>"
                data-booking-condition-form
                data-condition-ajax-url="<?php
                    echo esc_url(
                        admin_url(
                            'admin-ajax.php'
                        )
                    );
                ?>"
                data-condition-action="<?php
                    echo esc_attr(
                        self::CONDITION_CHECK_ACTION
                    );
                ?>"
                data-condition-nonce="<?php
                    echo esc_attr(
                        wp_create_nonce(
                            self::CONDITION_CHECK_NONCE
                        )
                    );
                ?>"
                data-condition-booking-id="<?php
                    echo esc_attr(
                        $edit_mode
                            ? absint(
                                $form_state[
                                    'booking_id'
                                ]
                            )
                            : 0
                    );
                ?>"

                data-condition-label-checking="<?php
                    echo esc_attr__(
                        'Checking booking availability…',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-label-clear="<?php
                    echo esc_attr__(
                        'No booking warnings were found.',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-label-warning="<?php
                    echo esc_attr__(
                        'This booking can be saved, but please review the following warning.',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-label-warnings="<?php
                    echo esc_attr__(
                        'This booking can be saved, but please review the following warnings.',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-label-blocked="<?php
                    echo esc_attr__(
                        'This booking cannot currently be saved.',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-label-failed="<?php
                    echo esc_attr__(
                        'Booking checks could not be completed.',
                        'tutorhelper-bookings'
                    );
                ?>"

                data-condition-heading-clear="<?php
                    echo esc_attr__(
                        'Booking checks complete',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-heading-warning="<?php
                    echo esc_attr__(
                        'Booking warnings',
                        'tutorhelper-bookings'
                    );
                ?>"
                data-condition-heading-blocked="<?php
                    echo esc_attr__(
                        'Booking cannot be saved',
                        'tutorhelper-bookings'
                    );
                ?>"
            >
				<input
					type="hidden"
					name="action"
					value="<?php
						echo esc_attr(
							$form_action
						);
					?>"
				/>

				<input
                    type="hidden"
                    name="timezone"
                    value="<?php
                        echo esc_attr(
                            $form_state['timezone']
                        );
                    ?>"
                    data-booking-condition-timezone
                />

                <?php if ( $edit_mode ) : ?>
                    <input
                        type="hidden"
                        name="<?php
                            echo esc_attr(
                                self::BOOKING_ARGUMENT
                            );
                        ?>"
                        value="<?php
                            echo esc_attr(
                                $form_state[
                                    'booking_id'
                                ]
                            );
                        ?>"
                    />
                <?php endif; ?>

                <?php if ( $edit_mode ) : ?>
                    <?php
                    $return_view =
                        self::get_return_view();

                    $return_date =
                        self::get_return_date();
                    ?>

                    <?php if ( '' !== $return_view ) : ?>
                        <input
                            type="hidden"
                            name="<?php
                                echo esc_attr(
                                    self::RETURN_VIEW_ARGUMENT
                                );
                            ?>"
                            value="<?php
                                echo esc_attr(
                                    $return_view
                                );
                            ?>"
                        />
                    <?php endif; ?>

                    <?php if ( '' !== $return_date ) : ?>
                        <input
                            type="hidden"
                            name="<?php
                                echo esc_attr(
                                    self::RETURN_DATE_ARGUMENT
                                );
                            ?>"
                            value="<?php
                                echo esc_attr(
                                    $return_date
                                );
                            ?>"
                        />
                    <?php endif; ?>
                <?php endif; ?>

				<?php
				wp_nonce_field(
                    $form_action,
                    $nonce_field
                );
				?>

                <section
                    class="tutorhelper-tutor-booking-section"
                    aria-labelledby="tutorhelper-booking-student-heading"
                >
                    <header
                        class="tutorhelper-tutor-booking-section__header"
                    >
                        <span
                            class="tutorhelper-tutor-booking-section__number"
                            aria-hidden="true"
                        >
                            1
                        </span>

                        <div>
                            <h3
                                id="tutorhelper-booking-student-heading"
                            >
                                <?php
                                echo esc_html__(
                                    'Select student',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </h3>

                            <p>
                                <?php
                                echo esc_html__(
                                    'Search for the student receiving this lesson.',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </p>
                        </div>
                    </header>

                    <div
                        class="tutorhelper-tutor-booking-section__body"
                    >

                <?php if ( $edit_mode ) : ?>
                <div
                    class="tutorhelper-tutor-booking__field is-wide"
                >
                    <span
                        class="tutorhelper-tutor-booking__readonly-label"
                    >
                        <?php
                        echo esc_html__(
                            'Student',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </span>

                    <div
                        class="tutorhelper-booking-student-search__selected is-readonly"
                    >
                        <div>
                            <strong>
                                <?php
                                echo esc_html(
                                    $form_state[
                                        'student_name'
                                    ]
                                );
                                ?>
                            </strong>

                            <?php if (
                                '' !== $form_state[
                                    'student_email'
                                ]
                            ) : ?>
                                <span>
                                    <?php
                                    echo esc_html(
                                        $form_state[
                                            'student_email'
                                        ]
                                    );
                                    ?>
                                </span>
                            <?php endif; ?>

                            <?php if (
                                '' !== $form_state[
                                    'student_username'
                                ]
                            ) : ?>
                                <small>
                                    <?php
                                    echo esc_html(
                                        $form_state[
                                            'student_username'
                                        ]
                                    );
                                    ?>
                                </small>
                            <?php endif; ?>
                        </div>

                        <span
                            class="tutorhelper-tutor-booking__locked"
                        >
                            <span
                                class="dashicons dashicons-lock"
                                aria-hidden="true"
                            ></span>

                            <?php
                            echo esc_html__(
                                'Student cannot be changed',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </span>
                    </div>
                </div>
            <?php else : ?>
                <div
                    class="tutorhelper-tutor-booking__field is-wide"
                >
                    <label for="tutorhelper-booking-student-search">
                        <?php
                        echo esc_html__(
                            'Student',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </label>

                    <div
                        class="tutorhelper-booking-student-search"
                        data-student-search
                    >
                        <input
                            type="hidden"
                            name="student_user_id"
                            value=""
                            data-student-value
                        />

                        <div
                            class="tutorhelper-booking-student-search__input-wrap"
                        >
                            <input
                                type="search"
                                id="tutorhelper-booking-student-search"
                                class="tutorhelper-booking-student-search__input"
                                placeholder="<?php
                                    echo esc_attr__(
                                        'Search by student name, username or email',
                                        'tutorhelper-bookings'
                                    );
                                ?>"
                                autocomplete="off"
                                aria-autocomplete="list"
                                aria-controls="tutorhelper-booking-student-results"
                                aria-expanded="false"
                                data-student-search-input
                            />

                            <span
                                class="spinner tutorhelper-booking-student-search__spinner"
                                aria-hidden="true"
                                data-student-spinner
                            ></span>
                        </div>

                        <div
                            id="tutorhelper-booking-student-results"
                            class="tutorhelper-booking-student-search__results"
                            role="listbox"
                            hidden
                            data-student-results
                        ></div>

                        <p
                            class="tutorhelper-booking-student-search__status"
                            role="status"
                            aria-live="polite"
                            data-student-status
                        ></p>

                        <div
                            class="tutorhelper-booking-student-search__selection"
                            data-student-selection
                        >
                            <p
                                class="tutorhelper-booking-student-search__empty"
                            >
                                <?php
                                echo esc_html__(
                                    'No student selected.',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </p>
                        </div>
                    </div>
                </div>
            <?php endif; ?>
				

                </div>
            </section>

            <section
                class="tutorhelper-tutor-booking-section"
                aria-labelledby="tutorhelper-booking-details-heading"
            >
                <header
                    class="tutorhelper-tutor-booking-section__header"
                >
                    <span
                        class="tutorhelper-tutor-booking-section__number"
                        aria-hidden="true"
                    >
                        2
                    </span>

                    <div>
                        <h3
                            id="tutorhelper-booking-details-heading"
                        >
                            <?php
                            echo esc_html__(
                                'Lesson details',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </h3>

                        <p>
                            <?php
                            echo esc_html__(
                                'Choose the Booking Type, date, time, location and booking status.',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </p>
                    </div>
                </header>

                <div
                    class="tutorhelper-tutor-booking-section__body"
                >
                    <div
                        class="tutorhelper-tutor-booking__grid"
                    >


					<div class="tutorhelper-tutor-booking__field">
						<label for="tutorhelper-booking-type">
							<?php
							echo esc_html__(
								'Booking Type',
								'tutorhelper-bookings'
							);
							?>
						</label>

						<select
                            id="tutorhelper-booking-type"
                            name="booking_type_id"
                            required
                            data-booking-condition-field
                        >
							<option value="">
								<?php
								echo esc_html__(
									'Select a Booking Type',
									'tutorhelper-bookings'
								);
								?>
							</option>

							<?php foreach ( $booking_types as $booking_type ) : ?>
								<option
                                    value="<?php
                                        echo esc_attr(
                                            $booking_type->id
                                        );
                                    ?>"
                                    <?php
                                    selected(
                                        $form_state['booking_type_id'],
                                        absint(
                                            $booking_type->id
                                        )
                                    );
                                    ?>
                                    data-duration="<?php
                                        echo esc_attr(
                                            absint(
                                                $booking_type
                                                    ->duration_minutes
                                            )
                                        );
                                    ?>"
                                    data-price="<?php
                                        echo esc_attr(
                                            absint(
                                                $booking_type
                                                    ->price_minor_units
                                            )
                                        );
                                    ?>"
                                    data-location="<?php
                                        echo esc_attr(
                                            sanitize_key(
                                                $booking_type
                                                    ->location_type
                                            )
                                        );
                                    ?>"
                                    data-location-details="<?php
                                        echo esc_attr(
                                            sanitize_textarea_field(
                                                $booking_type
                                                    ->location_details
                                            )
                                        );
                                    ?>"
                                    data-colour="<?php
                                        echo esc_attr(
                                            sanitize_hex_color(
                                                $booking_type->colour
                                            )
                                                ? sanitize_hex_color(
                                                    $booking_type->colour
                                                )
                                                : '#328BB8'
                                        );
                                    ?>"
                                >
									<?php
									echo esc_html(
										$booking_type->title
									);
									?>
								</option>
							<?php endforeach; ?>
						</select>
					</div>

					<div class="tutorhelper-tutor-booking__field">
						<label for="tutorhelper-booking-date">
							<?php
							echo esc_html__(
								'Date',
								'tutorhelper-bookings'
							);
							?>
						</label>

						<input
                            type="date"
                            id="tutorhelper-booking-date"
                            name="booking_date"
                            value="<?php
                                echo esc_attr(
                                    $form_state[
                                        'booking_date'
                                    ]
                                );
                            ?>"
                            required
                            data-booking-condition-field
                        />
					</div>

					<div class="tutorhelper-tutor-booking__field">
						<label for="tutorhelper-booking-start">
							<?php
							echo esc_html__(
								'Start time',
								'tutorhelper-bookings'
							);
							?>
						</label>

						<input
                            type="time"
                            id="tutorhelper-booking-start"
                            name="start_time"
                            step="60"
                            value="<?php
                                echo esc_attr(
                                    $form_state[
                                        'start_time'
                                    ]
                                );
                            ?>"
                            required
                            data-booking-condition-field
                        />
					</div>

					<div class="tutorhelper-tutor-booking__field">
						<label for="tutorhelper-booking-end">
							<?php
							echo esc_html__(
								'End time',
								'tutorhelper-bookings'
							);
							?>
						</label>

						<input
                            type="time"
                            id="tutorhelper-booking-end"
                            name="end_time"
                            step="60"
                            value="<?php
                                echo esc_attr(
                                    $form_state[
                                        'end_time'
                                    ]
                                );
                            ?>"
                            required
                            data-booking-condition-field
                        />
					</div>

                    <div
                        class="tutorhelper-tutor-booking__field is-half"
                    >
                        <label for="tutorhelper-booking-location">
                            <?php
                            echo esc_html__(
                                'Location',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </label>

                        <select
                            id="tutorhelper-booking-location"
                            name="location_type"
                            required
                            data-booking-condition-field
                        >
                            <option value="online">
                                <?php
                                echo esc_html__(
                                    'Online',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </option>

                            <option value="phone">
                                <?php
                                echo esc_html__(
                                    'Phone',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </option>

                            <option value="in_person">
                                <?php
                                echo esc_html__(
                                    'In person',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </option>

                            <option value="other">
                                <?php
                                echo esc_html__(
                                    'Other',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </option>
                        </select>

                        <p class="description">
                            <?php
                            echo esc_html__(
                                'The Booking Type location is suggested, but tutors may choose another option.',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </p>
                    </div>

                    

					<div class="tutorhelper-tutor-booking__field">
						<label for="tutorhelper-booking-status">
							<?php
							echo esc_html__(
								'Booking status',
								'tutorhelper-bookings'
							);
							?>
						</label>

						<select
							id="tutorhelper-booking-status"
							name="status"
							required
						>
							<option
								value="<?php
									echo esc_attr(
										TutorHelper_Booking_Records::
											STATUS_CONFIRMED
									);
								?>"
                                <?php
                                selected(
                                    $form_state['status'],
                                    TutorHelper_Booking_Records::
                                        STATUS_CONFIRMED
                                );
                                ?>
							>
								<?php
								echo esc_html__(
									'Confirmed',
									'tutorhelper-bookings'
								);
								?>
							</option>

							<option
								value="<?php
									echo esc_attr(
										TutorHelper_Booking_Records::
											STATUS_UNCONFIRMED
									);
								?>"
                                <?php
                                selected(
                                    $form_state['status'],
                                    TutorHelper_Booking_Records::
                                        STATUS_UNCONFIRMED
                                );
                                ?>
							>
								<?php
								echo esc_html__(
									'Unconfirmed',
									'tutorhelper-bookings'
								);
								?>
							</option>

                            <?php if ( $edit_mode ) : ?>
                            <option
                                value="<?php
                                    echo esc_attr(
                                        TutorHelper_Booking_Records::
                                            STATUS_CANCELLED
                                    );
                                ?>"
                                <?php
                                selected(
                                    $form_state['status'],
                                    TutorHelper_Booking_Records::
                                        STATUS_CANCELLED
                                );
                                ?>
                            >
                                <?php
                                echo esc_html__(
                                    'Cancelled',
                                    'tutorhelper-bookings'
                                );
                                ?>
                            </option>
                        <?php endif; ?>
						</select>

						<p class="description">
							<?php
							echo esc_html__(
								'This manually overrides the usual payment-derived confirmation decision.',
								'tutorhelper-bookings'
							);
							?>
						</p>
					</div>

                    <?php if ( $edit_mode ) : ?>
                    <div
                        class="tutorhelper-tutor-booking__field is-wide"
                        data-booking-cancellation-reason
                        hidden
                    >
                        <label
                            for="tutorhelper-booking-cancellation-reason"
                        >
                            <?php
                            echo esc_html__(
                                'Cancellation reason',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </label>

                        <textarea
                            id="tutorhelper-booking-cancellation-reason"
                            name="cancellation_reason"
                            rows="3"
                            maxlength="500"
                            disabled
                            data-booking-cancellation-reason-input
                        ></textarea>

                        <p class="description">
                            <?php
                            echo esc_html__(
                                'Briefly explain why this lesson is being cancelled. The student will receive this reason in their cancellation email.',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </p>
                    </div>
                <?php endif; ?>

                </div>
	        </div>
        </section>

        <?php if ( ! $edit_mode ) : ?>
            <?php
            /**
             * Render additional fields for the tutor
             * Add Booking form.
             *
             * Extensions may add fields used when creating
             * a booking. This hook is not rendered while
             * editing an existing individual booking.
             *
             * @param array $form_state Core form values.
             */
            do_action(
                'tutorhelper_tutor_booking_render_create_fields',
                $form_state
            );
            ?>
        <?php endif; ?>


        <section
            class="tutorhelper-booking-conditions"
            data-booking-condition-region
            aria-labelledby="tutorhelper-booking-conditions-heading"
            aria-live="polite"
            aria-atomic="true"
            hidden
        >
            <header
                class="tutorhelper-booking-conditions__header"
            >
                <span
                    class="dashicons dashicons-info-outline"
                    aria-hidden="true"
                    data-booking-condition-icon
                ></span>

                <div>
                    <h3
                        id="tutorhelper-booking-conditions-heading"
                        data-booking-condition-heading
                    >
                        <?php
                        echo esc_html__(
                            'Booking checks',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </h3>

                    <p
                        class="tutorhelper-booking-conditions__summary"
                        data-booking-condition-summary
                    ></p>
                </div>
            </header>

            <ul
                class="tutorhelper-booking-conditions__list"
                data-booking-condition-list
            ></ul>
        </section>


        <section
            class="tutorhelper-tutor-booking-section is-summary"
            aria-labelledby="tutorhelper-booking-summary-heading"
        >
            <header
                class="tutorhelper-tutor-booking-section__header"
            >
                <span
                    class="tutorhelper-tutor-booking-section__number"
                    aria-hidden="true"
                >
                    3
                </span>

                <div>
                    <h3
                        id="tutorhelper-booking-summary-heading"
                    >
                        <?php
                        echo esc_html__(
                            'Booking summary',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </h3>

                    <p>
                        <?php
                        echo esc_html__(
                            'Review the calculated duration and price before saving.',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </p>
                </div>
            </header>

            <div
                class="tutorhelper-tutor-booking-section__body"
            >
                <div
                        class="tutorhelper-tutor-booking__field is-wide"
                    >
                        <div
                            class="tutorhelper-tutor-booking-preview"
                            data-booking-preview
                        >
                            <div
                                class="tutorhelper-tutor-booking-preview__colour"
                                aria-hidden="true"
                                data-booking-colour
                            ></div>

                            <div
                                class="tutorhelper-tutor-booking-preview__content"
                            >
                                <strong>
                                    <?php
                                    echo esc_html__(
                                        'Booking summary',
                                        'tutorhelper-bookings'
                                    );
                                    ?>
                                </strong>

                                <div
                                    class="tutorhelper-tutor-booking-preview__values"
                                >
                                    <span>
                                        <?php
                                        echo esc_html__(
                                            'Duration:',
                                            'tutorhelper-bookings'
                                        );
                                        ?>

                                        <strong data-booking-duration>
                                            —
                                        </strong>
                                    </span>

                                    <span>
                                        <?php
                                        echo esc_html__(
                                            'Price:',
                                            'tutorhelper-bookings'
                                        );
                                        ?>

                                        <strong data-booking-price>
                                            —
                                        </strong>
                                    </span>
                                </div>

                                <p>
                                    <?php
                                    echo esc_html__(
                                        'The final duration and price are recalculated securely when the booking is saved.',
                                        'tutorhelper-bookings'
                                    );
                                    ?>
                                </p>
                            </div>
                        </div>
                    </div>

                    <?php if ( ! $edit_mode ) : ?>
                        <?php
                        /**
                         * Render additional Add Booking summary content.
                         *
                         * Extensions may augment the booking preview
                         * before the booking is submitted.
                         *
                         * @param array $form_state Core form values.
                         */
                        do_action(
                            'tutorhelper_tutor_booking_render_create_summary',
                            $form_state
                        );
                        ?>
                    <?php endif; ?>
            </div>
        </section>



        <section
            class="tutorhelper-tutor-booking-section"
            aria-labelledby="tutorhelper-booking-location-heading"
        >
            <header
                class="tutorhelper-tutor-booking-section__header"
            >
                <span
                    class="tutorhelper-tutor-booking-section__number"
                    aria-hidden="true"
                >
                    4
                </span>

                <div>
                    <h3
                        id="tutorhelper-booking-location-heading"
                    >
                        <?php
                        echo esc_html__(
                            'Location details',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </h3>

                    <p>
                        <?php
                        echo esc_html__(
                            'Add the meeting link, telephone details, address or other instructions.',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </p>
                </div>
            </header>

            <div
                class="tutorhelper-tutor-booking-section__body"
            >
                <div
                    class="tutorhelper-tutor-booking__field"
                >
                    <label
                        for="tutorhelper-booking-location-details"
                    >
                        <?php
                        echo esc_html__(
                            'Details for this booking',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </label>

                    <textarea
                        id="tutorhelper-booking-location-details"
                        name="location_details"
                        rows="4"
                    ><?php
                        echo esc_textarea(
                            $form_state[
                                'location_details'
                            ]
                        );
                    ?></textarea>
                </div>
            </div>
        </section>

        <p
            class="tutorhelper-booking-conditions__status"
            role="status"
            aria-live="polite"
            data-booking-condition-status
        ></p>

        


        <section
            class="tutorhelper-tutor-booking-section"
            aria-labelledby="tutorhelper-booking-notes-heading"
        >
            <header
                class="tutorhelper-tutor-booking-section__header"
            >
                <span
                    class="tutorhelper-tutor-booking-section__number"
                    aria-hidden="true"
                >
                    5
                </span>

                <div>
                    <h3
                        id="tutorhelper-booking-notes-heading"
                    >
                        <?php
                        echo esc_html__(
                            'Internal notes',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </h3>

                    <p>
                        <?php
                        echo esc_html__(
                            'Record private administrative information about this booking.',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </p>
                </div>
            </header>

            <div
                class="tutorhelper-tutor-booking-section__body"
            >
                <div
                    class="tutorhelper-tutor-booking__field"
                >
                    <label
                        for="tutorhelper-booking-notes"
                    >
                        <?php
                        echo esc_html__(
                            'Notes',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </label>

                    <textarea
                        id="tutorhelper-booking-notes"
                        name="notes"
                        rows="5"
                    ><?php
                        echo esc_textarea(
                            $form_state['notes']
                        );
                    ?></textarea>

                    <p class="description">
                        <?php
                        echo esc_html__(
                            'These notes are stored on the booking record and are not part of the public booking details.',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </p>
                </div>
            </div>
        </section>

		<footer
            class="tutorhelper-tutor-booking__actions"
        >
            <div
                class="tutorhelper-tutor-booking__actions-copy"
            >
                <strong>
                    <?php
                    echo esc_html(
                        $edit_mode
                            ? __(
                                'Ready to save these changes?',
                                'tutorhelper-bookings'
                            )
                            : __(
                                'Ready to create this booking?',
                                'tutorhelper-bookings'
                            )
                    );
                    ?>
                </strong>

                <span>
                    <?php
                    echo esc_html(
                        $edit_mode
                            ? __(
                                'The booking ownership, date, duration, price and conflicts will be checked again before it is updated.',
                                'tutorhelper-bookings'
                            )
                            : __(
                                'The date, duration, price and student will be checked again before the booking is saved.',
                                'tutorhelper-bookings'
                            )
                    );
                    ?>
                </span>
            </div>

            <div
                class="tutorhelper-tutor-booking__action-buttons"
            >

            <?php if ( $edit_mode ) : ?>
                <a
                    class="button"
                    href="<?php
                        echo esc_url(
                            self::get_calendar_url(
                                $booking,
                                self::get_return_view(),
                                self::get_return_date()
                            )
                        );
                    ?>"
                >
                    <span
                        class="dashicons dashicons-arrow-left-alt2"
                        aria-hidden="true"
                    ></span>

                    <?php
                    echo esc_html__(
                        'Back to calendar',
                        'tutorhelper-bookings'
                    );
                    ?>
                </a>
            <?php endif; ?>

           <button
                type="submit"
                class="button button-primary"
                data-booking-condition-submit
                <?php
                disabled(
                    empty( $booking_types )
                );
                ?>
            >
                <?php
                echo esc_html(
                    $edit_mode
                        ? __(
                            'Update booking',
                            'tutorhelper-bookings'
                        )
                        : __(
                            'Create booking',
                            'tutorhelper-bookings'
                        )
                );
                ?>
            </button>

            </div>
        </footer>



			</form>
		</section>
		<?php
	}

    /**
     * Render a safe error when edit mode cannot be opened.
     *
     * @param WP_Error $error Edit-mode error.
     *
     * @return void
     */
    private static function render_edit_error(
        $error
    ) {
        $message = is_wp_error( $error )
            ? $error->get_error_message()
            : __(
                'The booking could not be opened.',
                'tutorhelper-bookings'
            );

        ?>
        <section class="tutorhelper-tutor-booking">
            <header
                class="tutorhelper-tutor-booking__header"
            >
                <h2>
                    <?php
                    echo esc_html__(
                        'Edit booking',
                        'tutorhelper-bookings'
                    );
                    ?>
                </h2>
            </header>

            <div
                class="tutorhelper-tutor-booking__error"
            >
                <div class="notice notice-error inline">
                    <p>
                        <?php
                        echo esc_html(
                            $message
                        );
                        ?>
                    </p>
                </div>

                <a
                    class="button"
                    href="<?php
                        echo esc_url(
                            self::get_calendar_url()
                        );
                    ?>"
                >
                    <?php
                    echo esc_html__(
                        'Back to calendar',
                        'tutorhelper-bookings'
                    );
                    ?>
                </a>
            </div>
        </section>
        <?php
    }

}
