<?php
/**
 * TutorHelper availability-calendar administration interface.
 *
 * @package TutorHelper_Bookings
 */

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





/**
 * Renders the twelve-month availability-planning calendar.
 */
final class TutorHelper_Availability_Calendar_Admin {

    /**
     * Planner range save action.
     *
     * @var string
     */
    const SAVE_ACTION =
        'tutorhelper_save_availability_range';

	/**
     * Planner range load action for edit.
     *
     * @var string
     */
	const LOAD_ITEM_ACTION =
	'tutorhelper_load_availability_calendar_item';

	/**
     * Planner range delete action.
     *
     * @var string
     */
	const DELETE_ACTION =
	'tutorhelper_delete_availability_range';

	/**
	 * Register WordPress hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_action(
			'tutorhelper_booking_hub_render_availability',
			array(
				__CLASS__,
				'render_workspace',
			)
		);

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

		add_action(
			'wp_ajax_'
				. self::LOAD_ITEM_ACTION,
			array(
				__CLASS__,
				'handle_load_item',
			)
		);

		add_action(
			'admin_post_'
				. self::DELETE_ACTION,
			array(
				__CLASS__,
				'handle_delete',
			)
		);

	}


    /**
	 * Verify a planner save request.
	 *
	 * @return void
	 */
	private static function verify_save_request() {
		if (
			! current_user_can(
				TutorHelper_Booking_Hub::CAPABILITY
			)
		) {
			wp_die(
				esc_html__(
					'You are not allowed to manage availability.',
					'tutorhelper-bookings'
				),
				403
			);
		}


	}


    /**
	 * Save a planner range.
	 *
	 * @return void
	 */
	public static function handle_save() {
		self::verify_save_request();

		check_admin_referer(
			self::SAVE_ACTION
		);

		$data = array(
			'range_mode' => isset(
				$_POST['range_mode']
			)
				? sanitize_key(
					wp_unslash(
						$_POST['range_mode']
					)
				)
				: 'create',

			'record_type' => isset(
				$_POST['record_type']
			)
				? sanitize_key(
					wp_unslash(
						$_POST['record_type']
					)
				)
				: '',

			'record_id' => isset(
				$_POST['record_id']
			)
				? absint(
					$_POST['record_id']
				)
				: 0,

			'range_type' => isset(
				$_POST['tutorhelper_range_type']
			)
				? sanitize_key(
					wp_unslash(
						$_POST['tutorhelper_range_type']
					)
				)
				: '',

			'title' => isset( $_POST['title'] )
				? sanitize_text_field(
					wp_unslash(
						$_POST['title']
					)
				)
				: '',

			'start_date' => isset(
				$_POST['start_date']
			)
				? sanitize_text_field(
					wp_unslash(
						$_POST['start_date']
					)
				)
				: '',

			'end_date' => isset(
				$_POST['end_date']
			)
				? sanitize_text_field(
					wp_unslash(
						$_POST['end_date']
					)
				)
				: '',

			'weekdays' => isset(
				$_POST['weekdays']
			)
			&& is_array(
				$_POST['weekdays']
			)
				? array_map(
					'sanitize_key',
					wp_unslash(
						$_POST['weekdays']
					)
				)
				: array(),

			'start_time' => isset(
				$_POST['start_time']
			)
				? sanitize_text_field(
					wp_unslash(
						$_POST['start_time']
					)
				)
				: '',

			'end_time' => isset(
				$_POST['end_time']
			)
				? sanitize_text_field(
					wp_unslash(
						$_POST['end_time']
					)
				)
				: '',

			'location_types' => isset(
				$_POST['location_types']
			)
			&& is_array(
				$_POST['location_types']
			)
				? array_map(
					'sanitize_key',
					wp_unslash(
						$_POST['location_types']
					)
				)
				: array(),

			'location_type' => isset(
				$_POST['location_type']
			)
				? sanitize_key(
					wp_unslash(
						$_POST['location_type']
					)
				)
				: '',

			'location_details' => isset(
				$_POST['location_details']
			)
				? sanitize_textarea_field(
					wp_unslash(
						$_POST['location_details']
					)
				)
				: '',

			'allowed_booking_type_ids' => isset(
				$_POST['allowed_booking_type_ids']
			)
			&& is_array(
				$_POST['allowed_booking_type_ids']
			)
				? array_map(
					'absint',
					wp_unslash(
						$_POST['allowed_booking_type_ids']
					)
				)
				: array(),

			'notes' => isset( $_POST['notes'] )
				? sanitize_textarea_field(
					wp_unslash(
						$_POST['notes']
					)
				)
				: '',
		);

        
        TutorHelper_Logger::info(
            'Availability planner submission data.',
            array(
                'range_type' => $data['range_type'],
				'title'      => $data['title'],
				'start_date' => $data['start_date'],
				'end_date'   => $data['end_date'],
				'weekdays'   => $data['weekdays'],
            )
        );


		$result =
			TutorHelper_Availability_Range_Save::save(
				$data,
				get_current_user_id()
			);

		if ( is_wp_error( $result ) ) {
			TutorHelper_Logger::warning(
				'Availability planner range was rejected.',
				array(
					'range_type' =>
						sanitize_key(
							$data['range_type']
						),
					'error_code' =>
						$result->get_error_code(),
				)
			);

			self::redirect_after_save(
				'error',
				$result->get_error_code()
			);
		}

		TutorHelper_Logger::success(
			'Availability planner range saved.',
			array(
				'record_type' =>
					$result['record_type'],
				'record_id' =>
					$result['record_id'],
				'range_type' =>
					$result['range_type'],
			)
		);

		self::redirect_after_save(
			! empty(
				$result['updated']
			)
				? 'updated'
				: 'saved'
		);
	}


    /**
	 * Redirect back to the Availability planner.
	 *
	 * @param string $notice     Notice value.
	 * @param string $error_code Optional error code.
	 *
	 * @return void
	 */
	private static function redirect_after_save(
		$notice,
		$error_code = ''
	) {
		$args = array(
			'page' =>
				TutorHelper_Booking_Hub::PAGE_SLUG,

			'tab' =>
				'availability',

			'range_notice' =>
				sanitize_key( $notice ),
		);

		if ( ! empty( $error_code ) ) {
			$args['range_error'] =
				sanitize_key( $error_code );
		}

		wp_safe_redirect(
			add_query_arg(
				$args,
				admin_url( 'admin.php' )
			)
		);

		exit;
	}



    	/**
	 * Render the availability-planning workspace.
	 *
	 * @return void
	 */
	public static function render_workspace() {
		if (
			! current_user_can(
				TutorHelper_Booking_Hub::CAPABILITY
			)
		) {
			return;
		}

		$tutor_user_id = get_current_user_id();

		$calendar =
			TutorHelper_Availability_Calendar::
				get_upcoming_twelve_months(
					$tutor_user_id
				);

		?>

        <?php self::render_save_notice(); ?>


		<section class="tutorhelper-availability-planner">
			<header class="tutorhelper-booking-hub__toolbar tutorhelper-availability-planner__toolbar">
                <div class="tutorhelper-availability-planner__heading">
                    <h2 class="tutorhelper-booking-hub__period-title">
                        <?php
                        echo esc_html__(
                            'Availability planner',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </h2>

                    <p>
                        <?php
                        echo esc_html__(
                            'Review your working days, term dates, leave and public holidays across the upcoming twelve months.',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </p>
                </div>

                <div class="tutorhelper-availability-planner__actions">
                    <button
                        type="button"
                        id="tutorhelper-start-range-selection"
                        class="button button-primary"
                    >
                        <?php
                        echo esc_html__(
                            'Add date range',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </button>
                </div>
            </header>

            <?php self::render_range_selection_panel(); ?>
			<?php self::render_calendar_item_chooser(); ?>
			<?php self::render_legend(); ?>

			<?php
			if ( is_wp_error( $calendar ) ) {
				self::render_error(
					$calendar
				);
			} else {
				self::render_calendar(
					$calendar
				);
			}
			?>
		</section>
		<?php
	}


    /**
	 * Render a planner save result.
	 *
	 * @return void
	 */
	private static function render_save_notice() {
		$notice = isset( $_GET['range_notice'] ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only request state used for navigation or feedback; value is sanitized and no state change occurs.
			? sanitize_key(
				wp_unslash(
					$_GET['range_notice'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only request state used for navigation or feedback; value is sanitized and no state change occurs.
				)
			)
			: '';

		if ( 'updated' === $notice ) {
			?>
			<div
				class="notice notice-success is-dismissible"
			>
				<p>
					<?php
					echo esc_html__(
						'The date range was updated.',
						'tutorhelper-bookings'
					);
					?>
				</p>
			</div>
			<?php

			return;
		}

		if ( 'deleted' === $notice ) {
			?>
			<div
				class="notice notice-success is-dismissible"
			>
				<p>
					<?php
					echo esc_html__(
						'The date range was deleted.',
						'tutorhelper-bookings'
					);
					?>
				</p>
			</div>
			<?php

			return;
		}

		if ( 'saved' === $notice ) {
			?>
			<div class="notice notice-success is-dismissible">
				<p>
					<?php
					echo esc_html__(
						'The date range was saved.',
						'tutorhelper-bookings'
					);
					?>
				</p>
			</div>
			<?php

			return;
		}

		if ( 'error' !== $notice ) {
			return;
		}

		$error_code = isset(
			$_GET['range_error'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only request state used for navigation or feedback; value is sanitized and no state change occurs.
		)
			? sanitize_key(
				wp_unslash(
					$_GET['range_error'] // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only request state used for navigation or feedback; value is sanitized and no state change occurs.
				)
			)
			: '';

		?>
		<div class="notice notice-error is-dismissible">
			<p>
				<?php
				printf(
					/* translators: %s: technical error code. */
					esc_html__(
						'The date range could not be saved. Error: %s',
						'tutorhelper-bookings'
					),
					esc_html( $error_code )
				);
				?>
			</p>
		</div>
		<?php
	}



    	/**
	 * Render the calendar classification legend.
	 *
	 * @return void
	 */
	private static function render_legend() {
		$display_types =
			TutorHelper_Availability_Calendar::
				get_display_types();

		?>
		<div
			class="tutorhelper-availability-legend"
			aria-label="<?php
				echo esc_attr__(
					'Availability calendar legend',
					'tutorhelper-bookings'
				);
			?>"
		>
			<?php
			foreach (
				$display_types as $type => $definition
			) :
				?>
				<div class="tutorhelper-availability-legend__item">
					<span
						class="<?php
							echo esc_attr(
								self::get_marker_classes(
									array( $type )
								)
							);
						?>"
						aria-hidden="true"
					></span>

					<span>
						<?php
						echo esc_html(
							$definition['label']
						);
						?>
					</span>
				</div>
			<?php endforeach; ?>
		</div>
		<?php
	}


    /**
     * Render the date-range selection controls.
     *
     * This panel is controlled by JavaScript. No records are saved
     * during the range-selection stage.
     *
     * @return void
     */
    private static function render_range_selection_panel() {
        ?>
        <form
            id="tutorhelper-range-selection-panel"
            class="tutorhelper-range-selection"
            method="post"
            action="<?php
                echo esc_url(
                    admin_url( 'admin-post.php' )
                );
            ?>"
            hidden
            aria-labelledby="tutorhelper-range-selection-title"
        >
            <input
                type="hidden"
                name="action"
                value="<?php
                    echo esc_attr(
                        self::SAVE_ACTION
                    );
                ?>"
            />

            <?php
            wp_nonce_field(
                self::SAVE_ACTION
            );
			
			wp_nonce_field(
				self::DELETE_ACTION,
				'tutorhelper_delete_range_nonce'
			);
            ?>
			<input
				type="hidden"
				id="tutorhelper-range-mode"
				name="range_mode"
				value="create"
			/>

			<input
				type="hidden"
				id="tutorhelper-range-record-type"
				name="record_type"
				value=""
			/>

			<input
				type="hidden"
				id="tutorhelper-range-record-id"
				name="record_id"
				value="0"
			/>

            <div class="tutorhelper-range-selection__heading">
                <div>
                    <h3 id="tutorhelper-range-selection-title">
                        <?php
                        echo esc_html__(
                            'Add a date range',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </h3>

                    <p>
                        <?php
                        echo esc_html__(
                            'Choose the type of range, then select its first and final date on the calendar.',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </p>
                </div>

                <button
                    type="button"
                    id="tutorhelper-close-range-selection"
                    class="button-link"
                >
                    <?php
                    echo esc_html__(
                        'Close',
                        'tutorhelper-bookings'
                    );
                    ?>
                </button>
            </div>

            <fieldset class="tutorhelper-range-selection__types">
                <legend>
                    <?php
                    echo esc_html__(
                        'What type of range are you adding?',
                        'tutorhelper-bookings'
                    );
                    ?>
                </legend>

                <?php self::render_range_type_option(
                    'general_availability',
                    __(
                        'Working day',
                        'tutorhelper-bookings'
                    ),
                    __(
                        'Days & times when students can book lessons.',
                        'tutorhelper-bookings'
                    ),
                    true
                ); ?>

                <?php self::render_range_type_option(
                    'outside_term_time',
                    __(
                        'Outside term time',
                        'tutorhelper-bookings'
                    ),
                    __(
                        'Dates skipped by term-time-only recurring lessons.',
                        'tutorhelper-bookings'
                    )
                ); ?>

                <?php self::render_range_type_option(
                    'tutor_leave',
                    __(
                        'Tutor on leave',
                        'tutorhelper-bookings'
                    ),
                    __(
                        'Dates when the tutor is unavailable.',
                        'tutorhelper-bookings'
                    )
                ); ?>

                <?php self::render_range_type_option(
                    'public_holiday',
                    __(
                        'Public holiday',
                        'tutorhelper-bookings'
                    ),
                    __(
                        'Public or bank holiday dates.',
                        'tutorhelper-bookings'
                    )
                ); ?>
            </fieldset>

            <div
                class="tutorhelper-range-selection__summary"
                aria-live="polite"
            >
                <div>
                    <span class="tutorhelper-range-selection__label">
                        <?php
                        echo esc_html__(
                            'Start date',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </span>

                    <strong id="tutorhelper-selected-start-date">
                        <?php
                        echo esc_html__(
                            'Not selected',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </strong>
                </div>

                <div>
                    <span class="tutorhelper-range-selection__label">
                        <?php
                        echo esc_html__(
                            'End date',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </span>

                    <strong id="tutorhelper-selected-end-date">
                        <?php
                        echo esc_html__(
                            'Not selected',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </strong>
                </div>

                <div>
                    <span class="tutorhelper-range-selection__label">
                        <?php
                        echo esc_html__(
                            'Dates selected',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </span>

                    <strong id="tutorhelper-selected-day-count">
                        0
                    </strong>
                </div>
            </div>

			<div
				id="tutorhelper-range-edit-dates"
				class="tutorhelper-range-edit-dates"
				hidden
			>
				<p>
					<label for="tutorhelper-range-edit-start">
						<strong>
							<?php
							echo esc_html__(
								'Start date',
								'tutorhelper-bookings'
							);
							?>
						</strong>
					</label>

					<input
						type="date"
						id="tutorhelper-range-edit-start"
						value=""
					/>
				</p>

				<p>
					<label for="tutorhelper-range-edit-end">
						<strong>
							<?php
							echo esc_html__(
								'End date',
								'tutorhelper-bookings'
							);
							?>
						</strong>
					</label>

					<input
						type="date"
						id="tutorhelper-range-edit-end"
						value=""
					/>
				</p>
			</div>


            <?php self::render_working_day_fields(); ?>

            <input
                type="hidden"
                id="tutorhelper-range-start"
                name="start_date"
                value=""
            />

            <input
                type="hidden"
                id="tutorhelper-range-end"
                name="end_date"
                value=""
            />

            <p class="tutorhelper-range-selection__title">
			<label for="tutorhelper-range-title">
				<strong>
					<?php
					echo esc_html__(
						'Title',
						'tutorhelper-bookings'
					);
					?>
				</strong>
			</label>

			<input
				type="text"
				id="tutorhelper-range-title"
				name="title"
				class="regular-text"
				required
			/>

			<span class="description">
				<?php
				echo esc_html__(
					'For example: Autumn working hours, Christmas break or August leave.',
					'tutorhelper-bookings'
				);
				?>
			</span>
		</p>

		<div
			id="tutorhelper-working-day-calendar-link"
			class="tutorhelper-working-day-calendar-link"
			hidden
		>
			<p>
				<strong>
					<?php
					esc_html_e(
						'Editing a recurring Working Day',
						'tutorhelper-bookings'
					);
					?>
				</strong>
			</p>

			<p class="description">
				<?php
				esc_html_e(
					'Changes saved in this panel apply to the complete recurring Working Day range.',
					'tutorhelper-bookings'
				);
				?>
			</p>

			<p class="description">
				<?php
				esc_html_e(
					'To change only the selected date — for example its times, locations or available Booking Types — edit that occurrence in the Calendar instead.',
					'tutorhelper-bookings'
				);
				?>
			</p>

			<a
				id="tutorhelper-working-day-calendar-edit"
				href="#"
				class="
					button
					button-secondary
				"
			>
				<?php
				esc_html_e(
					'Edit this date only',
					'tutorhelper-bookings'
				);
				?>
			</a>
		</div>

		<button
			type="submit"
			id="tutorhelper-delete-range"
			class="button tutorhelper-range-delete"
			formaction="<?php
				echo esc_url(
					admin_url(
						'admin-post.php'
					)
				);
			?>"
			formmethod="post"
			name="action"
			value="<?php
				echo esc_attr(
					self::DELETE_ACTION
				);
			?>"
			hidden
		>
			<?php
			echo esc_html__(
				'Delete range',
				'tutorhelper-bookings'
			);
			?>
		</button>


		<div class="tutorhelper-range-selection__buttons">
			<button
				type="button"
				id="tutorhelper-clear-range-selection"
				class="button"
				disabled
			>
				<?php
				echo esc_html__(
					'Clear selection',
					'tutorhelper-bookings'
				);
				?>
			</button>

			<button
				type="submit"
				id="tutorhelper-save-range-selection"
				class="button button-primary"
				disabled
			>
				<?php
				echo esc_html__(
					'Save date range',
					'tutorhelper-bookings'
				);
				?>
			</button>
		</div>
            </div>
        </form>
        <?php
    }


    /**
     * Render the additional fields required for a Working day.
     *
     * These use the same field names as the existing Add Availability
     * form so the same service and save handler can process them.
     *
     * @return void
     */
    private static function render_working_day_fields() {
        $booking_types =
            TutorHelper_Booking_Types::get_active();

        ?>
        <div
            id="tutorhelper-working-day-fields"
            class="tutorhelper-working-day-fields"
        >
            <h4>
                <?php
                echo esc_html__(
                    'Working day details',
                    'tutorhelper-bookings'
                );
                ?>
            </h4>

            <p class="description">
                <?php
                echo esc_html__(
                    'Choose which weekdays and times within the selected date range are available for bookings.',
                    'tutorhelper-bookings'
                );
                ?>
            </p>

            <?php self::render_working_day_weekdays(); ?>

            <div class="tutorhelper-working-day-fields__times">
                <p>
                    <label for="tutorhelper-range-start-time">
                        <strong>
                            <?php
                            echo esc_html__(
                                'Start time',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </strong>
                    </label>

                    <input
                        type="time"
                        id="tutorhelper-range-start-time"
                        name="start_time"
                        value="09:00"
                    />
                </p>

                <p>
                    <label for="tutorhelper-range-end-time">
                        <strong>
                            <?php
                            echo esc_html__(
                                'End time',
                                'tutorhelper-bookings'
                            );
                            ?>
                        </strong>
                    </label>

                    <input
                        type="time"
                        id="tutorhelper-range-end-time"
                        name="end_time"
                        value="17:00"
                    />
                </p>
            </div>

            <?php self::render_working_day_locations(); ?>

            <p>
                <label for="tutorhelper-range-location-details">
                    <strong>
                        <?php
                        echo esc_html__(
                            'Location details',
                            'tutorhelper-bookings'
                        );
                        ?>
                    </strong>
                </label>

                <textarea
                    id="tutorhelper-range-location-details"
                    name="location_details"
                    class="widefat"
                    rows="3"
                ></textarea>
            </p>

            <?php
            self::render_working_day_booking_types(
                $booking_types
            );
            ?>
        </div>
        <?php
    }

    /**
     * Render weekdays for a Working day range.
     *
     * @return void
     */
    private static function render_working_day_weekdays() {
        $weekdays = array(
            'mon' => __(
                'Monday',
                'tutorhelper-bookings'
            ),
            'tue' => __(
                'Tuesday',
                'tutorhelper-bookings'
            ),
            'wed' => __(
                'Wednesday',
                'tutorhelper-bookings'
            ),
            'thu' => __(
                'Thursday',
                'tutorhelper-bookings'
            ),
            'fri' => __(
                'Friday',
                'tutorhelper-bookings'
            ),
            'sat' => __(
                'Saturday',
                'tutorhelper-bookings'
            ),
            'sun' => __(
                'Sunday',
                'tutorhelper-bookings'
            ),
        );

        ?>
        <fieldset class="tutorhelper-working-day-fields__weekdays">
            <legend>
                <strong>
                    <?php
                    echo esc_html__(
                        'Weekdays to include',
                        'tutorhelper-bookings'
                    );
                    ?>
                </strong>
            </legend>

            <div class="tutorhelper-workday-options">
                <?php foreach ( $weekdays as $key => $label ) : ?>
                    <label>
                        <input
                            type="checkbox"
                            name="weekdays[]"
                            value="<?php echo esc_attr( $key ); ?>"
                        />

                        <span>
                            <?php echo esc_html( $label ); ?>
                        </span>
                    </label>
                <?php endforeach; ?>
            </div>
        </fieldset>
        <?php
    }


    /**
     * Render location choices for a Working day.
     *
     * @return void
     */
    private static function render_working_day_locations() {
        $locations = array(
            'online' => __(
                'Online',
                'tutorhelper-bookings'
            ),
            'phone' => __(
                'Phone',
                'tutorhelper-bookings'
            ),
            'in_person' => __(
                'In person',
                'tutorhelper-bookings'
            ),
            'other' => __(
                'Other',
                'tutorhelper-bookings'
            ),
        );

        ?>
        <fieldset class="tutorhelper-working-day-fields__locations">
            <legend>
                <strong>
                    <?php
                    echo esc_html__(
                        'Available locations',
                        'tutorhelper-bookings'
                    );
                    ?>
                </strong>
            </legend>

            <div class="tutorhelper-location-options">
                <?php foreach ( $locations as $key => $label ) : ?>
                    <label>
                        <input
                            type="checkbox"
                            name="location_types[]"
                            value="<?php echo esc_attr( $key ); ?>"
                            <?php checked( 'online', $key ); ?>
                        />

                        <span>
                            <?php echo esc_html( $label ); ?>
                        </span>
                    </label>
                <?php endforeach; ?>
            </div>
        </fieldset>

        <p>
            <label for="tutorhelper-range-primary-location">
                <strong>
                    <?php
                    echo esc_html__(
                        'Primary location',
                        'tutorhelper-bookings'
                    );
                    ?>
                </strong>
            </label>

            <select
                id="tutorhelper-range-primary-location"
                name="location_type"
            >
                <?php foreach ( $locations as $key => $label ) : ?>
                    <option
                        value="<?php echo esc_attr( $key ); ?>"
                        <?php selected( 'online', $key ); ?>
                    >
                        <?php echo esc_html( $label ); ?>
                    </option>
                <?php endforeach; ?>
            </select>
        </p>
        <?php
    }


    /**
     * Render permitted Booking Types for a Working day.
     *
     * No selection means that all active Booking Types are permitted.
     *
     * @param array $booking_types Active Booking Types.
     *
     * @return void
     */
    private static function render_working_day_booking_types(
        $booking_types
    ) {
        ?>
        <fieldset class="tutorhelper-working-day-fields__booking-types">
            <legend>
                <strong>
                    <?php
                    echo esc_html__(
                        'Permitted Booking Types',
                        'tutorhelper-bookings'
                    );
                    ?>
                </strong>
            </legend>

            <p class="description">
                <?php
                echo esc_html__(
                    'Leave all options unticked to allow every active Booking Type.',
                    'tutorhelper-bookings'
                );
                ?>
            </p>

            <div class="tutorhelper-working-day-booking-types">
                <?php foreach ( $booking_types as $booking_type ) : ?>
                    <label>
                        <input
                            type="checkbox"
                            name="allowed_booking_type_ids[]"
                            value="<?php
                                echo esc_attr(
                                    absint(
                                        $booking_type->id
                                    )
                                );
                            ?>"
                        />

                        <span>
                            <?php
                            echo esc_html(
                                $booking_type->title
                            );
                            ?>
                        </span>
                    </label>
                <?php endforeach; ?>
            </div>
        </fieldset>
        <?php
    }



    /**
     * Render one range-type choice.
     *
     * @param string $value       Range type value.
     * @param string $label       Visible label.
     * @param string $description Supporting description.
     * @param bool   $checked     Whether selected initially.
     *
     * @return void
     */
    private static function render_range_type_option(
        $value,
        $label,
        $description,
        $checked = false
    ) {
        $input_id =
            'tutorhelper-range-type-'
            . sanitize_html_class( $value );

        ?>
        <label
            class="tutorhelper-range-type"
            for="<?php echo esc_attr( $input_id ); ?>"
        >
            <input
                type="radio"
                id="<?php echo esc_attr( $input_id ); ?>"
                name="tutorhelper_range_type"
                value="<?php echo esc_attr( $value ); ?>"
                <?php checked( $checked ); ?>
            />

            <span
                class="<?php
                    echo esc_attr(
                        self::get_marker_classes(
                            array( $value )
                        )
                    );
                ?>"
                aria-hidden="true"
            ></span>

            <span class="tutorhelper-range-type__content">
                <strong>
                    <?php echo esc_html( $label ); ?>
                </strong>

                <span>
                    <?php echo esc_html( $description ); ?>
                </span>
            </span>
        </label>
        <?php
    }




    	/**
	 * Render a calendar data error.
	 *
	 * @param WP_Error $error Calendar error.
	 *
	 * @return void
	 */
	private static function render_error(
		$error
	) {
		$message = is_wp_error( $error )
			? $error->get_error_message()
			: __(
				'The availability calendar could not be loaded.',
				'tutorhelper-bookings'
			);

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


    	/**
	 * Group calendar days by month.
	 *
	 * @param array $days Calendar days.
	 *
	 * @return array
	 */
	private static function group_days_by_month(
		$days
	) {
		$months = array();

		foreach ( $days as $day ) {
			if (
				! is_array( $day )
				|| empty( $day['date'] )
			) {
				continue;
			}

			$month_key = substr(
				$day['date'],
				0,
				7
			);

			if (
				! isset(
					$months[ $month_key ]
				)
			) {
				$months[ $month_key ] = array();
			}

			$months[ $month_key ][] = $day;
		}

		return $months;
	}


    	/**
	 * Render the full twelve-month calendar.
	 *
	 * @param array $calendar Calendar dataset.
	 *
	 * @return void
	 */
	private static function render_calendar(
		$calendar
	) {
		$days = isset( $calendar['days'] )
			&& is_array( $calendar['days'] )
				? $calendar['days']
				: array();

		$months = self::group_days_by_month(
			$days
		);

		if ( empty( $months ) ) {
			?>
			<div class="notice notice-info inline">
				<p>
					<?php
					echo esc_html__(
						'No calendar dates are available.',
						'tutorhelper-bookings'
					);
					?>
				</p>
			</div>
			<?php

			return;
		}

		?>
		<div class="tutorhelper-year-calendar">
			<?php
			foreach (
				$months as $month_key => $month_days
			) {
				self::render_month(
					$month_key,
					$month_days
				);
			}
			?>
		</div>
		<?php
	}


    	/**
	 * Render one calendar month.
	 *
	 * @param string $month_key  Month in Y-m format.
	 * @param array  $month_days Days in the month.
	 *
	 * @return void
	 */
	private static function render_month(
		$month_key,
		$month_days
	) {
		$month_date =
			DateTimeImmutable::createFromFormat(
				'!Y-m',
				$month_key,
				wp_timezone()
			);

		if ( false === $month_date ) {
			return;
		}

		$month_id =
			'tutorhelper-month-'
			. sanitize_html_class(
				$month_key
			);

		?>
		<section
			class="tutorhelper-year-calendar__month"
			aria-labelledby="<?php
				echo esc_attr( $month_id );
			?>"
		>
			<h3
				id="<?php echo esc_attr( $month_id ); ?>"
				class="tutorhelper-year-calendar__month-title"
			>
				<?php
				echo esc_html(
					wp_date(
						'F Y',
						$month_date->getTimestamp(),
						wp_timezone()
					)
				);
				?>
			</h3>

			<div
				class="tutorhelper-year-calendar__weekdays"
				aria-hidden="true"
			>
				<?php
				foreach (
					self::get_weekday_labels()
					as $weekday
				) :
					?>
					<span>
						<?php echo esc_html( $weekday ); ?>
					</span>
				<?php endforeach; ?>
			</div>

			<div class="tutorhelper-year-calendar__days">
				<?php
				self::render_leading_blanks(
					$month_days
				);

				foreach ( $month_days as $day ) {
					self::render_day( $day );
				}
				?>
			</div>
		</section>
		<?php
	}


    	/**
	 * Return short weekday labels beginning with Monday.
	 *
	 * @return array
	 */
	private static function get_weekday_labels() {
		return array(
			_x(
				'Mon',
				'Short weekday name',
				'tutorhelper-bookings'
			),
			_x(
				'Tue',
				'Short weekday name',
				'tutorhelper-bookings'
			),
			_x(
				'Wed',
				'Short weekday name',
				'tutorhelper-bookings'
			),
			_x(
				'Thu',
				'Short weekday name',
				'tutorhelper-bookings'
			),
			_x(
				'Fri',
				'Short weekday name',
				'tutorhelper-bookings'
			),
			_x(
				'Sat',
				'Short weekday name',
				'tutorhelper-bookings'
			),
			_x(
				'Sun',
				'Short weekday name',
				'tutorhelper-bookings'
			),
		);
	}


    	/**
	 * Render blank cells before the first date of a month.
	 *
	 * @param array $month_days Month day records.
	 *
	 * @return void
	 */
	private static function render_leading_blanks(
		$month_days
	) {
		if ( empty( $month_days ) ) {
			return;
		}

		$first_day = reset(
			$month_days
		);

		$weekday = isset(
			$first_day['weekday']
		)
			? (int) $first_day['weekday']
			: 1;

		$blank_count = max(
			0,
			$weekday - 1
		);

		for (
			$index = 0;
			$index < $blank_count;
			$index++
		) {
			?>
			<span
				class="tutorhelper-year-calendar__blank"
				aria-hidden="true"
			></span>
			<?php
		}
	}


    	/**
	 * Return classes for a date marker.
	 *
	 * @param array $display_types Display classifications.
	 *
	 * @return string
	 */
	private static function get_marker_classes(
		$display_types
	) {
		$display_types = is_array(
			$display_types
		)
			? array_values(
				array_unique(
					array_map(
						'sanitize_key',
						$display_types
					)
				)
			)
			: array();

		$classes = array(
			'tutorhelper-calendar-marker',
		);

		foreach ( $display_types as $type ) {
			$classes[] = 'has-' . $type;
		}

		$count = count( $display_types );

		if ( 1 === $count ) {
			$classes[] = 'has-one-type';
		} elseif ( 2 === $count ) {
			$classes[] = 'has-two-types';
		} elseif ( 2 < $count ) {
			$classes[] = 'has-multiple-types';
		}

		return implode(
			' ',
			$classes
		);
	}


    	/**
	 * Return a readable classification summary for a date.
	 *
	 * @param array $day Calendar day.
	 *
	 * @return string
	 */
	private static function get_day_description(
		$day
	) {
		$date = isset( $day['date'] )
			? $day['date']
			: '';

		$date_object =
			DateTimeImmutable::createFromFormat(
				'!Y-m-d',
				$date,
				wp_timezone()
			);

		$date_label = false !== $date_object
			? wp_date(
				'l j F Y',
				$date_object->getTimestamp(),
				wp_timezone()
			)
			: $date;

		$type_definitions =
			TutorHelper_Availability_Calendar::
				get_display_types();

		$labels = array();

		if (
			isset( $day['display_types'] )
			&& is_array(
				$day['display_types']
			)
		) {
			foreach (
				$day['display_types'] as $type
			) {
				if (
					isset(
						$type_definitions[
							$type
						]['label']
					)
				) {
					$labels[] =
						$type_definitions[
							$type
						]['label'];
				}
			}
		}

		if ( empty( $labels ) ) {
			return sprintf(
				/* translators: %s: formatted calendar date. */
				__(
					'%s. No availability information.',
					'tutorhelper-bookings'
				),
				$date_label
			);
		}

		return sprintf(
			/* translators: 1: formatted date, 2: availability descriptions. */
			__(
				'%1$s. %2$s.',
				'tutorhelper-bookings'
			),
			$date_label,
			implode(
				', ',
				$labels
			)
		);
	}

    	/**
	 * Render one calendar date.
	 *
	 * @param array $day Calendar day.
	 *
	 * @return void
	 */
	private static function render_day(
		$day
	) {
		$date = isset( $day['date'] )
			? sanitize_text_field(
				$day['date']
			)
			: '';

		if ( empty( $date ) ) {
			return;
		}

		$day_number = (int) substr(
			$date,
			8,
			2
		);

		$display_types = isset(
			$day['display_types']
		)
			&& is_array(
				$day['display_types']
			)
				? $day['display_types']
				: array();

		$classes = array(
			'tutorhelper-year-calendar__day',
		);

		if ( ! empty( $day['is_today'] ) ) {
			$classes[] = 'is-today';
		}

		if (
			! empty(
				$day['is_student_bookable']
			)
		) {
			$classes[] = 'is-student-bookable';
		}

		if ( ! empty( $display_types ) ) {
			$classes[] =
				'has-calendar-data';
		}

		$edit_items =
			self::get_day_edit_items(
				$day
			);

		?>
		<button
			type="button"
			class="<?php
				echo esc_attr(
					implode(
						' ',
						$classes
					)
				);
			?>"
			data-date="<?php echo esc_attr( $date ); ?>"
			aria-pressed="false"
			data-edit-items="<?php
				echo esc_attr(
					wp_json_encode(
						$edit_items
					)
				);
			?>"
			aria-label="<?php
				echo esc_attr(
					self::get_day_description(
						$day
					)
				);
			?>"
		>
			<span class="tutorhelper-year-calendar__day-number">
				<?php echo esc_html( $day_number ); ?>
			</span>

			<?php if ( ! empty( $display_types ) ) : ?>
				<span
					class="<?php
						echo esc_attr(
							self::get_marker_classes(
								$display_types
							)
						);
					?>"
					aria-hidden="true"
				></span>
			<?php endif; ?>

			<?php if ( ! empty( $day['is_today'] ) ) : ?>
				<span class="screen-reader-text">
					<?php
					echo esc_html__(
						'Today',
						'tutorhelper-bookings'
					);
					?>
				</span>
			<?php endif; ?>
		</button>
		<?php
	}


	/**
	 * Return editable records represented by one calendar day.
	 *
	 * @param array $day Calendar day.
	 *
	 * @return array
	 */
	private static function get_day_edit_items(
		$day
	) {

		$items = array();

		if (
			! empty(
				$day['availability']
			)
			&& is_array(
				$day['availability']
			)
		) {

			foreach (
				$day['availability']
				as $availability
			) {

				$record_id =
					isset(
						$availability[
							'availability_id'
						]
					)
						? absint(
							$availability[
								'availability_id'
							]
						)
						: 0;

				if ( ! $record_id ) {
					continue;
				}

				$items[
					'availability-'
					. $record_id
				] = array(
					'record_type' =>
						'availability',

					'record_id' =>
						$record_id,

					'range_type' =>
						'general_availability',

					'occurrence_date' =>
						isset(
							$day['date']
						)
							? sanitize_text_field(
								$day['date']
							)
							: '',

					'title' =>
						isset(
							$availability[
								'title'
							]
						)
							? sanitize_text_field(
								$availability[
									'title'
								]
							)
							: __(
								'Working day',
								'tutorhelper-bookings'
							),

				);
			}
		}


		if (
			! empty(
				$day['exclusions']
			)
			&& is_array(
				$day['exclusions']
			)
		) {

			foreach (
				$day['exclusions']
				as $exclusion
			) {

				$record_id =
					isset(
						$exclusion[
							'exclusion_id'
						]
					)
						? absint(
							$exclusion[
								'exclusion_id'
							]
						)
						: 0;

				if ( ! $record_id ) {
					continue;
				}

				$items[
					'exclusion-'
					. $record_id
				] = array(
					'record_type' =>
						'date_exclusion',

					'record_id' =>
						$record_id,

					'range_type' =>
						isset(
							$exclusion[
								'display_type'
							]
						)
							? sanitize_key(
								$exclusion[
									'display_type'
								]
							)
							: '',

					'title' =>
						isset(
							$exclusion[
								'title'
							]
						)
							? sanitize_text_field(
								$exclusion[
									'title'
								]
							)
							: '',
				);
			}
		}

		return array_values(
			$items
		);
	}


	/**
	 * Return one editable Availability planner record.
	 *
	 * @return void
	 */
	public static function handle_load_item() {

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

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

		$record_type =
			isset(
				$_POST['record_type']
			)
				? sanitize_key(
					wp_unslash(
						$_POST[
							'record_type'
						]
					)
				)
				: '';

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

		if ( ! $record_id ) {
			wp_send_json_error(
				array(
					'message' =>
						__(
							'The selected calendar item is invalid.',
							'tutorhelper-bookings'
						),
				),
				400
			);
		}


		if (
			'availability'
			=== $record_type
		) {

			$record =
				TutorHelper_Booking_Availability::
					get_by_id(
						$record_id
					);

			if (
				! $record
				|| absint(
					$record->
						tutor_user_id
				)
				!== get_current_user_id()
			) {
				wp_send_json_error(
					array(
						'message' =>
							__(
								'The selected Working day could not be found.',
								'tutorhelper-bookings'
							),
					),
					404
				);
			}

			wp_send_json_success(
				self::prepare_availability_for_edit(
					$record
				)
			);
		}


		if (
			'date_exclusion'
			=== $record_type
		) {

			$record =
				TutorHelper_Date_Exclusions::
					get_by_id(
						$record_id
					);

			if (
				! $record
				|| absint(
					$record->
						tutor_user_id
				)
				!== get_current_user_id()
			) {
				wp_send_json_error(
					array(
						'message' =>
							__(
								'The selected date range could not be found.',
								'tutorhelper-bookings'
							),
					),
					404
				);
			}

			wp_send_json_success(
				self::prepare_exclusion_for_edit(
					$record
				)
			);
		}


		wp_send_json_error(
			array(
				'message' =>
					__(
						'The selected calendar item type is invalid.',
						'tutorhelper-bookings'
					),
			),
			400
		);
	}


	private static function prepare_availability_for_edit(
		$record
	) {

		return array(
			'record_type' =>
				'availability',

			'record_id' =>
				absint(
					$record->id
				),

			'range_type' =>
				'general_availability',

			'title' =>
				sanitize_text_field(
					$record->title
				),

			'start_date' =>
				sanitize_text_field(
					$record->start_date
				),

			'end_date' =>
				sanitize_text_field(
					$record->end_date
				),

			'weekdays' =>
				array_values(
					array_filter(
						array_map(
							'sanitize_key',
							explode(
								',',
								(string)
									$record->
										weekdays
							)
						)
					)
				),

			'start_time' =>
				substr(
					(string)
						$record->
							start_time,
					0,
					5
				),

			'end_time' =>
				substr(
					(string)
						$record->
							end_time,
					0,
					5
				),

			'location_types' =>
				array_values(
					array_filter(
						array_map(
							'sanitize_key',
							explode(
								',',
								(string)
									$record->
										location_types
							)
						)
					)
				),

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

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

			'allowed_booking_type_ids' =>
				array_values(
					array_filter(
						array_map(
							'absint',
							explode(
								',',
								(string)
									$record->
										allowed_booking_type_ids
							)
						)
					)
				),
		);
	}


	private static function prepare_exclusion_for_edit(
		$record
	) {

		switch (
			sanitize_key(
				$record->
					exclusion_type
			)
		) {

			case TutorHelper_Date_Exclusions::
				TYPE_OUTSIDE_TERM_TIME:

				$range_type =
					'outside_term_time';

				break;

			case TutorHelper_Date_Exclusions::
				TYPE_HOLIDAY:

				$range_type =
					'public_holiday';

				break;

			case TutorHelper_Date_Exclusions::
				TYPE_UNAVAILABLE:

				$range_type =
					'tutor_leave';

				break;

			default:

				$range_type = '';
		}

		return array(
			'record_type' =>
				'date_exclusion',

			'record_id' =>
				absint(
					$record->id
				),

			'range_type' =>
				$range_type,

			'title' =>
				sanitize_text_field(
					$record->title
				),

			'start_date' =>
				sanitize_text_field(
					$record->start_date
				),

			'end_date' =>
				sanitize_text_field(
					$record->end_date
				),

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

	/**
	 * Render the calendar-item chooser.
	 *
	 * Used when one calendar date contains more than one
	 * editable Availability Planner record.
	 *
	 * @return void
	 */
	private static function render_calendar_item_chooser() {
		?>
		<div
			id="tutorhelper-calendar-item-chooser"
			class="tutorhelper-calendar-item-chooser"
			hidden
		>
			<div
				class="tutorhelper-calendar-item-chooser__backdrop"
				data-tutorhelper-close-chooser
			></div>

			<div
				class="tutorhelper-calendar-item-chooser__dialog"
				role="dialog"
				aria-modal="true"
				aria-labelledby="tutorhelper-calendar-item-chooser-title"
			>
				<div
					class="tutorhelper-calendar-item-chooser__header"
				>
					<div>
						<h3
							id="tutorhelper-calendar-item-chooser-title"
						>
							<?php
							echo esc_html__(
								'Choose an entry to edit',
								'tutorhelper-bookings'
							);
							?>
						</h3>

						<p
							id="tutorhelper-calendar-item-chooser-date"
						></p>
					</div>

					<button
						type="button"
						class="button-link"
						data-tutorhelper-close-chooser
					>
						<?php
						echo esc_html__(
							'Close',
							'tutorhelper-bookings'
						);
						?>
					</button>
				</div>

				<p>
					<?php
					echo esc_html__(
						'This date contains more than one calendar entry. Choose which one you want to edit.',
						'tutorhelper-bookings'
					);
					?>
				</p>

				<div
					id="tutorhelper-calendar-item-chooser-options"
					class="tutorhelper-calendar-item-chooser__options"
				></div>
			</div>
		</div>
		<?php
	}


	/**
	 * Archive a complete planner range.
	 *
	 * @return void
	 */
	public static function handle_delete() {

		self::verify_save_request();

		check_admin_referer(
			self::DELETE_ACTION,
			'tutorhelper_delete_range_nonce'
		);

		$record_type =
			isset(
				$_POST['record_type']
			)
				? sanitize_key(
					wp_unslash(
						$_POST['record_type']
					)
				)
				: '';

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

		if ( ! $record_id ) {
			self::redirect_after_save(
				'error',
				'tutorhelper_range_delete_invalid'
			);
		}


		if (
			'availability'
			=== $record_type
		) {

			$record =
				TutorHelper_Booking_Availability::
					get_by_id(
						$record_id
					);

			if (
				! $record
				|| absint(
					$record->tutor_user_id
				)
				!== get_current_user_id()
			) {
				self::redirect_after_save(
					'error',
					'tutorhelper_range_not_found'
				);
			}

			$result =
				TutorHelper_Booking_Availability::
					archive(
						$record_id
					);

		} elseif (
			'date_exclusion'
			=== $record_type
		) {

			$record =
				TutorHelper_Date_Exclusions::
					get_by_id(
						$record_id
					);

			if (
				! $record
				|| absint(
					$record->tutor_user_id
				)
				!== get_current_user_id()
			) {
				self::redirect_after_save(
					'error',
					'tutorhelper_range_not_found'
				);
			}

			$result =
				TutorHelper_Date_Exclusions::
					update(
						$record_id,
						array(
							'is_active' =>
								0,
						)
					);

		} else {

			self::redirect_after_save(
				'error',
				'tutorhelper_range_delete_invalid'
			);
		}


		if ( is_wp_error( $result ) ) {
			self::redirect_after_save(
				'error',
				$result->get_error_code()
			);
		}


		TutorHelper_Logger::success(
			'Availability planner range archived.',
			array(
				'record_type' =>
					$record_type,

				'record_id' =>
					$record_id,
			)
		);


		self::redirect_after_save(
			'deleted'
		);
	}


}

TutorHelper_Availability_Calendar_Admin::init();
