<?php
/**
 * Provider Factory
 *
 * Factory class to create integration provider instances.
 *
 * @package SureForms
 * @since 1.13.0
 */

namespace SRFM_Pro\Inc\Pro\Native_Integrations;

use SRFM\Inc\Helper;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Provider Factory class.
 *
 * @since 1.13.0
 */
class Provider_Factory {
	/**
	 * Provider instances cache
	 *
	 * @var array
	 * @since 1.13.0
	 */
	private static $instances = [];

	/**
	 * Integrations that require specific provider implementations
	 *
	 * @var array
	 * @since 1.13.0
	 */
	private static $specific_providers = [];

	/**
	 * Create provider instance
	 *
	 * @param string $provider_type Provider type (e.g., 'mailchimp').
	 * @param array  $config Provider configuration.
	 * @return object|null Provider instance or null if creation fails.
	 * @since 1.13.0
	 */
	public static function create( $provider_type, $config = [] ) {
		// Return cached instance if available.
		$cache_key = $provider_type . '_' . md5( Helper::get_string_value( wp_json_encode( $config ) ) );
		if ( isset( self::$instances[ $cache_key ] ) ) {
			return self::$instances[ $cache_key ];
		}

		// Check if config explicitly specifies a provider type.
		$explicit_provider = isset( $config['provider'] ) ? Helper::get_string_value( $config['provider'] ) : '';

		$provider = null;

		switch ( $explicit_provider ) {
			case 'wordpress': // phpcs:ignore WordPress.WP.CapitalPDangit.Misspelled -- Configuration uses lowercase.
				// Use WordPress plugin provider.
				$provider = new WordPress_Provider( $provider_type, $config );
				break;

			case 'generic':
				// Explicitly use generic provider.
				$provider = new Generic_Provider( $provider_type, $config );
				break;

			default:
				// Check if it's a plugin integration based on config.
				if ( isset( $config['plugin_detection'] ) ) {
					$provider = new WordPress_Provider( $provider_type, $config );
				} elseif ( self::has_specific_provider( $provider_type ) ) {
					// Check if specific provider exists for this type.
					$provider = self::create_specific_provider( $provider_type, $config );
				}

				// Fallback to generic provider if no specific provider or creation failed.
				if ( ! $provider ) {
					$provider = new Generic_Provider( $provider_type, $config );
				}
				break;
		}

		// Cache the instance if creation was successful.
		if ( $provider ) {
			self::$instances[ $cache_key ] = $provider;
		}

		return $provider;
	}

	/**
	 * Get provider type from integration name
	 *
	 * @param string $integration_name Integration name (e.g., 'Mailchimp').
	 * @return string Provider type (e.g., 'mailchimp').
	 * @since 1.13.0
	 */
	public static function get_provider_type( $integration_name ) {
		return sanitize_key( strtolower( $integration_name ) );
	}

	/**
	 * Check if provider type has a specific implementation
	 *
	 * @param string $provider_type Provider type.
	 * @return bool True if specific provider exists.
	 * @since 1.13.0
	 */
	private static function has_specific_provider( $provider_type ) {
		return in_array( $provider_type, self::$specific_providers, true );
	}

	/**
	 * Create specific provider instance
	 *
	 * @param string $provider_type Provider type.
	 * @param array  $config Provider configuration.
	 * @return object It should return null instead of Generic Provider Instance in the future if specific provider is not implemented.
	 * @since 1.13.0
	 */
	private static function create_specific_provider( $provider_type, $config ) {
		switch ( $provider_type ) {
			default:
				return new Generic_Provider( $provider_type, $config );
		}
	}

}
