<?php
/**
 * Abstract request model.
 *
 * @package flo-checkout
 */

namespace Flo_Checkout\Gateways\Shift4_APM\Requests;

use Exception;
use Flo_Checkout\Gateways\Shift4_APM\Abstract_APM_Gateway;
use Flo_Checkout\Gateways\Shift4_APM\Requests\Models\Gateway_Request_Response_Model;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Abstract_Response;
use Flo_Checkout\Gateways\Shift4_APM\Traits\Gateway_Request_And_Response_Logger_Trait;
use WC_Order;

defined( 'ABSPATH' ) || exit;

/**
 * Abstract request model.
 */
abstract class Abstract_Request_Gateway extends Abstract_Request {
	use Gateway_Request_And_Response_Logger_Trait;

	/**
	 * Request body.
	 *
	 * @var string
	 */
	protected string $request_body;

	/**
	 * Request response.
	 *
	 * @var Gateway_Request_Response_Model
	 */
	private Gateway_Request_Response_Model $gateway_request_response_model;

	/**
	 * Abstract_Request constructor.
	 *
	 * @param Abstract_APM_Gateway $gateway The gateway instance.
	 * @param WC_Order|null        $order   Order object.
	 */
	public function __construct(
		protected Abstract_APM_Gateway $gateway,
		protected ?WC_Order $order = null,
	) {
		parent::__construct(
			$this->gateway->response_factory,
		);
	}

	/**
	 * Return proper response handler.
	 *
	 * @return Abstract_Response
	 * @throws Exception If creation fails.
	 */
	protected function get_response_handler(): Abstract_Response {
		return $this->gateway->response_factory->create(
			$this->get_response_data(),
			$this->order
		);
	}

	/**
	 * Handle request response.
	 *
	 * @param string $request_url Request URL.
	 * @param array  $response    Request response.
	 *
	 * @return void
	 */
	protected function handle_response( string $request_url, array $response ): void {
		$this->request_response_model = new Gateway_Request_Response_Model(
			$this->gateway,
			$this->get_response_handler_type(),
			wp_remote_retrieve_body( $response ),
			wp_remote_retrieve_response_code( $response ),
			wp_remote_retrieve_headers( $response ),
			$request_url,
			$this->get_request_method()->name,
		);
	}
}
