<?php

namespace SugarCalendarBookings\Calendar\Admin;

use DateInterval;
use DatePeriod;
use Exception;
use SugarCalendarBookings\Appointments\AppointmentModel;
use SugarCalendarBookings\Calendar\CalendarHelpers;
use SugarCalendarBookings\Plugin;
use SugarCalendarBookings\Support\Helpers\Date;
use SugarCalendarBookings\Support\Helpers\Helpers;

/**
 * Calendar month view.
 *
 * @since 1.0.0
 */
class CalendarMonthView extends AbstractCalendarView {

	/**
	 * View mode.
	 *
	 * @since 1.0.0
	 *
	 * @var string
	 */
	const MODE = 'month';

	/**
	 * Get column options.
	 *
	 * @since 1.0.0
	 *
	 * @return array
	 */
	public function get_column_options() {

		return array_map( fn( $period ) => $period->get_end()->format( 'l' ), $this->get_header_slots() );
	}

	/**
	 * Get header slots.
	 *
	 * @since 1.0.0
	 *
	 * @return array<BaseCalendarSlot>
	 */
	protected function get_header_slots() {

		try {
			$period = new DatePeriod(
				$this->query->get_start_date(),
				DateInterval::createFromDateString( '1 day' ),
				$this->query->get_start_date()->modify( '+7 days' )
			);
		} catch ( Exception $e ) {
			return [];
		}

		return array_map(
			fn( $date ) => new BaseCalendarSlot( $date, $date->setTime( 23, 59, 59 ) ),
			iterator_to_array( $period )
		);
	}

	/**
	 * Get header cell class.
	 *
	 * @since 1.0.0
	 *
	 * @param BaseCalendarSlot $slot Calendar slot.
	 *
	 * @return array
	 */
	protected function get_header_cell_class( $slot ) {

		$class   = parent::get_header_cell_class( $slot );
		$class[] = 'sugar-calendar-bookings-calendar__cell--' . strtolower( $slot->get_start()->format( 'l' ) );

		return $class;
	}

	/**
	 * Get body cell class.
	 *
	 * @since 1.0.0
	 *
	 * @param BaseCalendarSlot $slot Calendar slot.
	 *
	 * @return array
	 */
	protected function get_body_cell_class( $slot ) {

		$class   = parent::get_body_cell_class( $slot );
		$class[] = 'sugar-calendar-bookings-calendar__cell--' . strtolower( $slot->get_start()->format( 'l' ) );

		if ( ! $slot->is_same_month( $this->query->get_date() ) ) {
			$class[] = 'sugar-calendar-bookings-calendar__cell--other-month';
		}

		if ( $slot->is_same_day( $this->query->get_today() ) ) {
			$class[] = 'sugar-calendar-bookings-calendar__cell--today';
		}

		return $class;
	}

	/**
	 * Display header cell.
	 *
	 * @since 1.0.0
	 *
	 * @param BaseCalendarSlot $slot Calendar slot.
	 *
	 * @return void
	 */
	protected function display_header_cell( $slot ) {

		echo esc_html( $slot->get_start()->format( 'l' ) );
	}

	/**
	 * Display body cell.
	 *
	 * @since 1.0.0
	 *
	 * @param BaseCalendarSlot        $slot         Calendar slot.
	 * @param array<AppointmentModel> $appointments Appointments.
	 *
	 * @return void
	 */
	protected function display_body_cell( $slot, $appointments ) {

		$format = $slot->is_first_day_of_month() ? 'M j' : 'j';

		/**
		 * Filter the amount of appointments to
		 * list before starting to collapse them.
		 *
		 * @since 1.0.0
		 *
		 * @param int $visible Visible appointments count.
		 */
		$visible = apply_filters( 'sugar_calendar_bookings_calendar_admin_calendar_month_view_visible_entries', 3 );

		[ $visible, $hidden ] = [
			array_slice( $appointments, 0, $visible ),
			array_slice( $appointments, $visible ),
		]
		?>
		<div class="sugar-calendar-bookings-calendar__day"><?php echo esc_html( $slot->get_start()->format( $format ) ); ?></div>
		<div class="sugar-calendar-bookings-calendar__entries">

			<?php
			foreach ( $visible as $appointment ) {
				$this->output_appointment( $appointment );
			}

			if ( count( $hidden ) > 0 ) :
				?>

				<div class="sugar-calendar-bookings-calendar__entry sugar-calendar-bookings-calendar__entry--more" data-show-more>
					<?php
					printf(
					/* translators: %1$s - appointment count. */
						esc_html__( '+%1$s More', 'sugar-calendar-bookings-scheduling-appointments-lite' ),
						count( $hidden )
					);
					?>
				</div>
				<div class="sugar-calendar-bookings-appointment-list-popover" data-sugar-calendar-bookings-more-appointments-popover>
					<div class="sugar-calendar-bookings-appointment-list-popover__header">
						<?php echo esc_html( $slot->get_start()->format( 'l, j' ) ); ?>
						<button data-close></button>
					</div>
					<div class="sugar-calendar-bookings-appointment-list-popover__body">

						<?php
						foreach ( $hidden as $appointment ) {
							$this->output_appointment( $appointment );
						}
						?>

					</div>
				</div>

			<?php endif; ?>

		</div>
		<?php
		CalendarHelpers::add_appointment_button( $slot->get_start(), $slot->get_end() );
	}

	/**
	 * Output appointment entry.
	 *
	 * @since 1.0.0
	 *
	 * @param AppointmentModel $appointment Appointment.
	 *
	 * @return void
	 */
	private function output_appointment( $appointment ) {

		?>
		<div class="sugar-calendar-bookings-calendar__entry sugar-calendar-bookings-calendar__entry--<?php echo esc_attr( $appointment->status ); ?>"
			data-preview
			data-appointment-id="<?php echo esc_attr( $appointment->id ); ?>"
			style="--entry-color: <?php echo esc_attr( $appointment->service->color ); ?>;">
			<span class="sugar-calendar-bookings-calendar__entry__time">
				<?php echo esc_html( Date::format_display_date( $appointment->start_at, 'g:iA' ) ); ?>
			</span>
			<span class="sugar-calendar-bookings-calendar__entry__title"><?php echo esc_html( $appointment->service->name ); ?></span>
		</div>
		<?php
	}

	/**
	 * Output dynamic styles.
	 *
	 * @since 1.0.0
	 * @since 1.4.0 Changed from static to instance method.
	 *
	 * @return void
	 */
	public function output_styles() {

		$available_days  = CalendarHelpers::get_available_days();
		$hidden_columns  = Plugin::get( CalendarScreenOptions::class )->get( 'hidden_columns' );
		$hidden_columns  = $hidden_columns[ static::MODE ] ?? [];
		$visible_columns = 7 - count( $hidden_columns );

		Helpers::template(
			'calendar/month-view-styles.php',
			[
				'available_days'  => $available_days,
				'hidden_columns'  => $hidden_columns,
				'visible_columns' => $visible_columns,
			]
		);
	}
}
