<?php

namespace SugarCalendarBookings\Notifications;

use SugarCalendarBookings\Appointments\AppointmentModel;
use SugarCalendarBookings\Notifications\Emails\EmailService;
use SugarCalendarBookings\Payments\PaymentModel;
use SugarCalendarBookings\Payments\PaymentsHelpers;
use SugarCalendarBookings\Plugin;

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

	/**
	 * Send notifications for payment status changes.
	 *
	 * @since 1.1.0
	 *
	 * @param PaymentModel|PaymentModel[] $payment         Payment model or array of payment models.
	 * @param string                      $previous_status Previous payment status.
	 */
	public function notify( $payment, $previous_status ) {

		// Handle array of payments.
		if ( is_array( $payment ) ) {
			foreach ( $payment as $single_payment ) {
				if ( $single_payment instanceof PaymentModel ) {
					$this->notify( $single_payment, $previous_status );
				}
			}

			return;
		}

		// Handle single payment.
		if ( ! $payment instanceof PaymentModel ) {
			return;
		}

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

		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( $payment, $notification_types );
	}

	/**
	 * Send email notifications.
	 *
	 * @since 1.1.0
	 *
	 * @param PaymentModel $payment            Payment model.
	 * @param array        $notification_types Array of notification type slugs.
	 */
	private function send_email_notifications( $payment, $notification_types ) {

		// Get the appointment associated with the payment.
		if ( empty( $payment->appointments ) || ! is_array( $payment->appointments ) ) {
			return;
		}

		$appointment = array_values( $payment->appointments )[0];

		if ( ! $appointment ) {
			return;
		}

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

		foreach ( $notification_types as $notification_type ) {
			$additional_vars = $this->prepare_refund_email_vars( $payment );

			$email_service->send_email( $notification_type, $appointment, $additional_vars );
		}
	}

	/**
	 * Determine which notification types should be sent.
	 *
	 * @since 1.1.0
	 *
	 * @param PaymentModel $payment         Payment model.
	 * @param string       $previous_status Previous payment status.
	 *
	 * @return array Array of notification type slugs.
	 */
	private function determine_notification_types( $payment, $previous_status ) {

		// Refund - send refund notification when status changes to refunded.
		if ( $previous_status !== PaymentModel::STATUS_REFUNDED && $payment->status === PaymentModel::STATUS_REFUNDED ) {
			return [ 'payment_refund_attendee' ];
		}

		// Future: Add more payment notification types here (e.g., payment_completed, payment_failed, etc.).

		return [];
	}

	/**
	 * Prepare additional variables for refund email.
	 *
	 * @since 1.1.0
	 *
	 * @param PaymentModel $payment Payment model.
	 *
	 * @return array Additional variables for refund email.
	 */
	public function prepare_refund_email_vars( $payment ) {

		// Keys must be braced so they override the defaults in EmailService::prepare_email_data().
		return [
			'{refund_amount}'   => PaymentsHelpers::format_currency( $payment->total_amount ),
			'{payment_gateway}' => PaymentsHelpers::get_payment_gateway_display_name( $payment ),
		];
	}
}
