<?php
/**
 * Shift4 APM response factory.
 * https://www.credorax.com/
 *
 * @package  flo-checkout
 */

namespace Flo_Checkout\Gateways\Shift4_APM\Responses;

use Exception;
use Flo_Checkout\Gateways\Shift4_APM\Requests\Models\Request_Response_Model;

defined( 'ABSPATH' ) || exit;

/**
 * Credorax Credorax response factory model.
 */
class Response_Factory {

	/**
	 * Response_Factory constructor.
	 */
	public function __construct() {}

	/**
	 * Set of requests.
	 *
	 * @var string[]
	 */
	protected array $invokableClasses = array();

	/**
	 * Add a class to the factory.
	 *
	 * @param string $key Key.
	 * @param string $class_name Class name.
	 */
	public function add_class( string $key, string $class_name ): void {
		$this->invokableClasses[ $key ] = $class_name;
	}

	/**
	 * Get class name for the response model.
	 *
	 * @param Request_Response_Model $request_response_model The request response model.
	 *
	 * @return string
	 * @throws Exception If the response type is not supported or otherwise valid.
	 */
	protected function get_class_name( Request_Response_Model $request_response_model ): string {
		$class_name = $this->invokableClasses[ $request_response_model->get_type() ] ?? null;

		if ( null === $class_name ) {
			throw new Exception( esc_html( $request_response_model->get_type() ) . ' response is not supported.', );
		}

		if ( ! is_subclass_of( $class_name, Abstract_Response::class ) ) {
			throw new Exception(
				esc_html(
					sprintf(
						"%s doesn't implement %s",
						$class_name,
						Abstract_Response::class
					)
				)
			);
		}

		return $class_name;
	}

	/**
	 * Create a response model.
	 *
	 * @param Request_Response_Model $response_model Response data.
	 *
	 * @return Abstract_Response
	 * @throws Exception If the response type is not supported.
	 */
	public function create(
		Request_Response_Model $response_model,
	): Abstract_Response {
		$class_name = $this->get_class_name( $response_model );

		return new $class_name( $response_model );
	}
}
