<?php
/**
 * Booking calendar administration renderer.
 *
 * @package TutorHelper_Bookings
 */

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

/**
 * Renders saved bookings inside Booking Hub calendars.
 */
final class TutorHelper_Booking_Calendar_Admin {

	/**
	 * Cached week results for the current request.
	 *
	 * Keyed by tutor, timezone and Monday date.
	 *
	 * @var array
	 */
	private static $week_cache = array();


	/**
	 * Cached month-grid results for the current request.
	 *
	 * Keyed by tutor, timezone and selected month.
	 *
	 * @var array
	 */
	private static $month_cache = array();

	/**
	 * Maximum number of booking indicators shown in one month cell.
	 *
	 * @var int
	 */
	const MONTH_VISIBLE_LIMIT = 5;

	/**
	 * Register calendar rendering hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_action(
			'tutorhelper_booking_hub_week_bookings',
			array(
				__CLASS__,
				'render_week_bookings',
			),
			10,
			2
		);

		add_action(
			'tutorhelper_booking_hub_month_day',
			array(
				__CLASS__,
				'render_month_bookings',
			),
			10,
			2
		);


	}

	/**
	 * Return the beginning and end of the displayed week.
	 *
	 * @param DateTimeImmutable $date A date within the displayed week.
	 *
	 * @return array
	 */
	private static function get_week_range(
		DateTimeImmutable $date
	) {
		$week_start = $date->modify(
			'monday this week'
		);

		$week_end = $week_start->modify(
			'+6 days'
		);

		return array(
			'start' => $week_start,
			'end'   => $week_end,
		);
	}


	/**
	 * Return the first and last dates in the visible month grid.
	 *
	 * @param DateTimeImmutable $selected_date Selected calendar date.
	 *
	 * @return array
	 */
	private static function get_month_grid_range(
		DateTimeImmutable $selected_date
	) {
		$weeks =
			TutorHelper_Booking_Hub::get_month_grid(
				$selected_date
			);

		if (
			empty( $weeks )
			|| ! is_array( $weeks )
		) {
			return array(
				'start' =>
					$selected_date->modify(
						'first day of this month'
					),

				'end' =>
					$selected_date->modify(
						'last day of this month'
					),
			);
		}

		$first_week = reset( $weeks );
		$last_week  = end( $weeks );

		$start = is_array( $first_week )
			? reset( $first_week )
			: null;

		$end = is_array( $last_week )
			? end( $last_week )
			: null;

		if (
			! $start instanceof DateTimeImmutable
			|| ! $end instanceof DateTimeImmutable
		) {
			return array(
				'start' =>
					$selected_date->modify(
						'first day of this month'
					),

				'end' =>
					$selected_date->modify(
						'last day of this month'
					),
			);
		}

		return array(
			'start' => $start,
			'end'   => $end,
		);
	}


	/**
	 * Return the cache key for a displayed week.
	 *
	 * @param int               $tutor_user_id Tutor user ID.
	 * @param DateTimeZone      $timezone      Calendar timezone.
	 * @param DateTimeImmutable $week_start    Local week start.
	 *
	 * @return string
	 */
	private static function get_cache_key(
		$tutor_user_id,
		$timezone,
		$week_start
	) {
		return implode(
			'|',
			array(
				absint( $tutor_user_id ),
				$timezone->getName(),
				$week_start->format(
					'Y-m-d'
				),
			)
		);
	}

	/**
	 * Return the request-cache key for a month grid.
	 *
	 * @param int               $tutor_user_id Tutor user ID.
	 * @param DateTimeZone      $timezone      Calendar timezone.
	 * @param DateTimeImmutable $selected_date Selected month date.
	 *
	 * @return string
	 */
	private static function get_month_cache_key(
		$tutor_user_id,
		DateTimeZone $timezone,
		DateTimeImmutable $selected_date
	) {
		return implode(
			'|',
			array(
				absint( $tutor_user_id ),
				$timezone->getName(),
				$selected_date->format(
					'Y-m'
				),
			)
		);
	}



	/**
	 * Retrieve and group one calendar week's bookings.
	 *
	 * The hook is called seven times, once for each day. This method
	 * caches the result so the database service runs only once.
	 *
	 * @param int               $tutor_user_id Tutor user ID.
	 * @param DateTimeImmutable $date          Date within the week.
	 *
	 * @return array
	 */
	private static function get_grouped_week_bookings(
		$tutor_user_id,
		DateTimeImmutable $date
	) {
		$timezone = wp_timezone();

		$range = self::get_week_range(
			$date
		);

		$cache_key = self::get_cache_key(
			$tutor_user_id,
			$timezone,
			$range['start']
		);

		if (
			array_key_exists(
				$cache_key,
				self::$week_cache
			)
		) {
			return self::$week_cache[
				$cache_key
			];
		}

		$result =
			TutorHelper_Booking_Calendar_Data::
				get_for_range(
					array(
						'tutor_user_id' =>
							$tutor_user_id,

						'date_from' =>
							$range['start']
								->format(
									'Y-m-d'
								),

						'date_to' =>
							$range['end']
								->format(
									'Y-m-d'
								),

						'timezone' =>
							$timezone
								->getName(),
					)
				);

		if ( is_wp_error( $result ) ) {
			TutorHelper_Logger::warning(
				'Weekly calendar bookings could not be loaded.',
				array(
					'tutor_user_id' =>
						absint(
							$tutor_user_id
						),

					'week_start' =>
						$range['start']
							->format(
								'Y-m-d'
							),

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

			self::$week_cache[
				$cache_key
			] = array();

			return array();
		}

		$grouped =
			TutorHelper_Booking_Calendar_Data::
				group_by_local_date(
					isset(
						$result['bookings']
					)
					&& is_array(
						$result['bookings']
					)
						? $result[
							'bookings'
						]
						: array()
				);

		self::$week_cache[
			$cache_key
		] = $grouped;

		return $grouped;
	}

	/**
	 * Retrieve and group bookings for the complete visible month grid.
	 *
	 * The month-day hook runs once for every displayed cell. Results are
	 * cached so the booking service performs one query per page request.
	 *
	 * @param int               $tutor_user_id Tutor user ID.
	 * @param DateTimeImmutable $selected_date Selected calendar date.
	 *
	 * @return array
	 */
	private static function get_grouped_month_bookings(
		$tutor_user_id,
		DateTimeImmutable $selected_date
	) {
		$timezone =
			wp_timezone();

		$cache_key =
			self::get_month_cache_key(
				$tutor_user_id,
				$timezone,
				$selected_date
			);

		if (
			array_key_exists(
				$cache_key,
				self::$month_cache
			)
		) {
			return self::$month_cache[
				$cache_key
			];
		}

		$range =
			self::get_month_grid_range(
				$selected_date
			);

		$result =
			TutorHelper_Booking_Calendar_Data::
				get_for_range(
					array(
						'tutor_user_id' =>
							absint(
								$tutor_user_id
							),

						'date_from' =>
							$range['start']
								->format(
									'Y-m-d'
								),

						'date_to' =>
							$range['end']
								->format(
									'Y-m-d'
								),

						'timezone' =>
							$timezone->getName(),
					)
				);

		if ( is_wp_error( $result ) ) {
			TutorHelper_Logger::warning(
				'Monthly calendar bookings could not be loaded.',
				array(
					'tutor_user_id' =>
						absint(
							$tutor_user_id
						),

					'month' =>
						$selected_date
							->format(
								'Y-m'
							),

					'grid_start' =>
						$range['start']
							->format(
								'Y-m-d'
							),

					'grid_end' =>
						$range['end']
							->format(
								'Y-m-d'
							),

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

			self::$month_cache[
				$cache_key
			] = array();

			return array();
		}

		$records = isset(
			$result['bookings']
		)
		&& is_array(
			$result['bookings']
		)
			? $result['bookings']
			: array();

		$grouped =
			TutorHelper_Booking_Calendar_Data::
				group_by_local_date(
					$records
				);

		self::$month_cache[
			$cache_key
		] = $grouped;

		return $grouped;
	}


	/**
	 * Return the weekly calendar URL for one local date.
	 *
	 * @param string $date_string Date in Y-m-d format.
	 *
	 * @return string
	 */
	private static function get_week_url(
		$date_string
	) {
		$date_string =
			sanitize_text_field(
				$date_string
			);

		return add_query_arg(
			array(
				'page' =>
					TutorHelper_Booking_Hub::
						PAGE_SLUG,

				'tab' =>
					'calendar',

				'view' =>
					'week',

				'date' =>
					$date_string,
			),
			admin_url( 'admin.php' )
		);
	}


	/**
	 * Return a user-facing status label.
	 *
	 * @param string $status Stored status.
	 *
	 * @return string
	 */
	private static function get_status_label(
		$status
	) {
		switch ( sanitize_key( $status ) ) {
			case TutorHelper_Booking_Records::
				STATUS_UNCONFIRMED:
				return __(
					'Unconfirmed',
					'tutorhelper-bookings'
				);

			case TutorHelper_Booking_Records::
				STATUS_CANCELLED:
				return __(
					'Cancelled',
					'tutorhelper-bookings'
				);

			case TutorHelper_Booking_Records::
				STATUS_CONFIRMED:
			default:
				return __(
					'Confirmed',
					'tutorhelper-bookings'
				);
		}
	}

	/**
	 * Return a user-facing location label.
	 *
	 * @param string $location_type Stored location key.
	 *
	 * @return string
	 */
	private static function get_location_label(
		$location_type
	) {
		switch (
			sanitize_key(
				$location_type
			)
		) {
			case 'phone':
				return __(
					'Phone',
					'tutorhelper-bookings'
				);

			case 'in_person':
				return __(
					'In person',
					'tutorhelper-bookings'
				);

			case 'custom':
			case 'other':
				return __(
					'Other',
					'tutorhelper-bookings'
				);

			case 'online':
			default:
				return __(
					'Online',
					'tutorhelper-bookings'
				);
		}
	}

	/**
	 * Return an accessible time-range label.
	 *
	 * @param array $booking Prepared calendar booking.
	 *
	 * @return string
	 */
	private static function get_time_label(
		$booking
	) {
		$start = isset(
			$booking['local_start_time']
		)
			? sanitize_text_field(
				$booking[
					'local_start_time'
				]
			)
			: '';

		$end = isset(
			$booking['local_end_time']
		)
			? sanitize_text_field(
				$booking[
					'local_end_time'
				]
			)
			: '';

		if (
			! empty(
				$booking[
					'spans_multiple_dates'
				]
			)
		) {
			return sprintf(
				/* translators: 1: Start time, 2: End time. */
				__(
					'%1$s–%2$s next day',
					'tutorhelper-bookings'
				),
				$start,
				$end
			);
		}

		return sprintf(
			/* translators: 1: Start time, 2: End time. */
			__(
				'%1$s–%2$s',
				'tutorhelper-bookings'
			),
			$start,
			$end
		);
	}


	/**
	 * Return the Add Booking edit URL for one booking.
	 *
	 * @param int    $booking_id  Booking ID.
	 * @param string $return_view Calendar view to return to.
	 * @param string $return_date Calendar date to return to.
	 *
	 * @return string
	 */
	private static function get_booking_edit_url(
		$booking_id,
		$return_view = '',
		$return_date = ''
	) {
		$booking_id = absint(
			$booking_id
		);

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

		$arguments = array(
			'page' =>
				TutorHelper_Booking_Hub::
					PAGE_SLUG,

			'tab' =>
				TutorHelper_Tutor_Booking_Admin::
					TAB_KEY,

			TutorHelper_Tutor_Booking_Admin::
				MODE_ARGUMENT =>
					TutorHelper_Tutor_Booking_Admin::
						MODE_EDIT,

			TutorHelper_Tutor_Booking_Admin::
				BOOKING_ARGUMENT =>
					$booking_id,
		);

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

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

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


	/**
	 * Return the local booking date formatted for an accessible label.
	 *
	 * @param array $booking Prepared calendar booking.
	 *
	 * @return string
	 */
	private static function get_booking_date_label(
		$booking
	) {
		$date = isset(
			$booking['local_date']
		)
			? sanitize_text_field(
				$booking['local_date']
			)
			: '';

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

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

		$errors =
			DateTimeImmutable::getLastErrors();

		if (
			false === $parsed
			|| (
				is_array( $errors )
				&& (
					0 < $errors['warning_count']
					|| 0 < $errors['error_count']
				)
			)
		) {
			return $date;
		}

		return wp_date(
			get_option( 'date_format' ),
			$parsed->getTimestamp(),
			wp_timezone()
		);
	}


	/**
	 * Build an accessible label for one booking edit link.
	 *
	 * @param array  $booking     Prepared booking.
	 * @param string $student_name Student snapshot name.
	 * @param string $type_title   Booking Type title.
	 * @param string $time_label   Local booking time range.
	 *
	 * @return string
	 */
	private static function get_booking_edit_label(
		$booking,
		$student_name,
		$type_title,
		$time_label
	) {
		$date_label =
			self::get_booking_date_label(
				$booking
			);

		if ( '' !== $date_label ) {
			return sprintf(
				/* translators: 1: Student name, 2: Booking Type, 3: Date, 4: Time. */
				__(
					'Edit booking for %1$s: %2$s on %3$s, %4$s',
					'tutorhelper-bookings'
				),
				$student_name,
				$type_title,
				$date_label,
				$time_label
			);
		}

		return sprintf(
			/* translators: 1: Student name, 2: Booking Type, 3: Time. */
			__(
				'Edit booking for %1$s: %2$s, %3$s',
				'tutorhelper-bookings'
			),
			$student_name,
			$type_title,
			$time_label
		);
	}



	/**
	 * Render one booking card.
	 *
	 * @param array $booking Prepared booking.
	 *
	 * @return void
	 */
	private static function render_booking_card(
		$booking
	) {
		$booking_id = isset(
			$booking['id']
		)
			? absint(
				$booking['id']
			)
			: 0;

		if ( ! $booking_id ) {
			return;
		}

		$colour = isset(
			$booking[
				'booking_type_colour'
			]
		)
			? sanitize_hex_color(
				$booking[
					'booking_type_colour'
				]
			)
			: '';

		if ( ! $colour ) {
			$colour =
				TutorHelper_Booking_Calendar_Data::
					FALLBACK_COLOUR;
		}

		$type_title = isset(
			$booking[
				'booking_type_title'
			]
		)
			? sanitize_text_field(
				$booking[
					'booking_type_title'
				]
			)
			: __(
				'Booking',
				'tutorhelper-bookings'
			);

		$student_name = isset(
			$booking['student_name']
		)
			? sanitize_text_field(
				$booking[
					'student_name'
				]
			)
			: '';

		if ( '' === $student_name ) {
			$student_name = __(
				'Student',
				'tutorhelper-bookings'
			);
		}

		$status = isset(
			$booking['status']
		)
			? sanitize_key(
				$booking['status']
			)
			: TutorHelper_Booking_Records::
				STATUS_CONFIRMED;

		$is_cancelled =
			TutorHelper_Booking_Records::
				STATUS_CANCELLED
			=== $status;

		$cancelled_by =
			isset(
				$booking['cancelled_by']
			)
				? sanitize_key(
					$booking['cancelled_by']
				)
				: '';

		$cancellation_reason =
			isset(
				$booking[
					'cancellation_reason'
				]
			)
				? sanitize_textarea_field(
					$booking[
						'cancellation_reason'
					]
				)
				: '';

		switch ( $status ) {
			case TutorHelper_Booking_Records::
				STATUS_UNCONFIRMED:
				$status_class =
					'is-unconfirmed';
				break;

			case TutorHelper_Booking_Records::
				STATUS_CANCELLED:
				$status_class =
					'is-cancelled';
				break;

			case TutorHelper_Booking_Records::
				STATUS_CONFIRMED:
			default:
				$status_class =
					'is-confirmed';
				break;
		}

		$time_label =
			self::get_time_label(
				$booking
			);

		$location_label =
			self::get_location_label(
				isset(
					$booking[
						'location_type'
					]
				)
					? $booking[
						'location_type'
					]
					: ''
			);

		$duration = isset(
			$booking[
				'duration_minutes'
			]
		)
			? absint(
				$booking[
					'duration_minutes'
				]
			)
			: 0;

		$edit_url =
			$is_cancelled
				? ''
				: self::get_booking_edit_url(
					$booking_id,
					'week',
					isset(
						$booking['local_date']
					)
						? sanitize_text_field(
							$booking[
								'local_date'
							]
						)
						: ''
				);


		$edit_label =
			$is_cancelled
				? ''
				: self::get_booking_edit_label(
					$booking,
					$student_name,
					$type_title,
					$time_label
				);


		if ( $is_cancelled ) :
		?>
		<div
			class="tutorhelper-calendar-booking <?php
				echo esc_attr(
					$status_class
				);
			?>"
			style="<?php
				echo esc_attr(
					'--tutorhelper-booking-colour: '
					. $colour
					. ';'
				);
			?>"
			data-booking-id="<?php
				echo esc_attr(
					$booking_id
				);
			?>"
		>
		<?php
		else :
			?>
			<a
				class="tutorhelper-calendar-booking <?php
					echo esc_attr(
						$status_class
					);
				?>"
				href="<?php
					echo esc_url(
						$edit_url
					);
				?>"
				aria-label="<?php
					echo esc_attr(
						$edit_label
					);
				?>"
				style="<?php
					echo esc_attr(
						'--tutorhelper-booking-colour: '
						. $colour
						. ';'
					);
				?>"
				data-booking-id="<?php
					echo esc_attr(
						$booking_id
					);
				?>"
			>
			<?php
		endif;
		?>

			<header
				class="tutorhelper-calendar-booking__header"
			>
				<time
					class="tutorhelper-calendar-booking__time"
				>
					<?php
					echo esc_html(
						$time_label
					);
					?>
				</time>

				<span
					class="tutorhelper-calendar-booking__status <?php
						echo esc_attr(
							$status_class
						);
					?>"
				>
					<?php
					echo esc_html(
						self::get_status_label(
							$status
						)
					);
					?>
				</span>
			</header>

			<strong
				class="tutorhelper-calendar-booking__student"
			>
				<?php
				echo esc_html(
					$student_name
				);
				?>
			</strong>

			<span
				class="tutorhelper-calendar-booking__type"
			>
				<span
					class="tutorhelper-calendar-booking__type-dot"
					aria-hidden="true"
				></span>

				<?php
				echo esc_html(
					$type_title
				);
				?>
			</span>

			<?php if ( $is_cancelled ) : ?>
				<span
					class="tutorhelper-calendar-booking__cancellation"
				>
					<?php
					if ( 'student' === $cancelled_by ) {
						esc_html_e(
							'Cancelled by student',
							'tutorhelper-bookings'
						);
					} elseif ( 'tutor' === $cancelled_by ) {
						esc_html_e(
							'Cancelled by tutor',
							'tutorhelper-bookings'
						);
					} else {
						esc_html_e(
							'Lesson cancelled',
							'tutorhelper-bookings'
						);
					}
					?>
				</span>

				<?php if ( '' !== $cancellation_reason ) : ?>
					<span
						class="tutorhelper-calendar-booking__cancellation-reason"
					>
						<?php
						echo esc_html(
							$cancellation_reason
						);
						?>
					</span>
				<?php endif; ?>
			<?php endif; ?>

			<footer
				class="tutorhelper-calendar-booking__meta"
			>
				<span>
					<span
						class="dashicons dashicons-location-alt"
						aria-hidden="true"
					></span>

					<?php
					echo esc_html(
						$location_label
					);
					?>
				</span>

				<?php if ( $duration ) : ?>
					<span>
						<span
							class="dashicons dashicons-clock"
							aria-hidden="true"
						></span>

						<?php
						printf(
							/* translators: %d: Booking duration in minutes. */
							esc_html__(
								'%d min',
								'tutorhelper-bookings'
							),
							absint(
								$duration
							)
						);
						?>
					</span>
				<?php endif; ?>
			</footer>
			<?php if ( ! $is_cancelled ) : ?>
				<span
					class="tutorhelper-calendar-booking__edit-cue"
					aria-hidden="true"
				>
					<span
						class="dashicons dashicons-edit"
					></span>

					<?php
					echo esc_html__(
						'Edit',
						'tutorhelper-bookings'
					);
					?>
				</span>
			<?php endif; ?>
		<?php if ( $is_cancelled ) : ?>
			</div>
		<?php else : ?>
			</a>
		<?php endif; ?>
		<?php
	}

	/**
	 * Render bookings for one weekly calendar day.
	 *
	 * @param string            $date_string Local date in Y-m-d format.
	 * @param DateTimeImmutable $date        Local date object.
	 *
	 * @return void
	 */
	public static function render_week_bookings(
		$date_string,
		$date
	) {
		if (
			! current_user_can(
				TutorHelper_Booking_Hub::
					CAPABILITY
			)
		) {
			return;
		}

		if (
			! $date
				instanceof DateTimeImmutable
		) {
			return;
		}

		$date_string =
			sanitize_text_field(
				$date_string
			);

		if (
			$date->format( 'Y-m-d' )
				!== $date_string
		) {
			return;
		}

		$grouped =
			self::get_grouped_week_bookings(
				get_current_user_id(),
				$date
			);

		if (
			empty(
				$grouped[
					$date_string
				]
			)
			|| ! is_array(
				$grouped[
					$date_string
				]
			)
		) {
			return;
		}

		foreach (
			$grouped[
				$date_string
			] as $booking
		) {
			self::render_booking_card(
				$booking
			);
		}
	}


	/**
	 * Render one compact booking link in a month cell.
	 *
	 * @param array $booking Prepared calendar booking.
	 *
	 * @return void
	 */
	private static function render_month_booking(
		$booking,
		$return_date
	) {
		$booking_id = isset(
			$booking['id']
		)
			? absint(
				$booking['id']
			)
			: 0;

		if ( ! $booking_id ) {
			return;
		}

		$status = isset(
			$booking['status']
		)
			? sanitize_key(
				$booking['status']
			)
			: TutorHelper_Booking_Records::
				STATUS_CONFIRMED;
	
		$is_cancelled =
			TutorHelper_Booking_Records::
				STATUS_CANCELLED
			=== $status;

		switch ( $status ) {
			case TutorHelper_Booking_Records::
				STATUS_UNCONFIRMED:
				$status_class =
					'is-unconfirmed';
				break;

			case TutorHelper_Booking_Records::
				STATUS_CANCELLED:
				$status_class =
					'is-cancelled';
				break;

			case TutorHelper_Booking_Records::
				STATUS_CONFIRMED:
			default:
				$status_class =
					'is-confirmed';
				break;
		}

		$edit_url =
			$is_cancelled
				? ''
				: self::get_booking_edit_url(
					$booking_id,
					'month',
					$return_date
				);

		$colour = isset(
			$booking[
				'booking_type_colour'
			]
		)
			? sanitize_hex_color(
				$booking[
					'booking_type_colour'
				]
			)
			: '';

		if ( ! $colour ) {
			$colour =
				TutorHelper_Booking_Calendar_Data::
					FALLBACK_COLOUR;
		}

		$student_name = isset(
			$booking['student_name']
		)
			? sanitize_text_field(
				$booking['student_name']
			)
			: '';

		if ( '' === $student_name ) {
			$student_name = __(
				'Student',
				'tutorhelper-bookings'
			);
		}

		$type_title = isset(
			$booking[
				'booking_type_title'
			]
		)
			? sanitize_text_field(
				$booking[
					'booking_type_title'
				]
			)
			: __(
				'Booking',
				'tutorhelper-bookings'
			);

		$time_label =
			self::get_time_label(
				$booking
			);

		

		$edit_label =
			self::get_booking_edit_label(
				$booking,
				$student_name,
				$type_title,
				$time_label
			);

		?>
		<?php if ( $is_cancelled ) : ?>
			<span
				class="tutorhelper-month-booking <?php
					echo esc_attr(
						$status_class
					);
				?>"
				style="<?php
					echo esc_attr(
						'--tutorhelper-booking-colour: '
						. $colour
						. ';'
					);
				?>"
				data-booking-id="<?php
					echo esc_attr(
						$booking_id
					);
				?>"
			>
		<?php else : ?>
			<a
				class="tutorhelper-month-booking <?php
					echo esc_attr(
						$status_class
					);
				?>"
				href="<?php
					echo esc_url(
						$edit_url
					);
				?>"
				aria-label="<?php
					echo esc_attr(
						$edit_label
					);
				?>"
				style="<?php
					echo esc_attr(
						'--tutorhelper-booking-colour: '
						. $colour
						. ';'
					);
				?>"
				data-booking-id="<?php
					echo esc_attr(
						$booking_id
					);
				?>"
			>
		<?php endif; ?>
			<span
				class="tutorhelper-month-booking__time"
			>
				<?php
				echo esc_html(
					$time_label
				);
				?>
			</span>

			<span
				class="tutorhelper-month-booking__student"
			>
				<?php
				echo esc_html(
					$student_name
				);
				?>
			</span>

			<?php if ( $is_cancelled ) : ?>
				<span
					class="tutorhelper-month-booking__status"
				>
					<?php
					esc_html_e(
						'Cancelled',
						'tutorhelper-bookings'
					);
					?>
				</span>
			<?php endif; ?>

			<span
				class="screen-reader-text"
			>
				<?php
				echo esc_html(
					sprintf(
						/* translators: 1: Booking Type, 2: Booking status. */
						__(
							'%1$s. Status: %2$s.',
							'tutorhelper-bookings'
						),
						$type_title,
						self::get_status_label(
							$status
						)
					)
				);
				?>
			</span>
		<?php if ( $is_cancelled ) : ?>
			</span>
		<?php else : ?>
			</a>
		<?php endif; ?>

		<?php
	}

	/**
	 * Render compact bookings inside one month calendar cell.
	 *
	 * @param string            $date_string Local date in Y-m-d format.
	 * @param DateTimeImmutable $date        Local date object.
	 *
	 * @return void
	 */
	public static function render_month_bookings(
		$date_string,
		$date
	) {
		if (
			! current_user_can(
				TutorHelper_Booking_Hub::
					CAPABILITY
			)
		) {
			return;
		}

		if (
			! $date instanceof DateTimeImmutable
		) {
			return;
		}

		$date_string =
			sanitize_text_field(
				$date_string
			);

		if (
			$date->format( 'Y-m-d' )
				!== $date_string
		) {
			return;
		}

		$selected_date =
			TutorHelper_Booking_Hub::
				get_selected_date();

		$grouped =
			self::get_grouped_month_bookings(
				get_current_user_id(),
				$selected_date
			);

		if (
			empty(
				$grouped[
					$date_string
				]
			)
			|| ! is_array(
				$grouped[
					$date_string
				]
			)
		) {
			return;
		}

		$bookings =
			array_values(
				$grouped[
					$date_string
				]
			);

		$visible =
			array_slice(
				$bookings,
				0,
				self::MONTH_VISIBLE_LIMIT
			);

		?>
		<div
			class="tutorhelper-month-bookings"
			aria-label="<?php
				echo esc_attr(
					sprintf(
						/* translators: %d: Number of bookings on this date. */
						_n(
							'%d booking',
							'%d bookings',
							count( $bookings ),
							'tutorhelper-bookings'
						),
						count( $bookings )
					)
				);
			?>"
		>
			<?php
			foreach ( $visible as $booking ) {
				self::render_month_booking(
					$booking,
					$selected_date->format( 'Y-m-d' ));
			}
			?>

			<?php if (
				count( $bookings )
					> self::MONTH_VISIBLE_LIMIT
			) : ?>
				<?php
				$remaining =
					count( $bookings )
					- self::MONTH_VISIBLE_LIMIT;
				?>

				<a
					class="tutorhelper-month-bookings__more"
					href="<?php
						echo esc_url(
							self::get_week_url(
								$date_string
							)
						);
					?>"
				>
					<?php
					echo esc_html(
						sprintf(
							/* translators: %d: Number of additional bookings. */
							_n(
								'+%d more',
								'+%d more',
								$remaining,
								'tutorhelper-bookings'
							),
							$remaining
						)
					);
					?>
				</a>
			<?php endif; ?>
		</div>
		<?php
	}


}
