<?php
/**
 * Mailer factory for creating mailer instances.
 *
 * @package Awesomemotive\Rewardswp\Factories
 * @since 1.0.0
 */

namespace Awesomemotive\Rewardswp\Factories;

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

use Awesomemotive\Rewardswp\Abstracts\AbstractEmailNotification;
use DI\Container;
use Exception;
use function Awesomemotive\Rewardswp\Helpers\str_snake_to_pascal_case;

class MailerFactory {
	/**
	 * Dependency injection container.
	 *
	 * @since 1.0.0
	 *
	 * @var Container
	 */
	private Container $container;

	public function __construct( Container $container ) {
		$this->container = $container;
	}

	/**
	 * Retrieves an instance of a Email object based on the email name.
	 *
	 * Search order: Pro → Base.
	 *
	 * @since 1.0.0
	 *
	 * @param string|AbstractEmailNotification $name_or_class The snake_case name of the Email or the class name.
	 * @return AbstractEmailNotification|null                 The Email object instance, or null if not found.
	 */
	function get_mailer( $name_or_class ): ?AbstractEmailNotification {
		try {
			// Check if it is the class name, if so, return right away.
			if ( class_exists( $name_or_class ) && is_subclass_of( $name_or_class, AbstractEmailNotification::class ) ) {
				return $this->container->get( $name_or_class );
			}

			// Convert snake_case name to PascalCase class name.
			$email_class_name = sprintf( '%sEmail', str_snake_to_pascal_case( rtrim( $name_or_class, 'email' ) ) );

			// Try Pro version first (if not Lite plan).
			if ( ! \Awesomemotive\Rewardswp\Helpers\is_rewardswp_lite_plan() ) {
				$pro_class = 'Awesomemotive\\Rewardswp\\Pro\\Notifications\\Emails\\' . $email_class_name;
				if ( class_exists( $pro_class ) && is_subclass_of( $pro_class, AbstractEmailNotification::class ) ) {
					return $this->container->get( $pro_class );
				}
			}

			// Try base email (standard location).
			$base_class = 'Awesomemotive\\Rewardswp\\Notifications\\Emails\\' . $email_class_name;
			if ( class_exists( $base_class ) && is_subclass_of( $base_class, AbstractEmailNotification::class ) ) {
				return $this->container->get( $base_class );
			}

			return null;
		} catch ( Exception $exception ) {
			return null;
		}
	}
}
