<?php

namespace Simplyin\Simplyin_W_Plugin\Payments\Gateway\Payment_Fields;

use Exception;


use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Api\PaymentsApi;


use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Configuration;
use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Model\PaymentsGetAvailablePaymentMethods200ResponseInner;
use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\ObjectSerializer;
use Simplyin\Simplyin_W_Plugin\Lib\Session\Simplyin_Session;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model\Session_Data;
use Simplyin\Simplyin_W_Plugin\Payments\Mappers\Payment_Method_Mapper;
use Simplyin\Simplyin_W_Plugin\Payments\Mappers\Payment_Provider_Mapper;
use Simplyin\Simplyin_W_Plugin\Payments\Mappers\View_Model\Payment_Methods_Blocks_Mapper;
use Simplyin\Simplyin_W_Plugin\Payments\Mappers\View_Model\Payment_Methods_Group_Mapper;
use Simplyin\Simplyin_W_Plugin\Payments\Remote\Sample_Response;
use Simplyin\Simplyin_W_Plugin\Payments\View_Model\Classic_Checkout\Payment_Method_Group;
use Simplyin\Simplyin_W_Plugin\Payments\View_Model\Classic_Checkout\Payment_Method_Item_Provider;
use Simplyin\Simplyin_W_Plugin\Payments\View_Model\Classic_Checkout\Payment_Method_Provider_Group;


class Payment_Fields {

	private const TRANSIENT_KEY = 'simplyin_payment_provider_cache';
	private const METHODS_CACHE_PREFIX = 'simplyin_payment_methods_';
	private const METHODS_CACHE_TTL = 120;


	public function render_payment_fields_checkout() {
		$payment_methods_view_model = $this->get_classic_checkout_payment_fields();

		if ( ! $payment_methods_view_model ) {
			throw new Exception( 'render_payment_fields failed. No payment methods.' );
		}

		simplyin()->locate_template( 'payment_methods.php',
			[ 'main_group' => $payment_methods_view_model ],
			'src/Payments/views/classic_checkout' );

	}

	/**
	 * @return Payment_Method_Provider_Group | null
	 * @throws Exception
	 */
	public function get_classic_checkout_payment_fields() {
		$raw = $this->get_payment_fields();

		if ( ! $raw ) {
			return null;
		}

		$payment_methods_view_model = ( new Payment_Methods_Group_Mapper( $raw ) )->map();


		return $payment_methods_view_model;

	}

	/**
	 * @return array | null
	 * @throws Exception
	 */
	public function get_blocks_payment_fields() {
		$raw = $this->get_payment_fields();

		if ( ! $raw ) {
			return null;
		}

		return ( new Payment_Methods_Blocks_Mapper( $raw ) )->map();
	}

	public function reload() {
		$raw = $this->fetch_from_remote();
		$this->cache_data_for_payment_processing( ( (array) $raw ) );
	}

	/**
	 * @throws Exception
	 */
	private function cache_data_for_payment_processing( $raw_payment_fields ) {
		simplyin()->get_simplyin_logger()->log_if_wpdebug_on(
			sprintf( "[cache_data_for_payment_processing] %s",
				wp_json_encode( [
					'payment_methods_raw array size' => count( $raw_payment_fields ),
				] ),
			),
			'payment-methods' );

		if ( ! empty( $raw_payment_fields ) ) {
			$payment_methods = Payment_Method_Mapper::map_from_simplyin_api( $raw_payment_fields );
			$session_data    = new Session_Data();
			$session_data->update_payment_methods( $payment_methods );
			$payment_provider_mapper = new Payment_Provider_Mapper( $raw_payment_fields );
			$provider                = $payment_provider_mapper->map();
			$session_data->update_payment_provider( $provider );
		}

	}

	/**
	 * @return array<PaymentsGetAvailablePaymentMethods200ResponseInner> | null
	 * @throws Exception
	 */
	private function get_payment_fields(): ?array {
		$raw = $this->fetch_from_remote();
		$this->cache_data_for_payment_processing( ( (array) $raw ) );

		if ( ! $raw ) {
			return null;
		}

		return $raw;
	}


	/**
	 *
	 * @return array<PaymentsGetAvailablePaymentMethods200ResponseInner> | null
	 */
	private function fetch_from_remote(): ?array {
		$simplyin_config  = simplyin()->get_simplyin_config();
		$simplyin_api_url = $simplyin_config['backendSimplyIn'];

		$config           = new Configuration();
		$simplyin_session = new Simplyin_Session();
		$simplyin_auth_token = (string) $simplyin_session->get( 'simplyin_auth_token', '' );
		$session_id          = (string) $simplyin_session->get( 'id', '' );
		$cache_key           = $this->get_methods_cache_key( $simplyin_auth_token, $session_id );
		$cached              = get_transient( $cache_key );
		if ( is_array( $cached ) ) {
			return $cached;
		}

		if ( ! empty( $simplyin_auth_token ) ) {
			$config->setApiKey( 'api_token', $simplyin_auth_token );
		}

		$config->setApiKey( 'X-Auth-Merchant-Api-Key',
			get_option( 'simplyin_api_key' ) );

		$config->setHost( $simplyin_api_url );


		$sample_response = false;
		if ( $sample_response ) {
			$returnType = '\Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Model\PaymentsGetAvailablePaymentMethods200ResponseInner[]';
			$json       = ( new Sample_Response() )->get_sample_response();
			$raw        = ObjectSerializer::deserialize( $json,
				$returnType,
				[] );
		} else {
			$api = new PaymentsApi( null, $config );
			try {
			$raw = $api->paymentsGetAvailablePaymentMethods();


			} catch ( Exception $e ) {
				$msg = $e->getMessage();

				simplyin()->get_simplyin_logger()->log_if_wpdebug_on(
					sprintf( "[cache_data_for_payment_processing] %s",
						wp_json_encode( [
							'msg' => $msg,
						] ),
					),
					'payment-methods-remote' );

				return null;


			}
		}

		if ( is_array( $raw ) && ! empty( $raw ) ) {
			set_transient( $cache_key, $raw, self::METHODS_CACHE_TTL );
		}

		return $raw;
	}

	private function get_methods_cache_key( string $auth_token, string $session_id ): string {
		$host = (string) wp_parse_url( home_url(), PHP_URL_HOST );
		$key_source = $host . '|' . $auth_token . '|' . $session_id;

		return self::METHODS_CACHE_PREFIX . md5( $key_source );
	}

	public static function clear_methods_cache( ?string $auth_token = null, ?string $session_id = null ): void {
		$session = new Simplyin_Session();
		$token   = $auth_token !== null ? $auth_token : (string) $session->get( 'simplyin_auth_token', '' );
		$sid     = $session_id !== null ? $session_id : (string) $session->get( 'id', '' );
		$instance = new self();
		$cache_key = $instance->get_methods_cache_key( $token, $sid );
		delete_transient( $cache_key );
	}

}
