<?php
/**
 * Booking email event handling.
 *
 * @package TutorHelper_Bookings
 */

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

/**
 * Sends Booking emails in response to booking events.
 */
final class TutorHelper_Booking_Email_Events {

	/**
	 * Initialise Booking email hooks.
	 *
	 * @return void
	 */
	public static function init() {
		add_action(
			'tutorhelper_booking_created',
			array(
				__CLASS__,
				'handle_booking_created',
			),
			20,
			3
		);

        add_action(
            'tutorhelper_booking_updated',
            array(
                __CLASS__,
                'handle_booking_updated',
            ),
            20,
            3
        );

        add_action(
            'tutorhelper_booking_cancelled',
            array(
                __CLASS__,
                'handle_booking_cancelled',
            ),
            20,
            4
        );
	}

	/**
	 * Handle a newly created booking.
	 *
	 * Core sends request emails only for student-created,
	 * unconfirmed lesson requests.
	 *
	 * @param int   $booking_id      Booking ID.
	 * @param array $insert_data     Stored booking data.
	 * @param int   $duration_minutes Booking duration.
	 *
	 * @return void
	 */
	public static function handle_booking_created(
		$booking_id,
		$insert_data,
		$duration_minutes
	) {
		unset( $duration_minutes );

		$booking_id =
			absint( $booking_id );

		if (
			! $booking_id
			|| ! is_array(
				$insert_data
			)
		) {
			return;
		}

		$source =
			isset(
				$insert_data['source']
			)
				? sanitize_key(
					$insert_data['source']
				)
				: '';

		$status =
			isset(
				$insert_data['status']
			)
				? sanitize_key(
					$insert_data['status']
				)
				: '';

		/*
        * A tutor-created booking may be confirmed immediately.
        * Send the normal student confirmation in that case.
        */
        if (
            TutorHelper_Booking_Records::
                STATUS_CONFIRMED
            === $status
        ) {

            /**
             * Filters whether the normal student confirmation
             * email should be sent for a newly created booking.
             *
             * Extensions may suppress the individual email when
             * bookings are being created as part of a larger
             * workflow, such as a booking series.
             *
             * @param bool  $send_confirmation Whether to send.
             * @param int   $booking_id        Booking ID.
             * @param array $insert_data       Stored booking data.
             */
            $send_confirmation =
                (bool) apply_filters(
                    'tutorhelper_booking_send_student_confirmation',
                    true,
                    $booking_id,
                    $insert_data
                );

            if ( ! $send_confirmation ) {
                return;
            }
            

            $context =
                TutorHelper_Booking_Email_Context::
                    build(
                        $booking_id
                    );

            if ( is_wp_error( $context ) ) {
                self::log_warning(
                    'Booking confirmation email could not be prepared.',
                    array(
                        'booking_id' =>
                            $booking_id,

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

                return;
            }

            

            self::send_student_confirmation_email(
                $booking_id,
                $context
            );

            return;
        }

        /*
        * Core request emails apply only to student-created,
        * unconfirmed lesson requests.
        */
        if (
            TutorHelper_Booking_Records::
                SOURCE_STUDENT
            !== $source
            || TutorHelper_Booking_Records::
                STATUS_UNCONFIRMED
            !== $status
        ) {
            return;
        }

		$context =
			TutorHelper_Booking_Email_Context::
				build(
					$booking_id
				);

		if ( is_wp_error( $context ) ) {
			self::log_warning(
				'Booking request emails could not be prepared.',
				array(
					'booking_id' =>
						$booking_id,

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

			return;
		}

		self::send_tutor_request_email(
			$booking_id,
			$context
		);

		self::send_student_request_email(
			$booking_id,
			$context
		);
	}

    /**
     * Handle an updated booking.
     *
     * The confirmation email is sent only when the booking changes
     * from another status into Confirmed.
     *
     * @param int    $booking_id Booking ID.
     * @param object $updated    Booking after the update.
     * @param object $existing   Booking before the update.
     *
     * @return void
     */
    public static function handle_booking_updated(
        $booking_id,
        $updated,
        $existing
    ) {
        $booking_id =
            absint( $booking_id );

        if (
            ! $booking_id
            || ! is_object( $updated )
            || ! is_object( $existing )
        ) {
            return;
        }

        $previous_status =
            isset( $existing->status )
                ? sanitize_key(
                    $existing->status
                )
                : '';

        $new_status =
            isset( $updated->status )
                ? sanitize_key(
                    $updated->status
                )
                : '';

        /*
        * Editing the date, time, location or notes on an already-confirmed
        * booking must not send another confirmation email.
        */
        if (
            TutorHelper_Booking_Records::
                STATUS_CONFIRMED
            !== $new_status
            || TutorHelper_Booking_Records::
                STATUS_CONFIRMED
            === $previous_status
        ) {
            return;
        }

        $context =
            TutorHelper_Booking_Email_Context::
                build(
                    $booking_id
                );

        if ( is_wp_error( $context ) ) {
            self::log_warning(
                'Booking confirmation email could not be prepared.',
                array(
                    'booking_id' =>
                        $booking_id,

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

            return;
        }

        self::send_student_confirmation_email(
            $booking_id,
            $context
        );
    }

    /**
     * Send the student's booking confirmation.
     *
     * @param int   $booking_id Booking ID.
     * @param array $context    Prepared Booking email context.
     *
     * @return void
     */
    private static function send_student_confirmation_email(
        $booking_id,
        $context
    ) {
        $template_key =
            TutorHelper_Booking_Email_Templates::
                STUDENT_BOOKING_CONFIRMED;

        if (
            ! TutorHelper_Email_Templates::
                is_enabled(
                    $template_key
                )
        ) {
            return;
        }

        $result =
            TutorHelper_Email_Sender::send(
                $template_key,
                $context[
                    'student_email'
                ],
                $context[
                    'placeholders'
                ],
                array(
                    'reply_to_email' =>
                        $context[
                            'tutor_email'
                        ],

                    'reply_to_name' =>
                        $context[
                            'placeholders'
                        ][
                            '{tutor_name}'
                        ],

                    'context' =>
                        array(
                            'booking_id' =>
                                $booking_id,

                            'email_type' =>
                                'student_booking_confirmed',
                        ),
                )
            );

        if ( is_wp_error( $result ) ) {
            self::log_warning(
                'Student booking confirmation email was not sent.',
                array(
                    'booking_id' =>
                        $booking_id,

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



	/**
	 * Send the tutor's new-request notification.
	 *
	 * @param int   $booking_id Booking ID.
	 * @param array $context    Prepared Booking email context.
	 *
	 * @return void
	 */
	private static function send_tutor_request_email(
		$booking_id,
		$context
	) {
		$template_key =
			TutorHelper_Booking_Email_Templates::
				STUDENT_REQUEST_TUTOR;

		if (
			! TutorHelper_Email_Templates::
				is_enabled(
					$template_key
				)
		) {
			return;
		}

		$result =
			TutorHelper_Email_Sender::send(
				$template_key,
				$context[
					'tutor_email'
				],
				$context[
					'placeholders'
				],
				array(
					'reply_to_email' =>
						$context[
							'student_email'
						],

					'reply_to_name' =>
						$context[
							'placeholders'
						][
							'{student_name}'
						],

					'context' =>
						array(
							'booking_id' =>
								$booking_id,

							'email_type' =>
								'student_request_tutor',
						),
				)
			);

		if ( is_wp_error( $result ) ) {
			self::log_warning(
				'Tutor booking request email was not sent.',
				array(
					'booking_id' =>
						$booking_id,

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

	/**
	 * Send the student's request acknowledgement.
	 *
	 * @param int   $booking_id Booking ID.
	 * @param array $context    Prepared Booking email context.
	 *
	 * @return void
	 */
	private static function send_student_request_email(
		$booking_id,
		$context
	) {
		$template_key =
			TutorHelper_Booking_Email_Templates::
				STUDENT_REQUEST_RECEIVED;

		if (
			! TutorHelper_Email_Templates::
				is_enabled(
					$template_key
				)
		) {
			return;
		}

		$result =
			TutorHelper_Email_Sender::send(
				$template_key,
				$context[
					'student_email'
				],
				$context[
					'placeholders'
				],
				array(
					'reply_to_email' =>
						$context[
							'tutor_email'
						],

					'reply_to_name' =>
						$context[
							'placeholders'
						][
							'{tutor_name}'
						],

					'context' =>
						array(
							'booking_id' =>
								$booking_id,

							'email_type' =>
								'student_request_received',
						),
				)
			);

		if ( is_wp_error( $result ) ) {
			self::log_warning(
				'Student booking request acknowledgement was not sent.',
				array(
					'booking_id' =>
						$booking_id,

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



    /**
     * Handle a cancelled booking.
     *
     * @param int    $booking_id Booking ID.
     * @param object $updated    Cancelled booking record.
     * @param object $existing   Record before cancellation.
     *
     * @return void
     */
    public static function handle_booking_cancelled(
        $booking_id,
        $updated,
        $existing,
        $cancelled_by
    ) {
        unset( $updated, $existing );

        $cancelled_by =
            sanitize_key(
                $cancelled_by
            );

        $booking_id =
            absint( $booking_id );

        if ( ! $booking_id ) {
            return;
        }

        $context =
            TutorHelper_Booking_Email_Context::
                build(
                    $booking_id
                );

        if ( is_wp_error( $context ) ) {
            self::log_warning(
                'Booking cancellation email could not be prepared.',
                array(
                    'booking_id' =>
                        $booking_id,

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

            return;
        }

        self::send_student_cancellation_email(
            $booking_id,
            $context
        );

        if ( 'student' === $cancelled_by ) {
            self::send_tutor_student_cancellation_email(
                $booking_id,
                $context
            );
        }
    }


    /**
     * Send the student's cancellation notification.
     *
     * @param int   $booking_id Booking ID.
     * @param array $context    Prepared Booking email context.
     *
     * @return void
     */
    private static function send_student_cancellation_email(
        $booking_id,
        $context
    ) {
        $template_key =
            TutorHelper_Booking_Email_Templates::
                STUDENT_BOOKING_CANCELLED;

        if (
            ! TutorHelper_Email_Templates::
                is_enabled(
                    $template_key
                )
        ) {
            return;
        }

        $result =
            TutorHelper_Email_Sender::send(
                $template_key,
                $context[
                    'student_email'
                ],
                $context[
                    'placeholders'
                ],
                array(
                    'reply_to_email' =>
                        $context[
                            'tutor_email'
                        ],

                    'reply_to_name' =>
                        $context[
                            'placeholders'
                        ][
                            '{tutor_name}'
                        ],

                    'context' =>
                        array(
                            'booking_id' =>
                                $booking_id,

                            'email_type' =>
                                'student_booking_cancelled',
                        ),
                )
            );

        if ( is_wp_error( $result ) ) {
            self::log_warning(
                'Student booking cancellation email was not sent.',
                array(
                    'booking_id' =>
                        $booking_id,

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


    /**
     * Notify the tutor when a student cancels a lesson.
     *
     * @param int   $booking_id Booking ID.
     * @param array $context    Prepared Booking email context.
     *
     * @return void
     */
    private static function send_tutor_student_cancellation_email(
        $booking_id,
        $context
    ) {
        $template_key =
            TutorHelper_Booking_Email_Templates::
                STUDENT_CANCELLED_TUTOR;

        if (
            ! TutorHelper_Email_Templates::
                is_enabled(
                    $template_key
                )
        ) {
            return;
        }

        $result =
            TutorHelper_Email_Sender::send(
                $template_key,
                $context[
                    'tutor_email'
                ],
                $context[
                    'placeholders'
                ],
                array(
                    'reply_to_email' =>
                        $context[
                            'student_email'
                        ],

                    'reply_to_name' =>
                        $context[
                            'placeholders'
                        ][
                            '{student_name}'
                        ],

                    'context' =>
                        array(
                            'booking_id' =>
                                $booking_id,

                            'email_type' =>
                                'student_cancelled_tutor',
                        ),
                )
            );

        if ( is_wp_error( $result ) ) {
            self::log_warning(
                'Tutor student-cancellation email was not sent.',
                array(
                    'booking_id' =>
                        $booking_id,

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



	/**
	 * Log a non-fatal Booking email warning.
	 *
	 * Booking creation must never fail simply because an email could not
	 * be prepared or delivered.
	 *
	 * @param string $message Log message.
	 * @param array  $context Log context.
	 *
	 * @return void
	 */
	private static function log_warning(
		$message,
		$context = array()
	) {
		if (
			class_exists(
				'TutorHelper_Logger'
			)
			&& method_exists(
				'TutorHelper_Logger',
				'warning'
			)
		) {
			TutorHelper_Logger::warning(
				$message,
				is_array( $context )
					? $context
					: array()
			);
		}
	}
}
