<?php

namespace SugarCalendarBookings\Notifications;

use SugarCalendarBookings\Appointments\AppointmentModel;
use SugarCalendarBookings\Plugin;
use SugarCalendarBookings\Notifications\Emails\EmailService;

/**
 * Handles notifications for appointment lifecycle events.
 *
 * This class determines which notifications should be sent based on appointment
 * state changes and delegates to appropriate notification channels (email, SMS, etc.).
 *
 * @since 1.0.0
 */
class AppointmentNotifier {

	/**
	 * Send notifications for appointment.
	 *
	 * @since 1.0.0
	 *
	 * @param AppointmentModel $appointment Appointment model.
	 */
	public function notify( $appointment ) {

		// Determine which notification types to send.
		$notification_types = $this->determine_notification_types( $appointment );

		if ( empty( $notification_types ) ) {
			return;
		}

		// Send notifications via email channel.
		// Future: This could be extended to support additional channels (SMS, Slack, push, etc.).
		$this->send_email_notifications( $appointment, $notification_types );
	}

	/**
	 * Send email notifications.
	 *
	 * @since 1.0.0
	 *
	 * @param AppointmentModel $appointment        Appointment model.
	 * @param array            $notification_types Array of notification type slugs.
	 */
	private function send_email_notifications( $appointment, $notification_types ) {

		$email_service = Plugin::get( EmailService::class );

		foreach ( $notification_types as $notification_type ) {
			$email_service->send_email( $notification_type, $appointment );
		}
	}

	/**
	 * Determine which notification types should be sent.
	 *
	 * @since 1.0.0
	 *
	 * @param AppointmentModel $appointment Appointment model.
	 *
	 * @return array Array of notification type slugs.
	 */
	private function determine_notification_types( $appointment ) {

		$previous_status = $appointment->get_previous( 'status' );

		// Cancellation - send cancellation notifications only when status changes to cancelled.
		if ( $appointment->status === AppointmentModel::STATUS_CANCELLED && $previous_status !== AppointmentModel::STATUS_CANCELLED ) {
			return [ 'booking_cancellation_attendee', 'booking_cancellation_employee' ];
		}

		// New appointment - check if previous state was empty OR transitioning from draft (first real notification).
		$previous_values = $appointment->get_previous();
		$is_new          = empty( $previous_values ) || $previous_status === AppointmentModel::STATUS_DRAFT;

		// New pending appointment - send pending notifications.
		if ( $is_new && $appointment->status === AppointmentModel::STATUS_PENDING ) {
			return [ 'booking_pending_attendee', 'booking_pending_employee' ];
		}

		// New approved appointment - send confirmation notifications.
		if ( $is_new && $appointment->status === AppointmentModel::STATUS_APPROVED ) {
			return [ 'booking_confirmation_attendee', 'booking_confirmation_employee' ];
		}

		// Status changed from pending to approved - send confirmation notifications.
		if ( $previous_status === AppointmentModel::STATUS_PENDING && $appointment->status === AppointmentModel::STATUS_APPROVED ) {
			return [ 'booking_confirmation_attendee', 'booking_confirmation_employee' ];
		}

		// Appointment details changed - send update notifications.
		if ( $this->has_significant_changes( $appointment ) ) {
			return [ 'booking_update_attendee', 'booking_update_employee' ];
		}

		return [];
	}

	/**
	 * Check if the appointment has significant changes that warrant sending update notifications.
	 *
	 * @since 1.0.0
	 *
	 * @param AppointmentModel $appointment Appointment model.
	 *
	 * @return bool True if significant changes occurred.
	 */
	private function has_significant_changes( $appointment ) {

		return $appointment->has_changed( 'start_at' ) ||
				$appointment->has_changed( 'end_at' ) ||
				$appointment->has_changed( 'employee_id' ) ||
				$appointment->has_changed( 'service_id' );
	}
}
