<?php
/**
 * Student booking front-end AJAX actions.
 *
 * @package TutorHelper_Bookings
 */

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

/**
 * Supplies public booking-form calendar data.
 */
final class TutorHelper_Student_Booking_Ajax {

	/**
	 * AJAX action for available dates.
	 *
	 * @var string
	 */
	const ACTION_DATES =
		'tutorhelper_student_booking_dates';

	/**
	 * Nonce action.
	 *
	 * @var string
	 */
	const NONCE_ACTION =
		'tutorhelper_student_booking';

    
    /**
     * AJAX action for available times.
     *
     * @var string
     */
    const ACTION_TIMES =
        'tutorhelper_student_booking_times';
        
    
    /**
     * AJAX action for submitting a lesson request.
     *
     * @var string
     */
    const ACTION_SUBMIT =
        'tutorhelper_student_booking_submit';

	/**
	 * Register AJAX actions.
	 *
	 * @return void
	 */
	public static function init() {
		add_action(
			'wp_ajax_' . self::ACTION_DATES,
			array(
				__CLASS__,
				'get_available_dates',
			)
		);

        add_action(
            'wp_ajax_' . self::ACTION_TIMES,
            array(
                __CLASS__,
                'get_available_times',
            )
        );

        add_action(
            'wp_ajax_' . self::ACTION_SUBMIT,
            array(
                __CLASS__,
                'submit_request',
            )
        );

	}


    /**
     * Return available times for a Booking Type and date.
     *
     * @return void
     */
    public static function get_available_times() {
        check_ajax_referer(
            self::NONCE_ACTION,
            'nonce'
        );

        if ( ! is_user_logged_in() ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'Please log in to view lesson availability.',
                        'tutorhelper-bookings'
                    ),
                ),
                401
            );
        }

        $current_user_id =
            get_current_user_id();

        $is_student =
            TutorHelper_Students::get_student(
                $current_user_id
            ) instanceof WP_User;

        $is_preview =
            current_user_can(
                'manage_options'
            );

        if (
            ! $is_student
            && ! $is_preview
        ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'You cannot view lesson availability.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

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

        $date =
            isset( $_POST['date'] )
                ? sanitize_text_field(
                    wp_unslash(
                        $_POST['date']
                    )
                )
                : '';
        
        $booking_type =
            TutorHelper_Booking_Types::get_by_id(
                $booking_type_id
            );

        if (
            ! $booking_type
            || ! TutorHelper_Student_Booking_Access::
                can_book(
                    $booking_type,
                    $is_student
                        ? $current_user_id
                        : 0
                )
        ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'The selected service is not available.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

        $tutor_user_id =
            TutorHelper_Booking_Tutor_Resolver::
                resolve(
                    $is_student
                        ? $current_user_id
                        : 0,
                    $booking_type_id
                );

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

        $slots =
            TutorHelper_Student_Booking_Slots::
                get_for_date(
                    $tutor_user_id,
                    $booking_type_id,
                    $date
                );

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

        wp_send_json_success(
            array(
                'date' =>
                    $date,

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



	/**
	 * Return available dates for one Booking Type and month.
	 *
	 * @return void
	 */
	public static function get_available_dates() {
		check_ajax_referer(
			self::NONCE_ACTION,
			'nonce'
		);

		if ( ! is_user_logged_in() ) {
			wp_send_json_error(
				array(
					'message' => __(
						'Please log in to view lesson availability.',
						'tutorhelper-bookings'
					),
				),
				401
			);
		}

		$current_user_id =
			get_current_user_id();

		$is_student =
			TutorHelper_Students::get_student(
				$current_user_id
			) instanceof WP_User;

		$is_preview =
			current_user_can(
				'manage_options'
			);

		if (
			! $is_student
			&& ! $is_preview
		) {
			wp_send_json_error(
				array(
					'message' => __(
						'You cannot view lesson availability.',
						'tutorhelper-bookings'
					),
				),
				403
			);
		}

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

		$month = isset(
			$_POST['month']
		)
			? sanitize_text_field(
				wp_unslash(
					$_POST['month']
				)
			)
			: '';

		$booking_type =
            TutorHelper_Booking_Types::get_by_id(
                $booking_type_id
            );

        if (
            ! $booking_type
            || ! TutorHelper_Student_Booking_Access::
                can_book(
                    $booking_type,
                    $is_student
                        ? $current_user_id
                        : 0
                )
        ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'The selected service is not available.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

		$month_date =
			DateTimeImmutable::createFromFormat(
				'!Y-m',
				$month,
				wp_timezone()
			);

		$errors =
			DateTimeImmutable::getLastErrors();

		if (
			false === $month_date
			|| (
				is_array( $errors )
				&& (
					0 < $errors['warning_count']
					|| 0 < $errors['error_count']
				)
			)
			|| $month_date->format( 'Y-m' )
				!== $month
		) {
			wp_send_json_error(
				array(
					'message' => __(
						'The requested calendar month is invalid.',
						'tutorhelper-bookings'
					),
				),
				400
			);
		}

		$range_start =
			$month_date->format(
				'Y-m-01'
			);

		$range_end =
			$month_date
				->modify(
					'last day of this month'
				)
				->format(
					'Y-m-d'
				);

		$tutor_user_id =
			TutorHelper_Booking_Tutor_Resolver::
				resolve(
					$is_student
						? $current_user_id
						: 0,
					$booking_type_id
				);

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

		$calendar =
			TutorHelper_Availability_Calendar::
				get_range(
					$tutor_user_id,
					$range_start,
					$range_end
				);

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

		$days = isset(
			$calendar['days']
		)
			&& is_array(
				$calendar['days']
			)
				? $calendar['days']
				: array();

		$today =
			current_time(
				'Y-m-d'
			);

		$available_dates = array();

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

			$date =
				sanitize_text_field(
					$day['date']
				);

			if ( $date < $today ) {
				continue;
			}

			$slots =
                TutorHelper_Student_Booking_Slots::
                    get_for_date(
                        $tutor_user_id,
                        $booking_type_id,
                        $date
                    );

            if (
                is_wp_error( $slots )
                || empty( $slots )
            ) {
                continue;
            }

            $available_dates[] =
                $date;
		}

		wp_send_json_success(
			array(
				'month' =>
					$month,

				'range_start' =>
					$range_start,

				'range_end' =>
					$range_end,

				'available_dates' =>
					array_values(
						array_unique(
							$available_dates
						)
					),
			)
		);
	}

	/**
	 * Determine whether a calendar day offers a Booking Type.
	 *
	 * An empty allowed Booking Type list means the availability rule is
	 * not restricted to particular Booking Types.
	 *
	 * @param array $day             Calendar day.
	 * @param int   $booking_type_id Booking Type ID.
	 *
	 * @return bool
	 */
	private static function day_supports_booking_type(
		$day,
		$booking_type_id
	) {
		if (
			empty( $day['availability'] )
			|| ! is_array(
				$day['availability']
			)
		) {
			return false;
		}

		foreach (
			$day['availability']
				as $availability
		) {
			if ( ! is_array( $availability ) ) {
				continue;
			}

			$allowed_ids = isset(
				$availability[
					'allowed_booking_type_ids'
				]
			)
				&& is_array(
					$availability[
						'allowed_booking_type_ids'
					]
				)
					? array_values(
						array_filter(
							array_map(
								'absint',
								$availability[
									'allowed_booking_type_ids'
								]
							)
						)
					)
					: array();

			if (
				empty( $allowed_ids )
				|| in_array(
					absint(
						$booking_type_id
					),
					$allowed_ids,
					true
				)
			) {
				return true;
			}
		}

		return false;
	}


    /**
     * Submit one student lesson request.
     *
     * @return void
     */
    public static function submit_request() {
        check_ajax_referer(
            self::NONCE_ACTION,
            'nonce'
        );

        if ( ! is_user_logged_in() ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'Please log in to request a lesson.',
                        'tutorhelper-bookings'
                    ),
                ),
                401
            );
        }

        $current_user_id =
            get_current_user_id();

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

        if ( ! $student instanceof WP_User ) {
            wp_send_json_error(
                array(
                    'message' => __(
                        'Only registered students can request lessons.',
                        'tutorhelper-bookings'
                    ),
                ),
                403
            );
        }

        $result =
            TutorHelper_Student_Booking_Request::
                create(
                    array(
                        'booking_type_id' =>
                            isset(
                                $_POST[
                                    'booking_type_id'
                                ]
                            )
                                ? absint(
                                    wp_unslash(
                                        $_POST[
                                            'booking_type_id'
                                        ]
                                    )
                                )
                                : 0,

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

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

                        'timezone' =>
                            isset(
                                $_POST['timezone']
                            )
                                ? sanitize_text_field(
                                    wp_unslash(
                                        $_POST[
                                            'timezone'
                                        ]
                                    )
                                )
                                : wp_timezone()
                                    ->getName(),

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

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

        if ( is_wp_error( $result ) ) {
            wp_send_json_error(
                array(
                    'message' =>
                        $result
                            ->get_error_message(),

                    'code' =>
                        $result
                            ->get_error_code(),
                ),
                400
            );
        }

        wp_send_json_success(
            array(
                'booking_id' =>
                    absint(
                        $result['booking_id']
                    ),

                'status' =>
                    sanitize_key(
                        $result['status']
                    ),

                'message' => __(
                    'Your lesson request has been sent to your tutor for confirmation.',
                    'tutorhelper-bookings'
                ),
            )
        );
    }

}
