<?php
/**
 * Model of the Payment Response.
 *
 * @package flo-checkout
 *
 * @phpcs:disable Squiz.Commenting.FunctionComment.MissingParamTag
 */

namespace Flo_Checkout\Gateways\Shift4_APM\Responses\Models;

use Flo_Checkout\Gateways\Apple_Pay\Settings;
use Flo_Checkout\Gateways\Shift4_APM\Enums\Payment_Method;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Models\Payment\Amount_Model;
use Flo_Checkout\Gateways\Shift4_APM\Models\Link_Model;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Models\Payment\Merchant_Info_Model;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Models\Payment\Payment_Details_Model;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Models\Payment\Result_Model_Gateway_Payment;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Models\Payment\Routing_Model;
use Flo_Checkout\Gateways\Shift4_APM\Responses\Models\Payment\Shopper_Info_Model;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Interfaces\JsonUnserializable;
use Northmill_Online_Shared_Checkout\Northmill_Online_Shared\Traits\Json_Decode_Trait;

defined( 'ABSPATH' ) || exit;

/**
 * Class Payment_Response_Model
 */
class Payment_Response_Model implements JsonUnserializable {
	use Json_Decode_Trait;

	/**
	 * The Shift4-generated Payment ID. Payment_id aggregates several transaction_ids.
	 *
	 * @var string
	 */
	public string $payment_id;

	/**
	 * The Shift4-generated Transaction ID. Each request results in a unique transaction_id.
	 *
	 * @var string
	 */
	public string $transaction_id;

	/**
	 * An echo of the unique transaction_id that the merchant had transmitted to Shift4 when creating the payment request.
	 *
	 * @var string
	 */
	public string $request_id;

	/**
	 * Payment Processor Transaction ID. The unique transaction_id created by the Payment Processor.
	 *
	 * @var string
	 */
	public string $pr_transaction_id;

	/**
	 * Selected payment method.
	 *
	 * @var Payment_Method
	 */
	public Payment_Method $payment_method;

	/**
	 * Selected payment method in API string format
	 *
	 * @var string
	 */
	public string $payment_method_api;

	/**
	 * One of:
	 * - 'Sale'
	 * - 'Authorisation'
	 * - 'Capture'
	 * - 'Void'
	 * - 'Refund'
	 * - 'Re-Authorisation'
	 *
	 * @var string
	 */
	public string $operation;

	/**
	 * From format 'dd-MM-yy HH:mm:ss:SSS' in UTC
	 *
	 * @var string
	 */
	public string $transaction_time;

	/**
	 * Links related to the payment.
	 *
	 * @var Link_Model[]
	 */
	public array $links;

	/**
	 * Amount of the payment.
	 *
	 * @var Amount_Model
	 */
	public Amount_Model $amount;

	/**
	 * Payment details.
	 *
	 * @var Payment_Details_Model
	 */
	public Payment_Details_Model $payment_details;

	/**
	 * Routing information.
	 *
	 * @var Routing_Model
	 */
	public Routing_Model $routing;

	/**
	 * Shopper information.
	 *
	 * @var Shopper_Info_Model
	 */
	public Shopper_Info_Model $shopper_info;

	/**
	 * Merchant information.
	 *
	 * @var Merchant_Info_Model
	 */
	public Merchant_Info_Model $merchant_info;

	/**
	 * Result model.
	 *
	 * @var Result_Model_Gateway_Payment
	 */
	public Result_Model_Gateway_Payment $result;

	/**
	 * Payment_Response_Model constructor.
	 *
	 * @param Result_Model $result The result model.
	 */
	public function __construct( Result_Model $result ) {
		$result_body = $result->get_response_body();

		$this->payment_id         = $result_body['payment_id'];
		$this->transaction_id     = $result_body['transaction_id'];
		$this->request_id         = $result_body['request_id'];
		$this->pr_transaction_id  = $result_body['pr_transaction_id'];
		$this->payment_method_api = $result_body['payment_method'];
		$this->payment_method     = Payment_Method::from_api_string( $this->payment_method_api );
		$this->operation          = $result_body['operation'];
		$this->transaction_time   = $result_body['transaction_time'];

		$this->amount          = new Amount_Model( $result_body['amount'] );
		$this->payment_details = new Payment_Details_Model( $result_body['payment_details'] );
		$this->routing         = new Routing_Model( $result_body['routing'] );
		$this->shopper_info    = new Shopper_Info_Model( $result_body['shopper_info'] );
		$this->merchant_info   = new Merchant_Info_Model( $result_body['merchant_info'] );
		$this->result          = new Result_Model_Gateway_Payment( $result_body );

		if ( ! empty( $result_body['links'] ) ) {
			$this->links = array_map(
				function ( $link ) {
					return new Link_Model( $link );
				},
				$result_body['links']
			);
		} else {
			$this->links = array();
		}
	}

	/**
	 * Get the refund href.
	 *
	 * @return Link_Model|null
	 */
	public function get_refund_link(): ?Link_Model {
		foreach ( $this->links as $link ) {
			if ( 'refund' === $link->rel ) {
				return $link;
			}
		}

		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	public function jsonSerialize(): array {
		return array(
			'payment_id'        => $this->payment_id,
			'transaction_id'    => $this->transaction_id,
			'request_id'        => $this->request_id,
			'pr_transaction_id' => $this->pr_transaction_id,
			'payment_method'    => $this->payment_method_api,
			'operation'         => $this->operation,
			'transaction_time'  => $this->transaction_time,
			'links'             => array_map(
				function ( $link ) {
					return $link->jsonSerialize();
				},
				$this->links
			),
			'amount'            => $this->amount,
			'payment_details'   => $this->payment_details,
			'routing'           => $this->routing,
			'shopper_info'      => $this->shopper_info,
			'merchant_info'     => $this->merchant_info,
			'result'            => $this->result,
		);
	}

	/**
	 * {@inheritDoc}
	 */
	public static function jsonUnserialize( array|string $data ): ?static {
		$data = self::decode_json_data(
			$data,
			array(
				'payment_id',
				'transaction_id',
				'request_id',
				'pr_transaction_id',
				'payment_method',
				'operation',
				'transaction_time',
				'amount',
				'payment_details',
				'routing',
				'shopper_info',
				'merchant_info',
				'result',
				'links',
			)
		);

		if ( ! is_array( $data ) ) {
			return null;
		}

		return new static(
			new Result_Model(
				array(
					'payment_id'        => $data['payment_id'],
					'transaction_id'    => $data['transaction_id'],
					'request_id'        => $data['request_id'],
					'pr_transaction_id' => $data['pr_transaction_id'],
					'payment_method'    => $data['payment_method'],
					'operation'         => $data['operation'],
					'transaction_time'  => $data['transaction_time'],
					'amount'            => $data['amount'],
					'payment_details'   => $data['payment_details'],
					'routing'           => $data['routing'],
					'shopper_info'      => $data['shopper_info'],
					'merchant_info'     => $data['merchant_info'],
					'result'            => $data['result'],
					'links'             => $data['links'],
				)
			)
		);
	}
}
