<?php
/**
 * Booking email context builder.
 *
 * @package TutorHelper_Bookings
 */

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

/**
 * Builds recipients and placeholders from a booking record.
 */
final class TutorHelper_Booking_Email_Context {

	/**
	 * Build email context for one booking.
	 *
	 * @param int $booking_id Booking ID.
	 *
	 * @return array|WP_Error
	 */
	public static function build(
		$booking_id
	) {
		$booking_id =
			absint( $booking_id );

		if ( ! $booking_id ) {
			return new WP_Error(
				'tutorhelper_booking_email_invalid_booking',
				__(
					'The booking could not be prepared for email.',
					'tutorhelper-bookings'
				)
			);
		}

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

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

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

		if ( ! $student instanceof WP_User ) {
			return new WP_Error(
				'tutorhelper_booking_email_student_missing',
				__(
					'The student account could not be found.',
					'tutorhelper-bookings'
				)
			);
		}

		$tutor =
			get_user_by(
				'id',
				absint(
					$booking->tutor_user_id
				)
			);

		if ( ! $tutor instanceof WP_User ) {
			return new WP_Error(
				'tutorhelper_booking_email_tutor_missing',
				__(
					'The tutor account could not be found.',
					'tutorhelper-bookings'
				)
			);
		}

		$booking_type =
			TutorHelper_Booking_Types::get_by_id(
				absint(
					$booking->booking_type_id
				)
			);

		$booking_type_title =
			$booking_type
			&& ! empty(
				$booking_type->title
			)
				? sanitize_text_field(
					$booking_type->title
				)
				: __(
					'Lesson',
					'tutorhelper-bookings'
				);

		$dates =
			self::prepare_dates(
				$booking
			);

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

		$calendar_url =
			add_query_arg(
				array(
					'page' =>
						'tutorhelper',

					'tab' =>
						'calendar',
				),
				admin_url(
					'admin.php'
				)
			);

		$student_dashboard_url =
			self::get_student_dashboard_url(
				$booking
			);

		$placeholders = array(
			'{student_name}' =>
				self::get_user_name(
					$student
				),

			'{student_email}' =>
				sanitize_email(
					$student->user_email
				),

			'{tutor_name}' =>
				self::get_user_name(
					$tutor
				),

			'{booking_type}' =>
				$booking_type_title,

			'{lesson_date}' =>
				$dates['date'],

			'{lesson_time}' =>
				$dates['time'],

			'{location_type}' =>
				self::get_location_label(
					isset(
						$booking->location_type
					)
						? $booking->location_type
						: ''
				),

			'{joining_details}' =>
				isset(
					$booking->location_details
				)
					? sanitize_textarea_field(
						$booking->location_details
					)
					: '',

			'{student_notes}' =>
				isset(
					$booking->notes
				)
					? sanitize_textarea_field(
						$booking->notes
					)
					: '',

			'{calendar_url}' =>
				esc_url_raw(
					$calendar_url
				),

			'{student_dashboard_url}' =>
				esc_url_raw(
					$student_dashboard_url
				),

			'{cancellation_reason}' =>
				isset(
					$booking->cancellation_reason
				)
					? sanitize_textarea_field(
						$booking->cancellation_reason
					)
					: '',
		);

		return array(
			'booking' =>
				$booking,

			'student' =>
				$student,

			'tutor' =>
				$tutor,

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

			'tutor_email' =>
				sanitize_email(
					$tutor->user_email
				),

			'placeholders' =>
				$placeholders,
		);
	}

	/**
	 * Prepare the booking date and time for display.
	 *
	 * Booking dates are stored in UTC.
	 *
	 * @param object $booking Booking record.
	 *
	 * @return array|WP_Error
	 */
	private static function prepare_dates(
		$booking
	) {
		if (
			empty(
				$booking->booking_start
			)
			|| empty(
				$booking->booking_end
			)
		) {
			return new WP_Error(
				'tutorhelper_booking_email_dates_missing',
				__(
					'The booking date could not be prepared for email.',
					'tutorhelper-bookings'
				)
			);
		}

		$timezone_name =
			! empty(
				$booking->timezone
			)
				? sanitize_text_field(
					$booking->timezone
				)
				: wp_timezone_string();

		if ( ! $timezone_name ) {
			$timezone_name = 'UTC';
		}

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

			$start =
				new DateTimeImmutable(
					$booking->booking_start,
					new DateTimeZone( 'UTC' )
				);

			$end =
				new DateTimeImmutable(
					$booking->booking_end,
					new DateTimeZone( 'UTC' )
				);

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

			$end =
				$end->setTimezone(
					$timezone
				);
		} catch ( Exception $exception ) {
			return new WP_Error(
				'tutorhelper_booking_email_dates_invalid',
				__(
					'The booking date could not be prepared for email.',
					'tutorhelper-bookings'
				)
			);
		}

		$date =
			wp_date(
				'l j F Y',
				$start->getTimestamp(),
				$timezone
			);

		$time =
			sprintf(
				'%1$s–%2$s',
				wp_date(
					get_option(
						'time_format'
					),
					$start->getTimestamp(),
					$timezone
				),
				wp_date(
					get_option(
						'time_format'
					),
					$end->getTimestamp(),
					$timezone
				)
			);

		return array(
			'date' =>
				$date,

			'time' =>
				$time,
		);
	}

	/**
	 * Return a display name for a WordPress user.
	 *
	 * @param WP_User $user User account.
	 *
	 * @return string
	 */
	private static function get_user_name(
		$user
	) {
		if (
			! $user instanceof WP_User
		) {
			return '';
		}

		$name =
			trim(
				(string) $user->display_name
			);

		if ( '' !== $name ) {
			return sanitize_text_field(
				$name
			);
		}

		return sanitize_text_field(
			$user->user_login
		);
	}

	/**
	 * Return a readable booking location.
	 *
	 * @param string $location_type Stored location type.
	 *
	 * @return string
	 */
	private static function get_location_label(
		$location_type
	) {
		$location_type =
			sanitize_key(
				$location_type
			);

		$labels = array(
			'online' =>
				__(
					'Online',
					'tutorhelper-bookings'
				),

			'phone' =>
				__(
					'Phone',
					'tutorhelper-bookings'
				),

			'in_person' =>
				__(
					'In person',
					'tutorhelper-bookings'
				),

			'custom' =>
				__(
					'Other',
					'tutorhelper-bookings'
				),

			'other' =>
				__(
					'Other',
					'tutorhelper-bookings'
				),
		);

		return isset(
			$labels[ $location_type ]
		)
			? $labels[ $location_type ]
			: __(
				'Not specified',
				'tutorhelper-bookings'
			);
	}

	/**
     * Return the student dashboard URL.
     *
     * @param object $booking Booking record.
     *
     * @return string
     */
    private static function get_student_dashboard_url(
        $booking
    ) {
        $url =
            TutorHelper_Settings::
                get_student_dashboard_url();

        if ( '' === $url ) {
            $url =
                home_url( '/' );
        }

        /**
         * Filters the student dashboard URL used in Booking emails.
         *
         * @param string $url     Dashboard URL.
         * @param object $booking Booking record.
         */
        return apply_filters(
            'tutorhelper_student_dashboard_url',
            $url,
            $booking
        );
    }
    
}
