<?php

namespace Simplyin\Simplyin_W_Plugin\Payments\Gateway\Model;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

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\PaymentsPayRequest;
use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Model\PaymentsPayRequestCustomerPaymentData;
use Simplyin\Simplyin_W_Plugin\Lib\Remote\SimplyInApi\Model\PaymentsPayRequestPaymentMethodData;
use Simplyin\Simplyin_W_Plugin\Lib\Session\Simplyin_Session;
use Simplyin\Simplyin_W_Plugin\Payments\Gateway\Gateway_Helper;

class Payment_Type_Blik extends Abstract_Payment implements Payment_Type_Interface {

	private static bool $modal_rendered = false;
	public string $blik_code = '';
	public ?string $customer_error_message = null;


	public function process_payment( Order_Data $order_data ) {
		global $simplyin_config;
		$simplyin_api_url = $simplyin_config['backendSimplyIn'];
		$config           = new Configuration();

		$simplyin_auth_token = ( new Simplyin_Session() )->get( 'simplyin_auth_token' );
		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 );

		$api                 = new PaymentsApi( null, $config );
		$this->payment_uuid  = $this->generate_random_uuid();
		$payment_method_data = new PaymentsPayRequestPaymentMethodData();
		$payment_method_data->setBlikCode( $this->blik_code );

		$order   = $order_data->get_order();
		$request = new PaymentsPayRequest();
		//$request->setOrderId( uniqid() );
		$request->setPaymentMethodId( $this->get_id() );
		$request->setPaymentId( $this->payment_uuid );
		$request->setTitle( 'Order #' . $order->get_id() );
		$request->setAmount( Gateway_Helper::normalize_price( $order->get_total() ) );
		$request->setCurrency( get_woocommerce_currency() );
		$request->setReturnUrl( $order->get_checkout_order_received_url() );
		$request->setWebhookUrl( Gateway_Helper::get_webhook_url( $order ) );
		$request->setPaymentMethodData( $payment_method_data );

		$debug = [
			'PaymentId'         => $request->getPaymentId(),
			'PaymentMethodId'   => $request->getPaymentMethodId(),
			'Title'             => $request->getTitle(),
			'Amount'            => $request->getAmount(),
			'Currency'          => $request->getCurrency(),
			'ReturnUrl'         => $request->getReturnUrl(),
			'WebhookUrl'        => $request->getWebhookUrl(),
			'PaymentMethodData' => $request->getPaymentMethodData(),
		];

		if ( false === $this->is_simplyin_user_logged() ) {
			$customerPaymentData = new PaymentsPayRequestCustomerPaymentData();
			$customerPaymentData->setEmail( $order->get_billing_email() );
			$customerPaymentData->setId( '' );
			$customerPaymentData->setFirstName( $order->get_billing_first_name() );
			$customerPaymentData->setLastName( $order->get_billing_last_name() );
			$customerPaymentData->setPhone( $order->get_billing_phone() );
			$request->setCustomerPaymentData( $customerPaymentData );
		}


		try {
			$raw = $api->paymentsPay( $request );
		} catch ( Exception $e ) {

			if ( method_exists( $e, 'getResponseBody' ) ) {
				//$message = $e->getMessage();
				$response_body                = $e->getResponseBody();
				$message                      = $response_body;
				$this->customer_error_message = $this->find_customer_message_error( $message );
				$order_data->update_selected_payment_method( $this );
				$order_data->update_order_status( 'failed', sprintf( 'Simply.IN payment failed with method: %s', $this->get_name() ) );
			} else {
				$message = $e->getMessage();
			}


			simplyin()->get_simplyin_logger()->log_if_wpdebug_on(
				sprintf( "[Payment_Type_Blik] [process_payment] %s",
					wp_json_encode( [
						'error'   => $message,
						'request' => $debug,
					] ),
				),
				'payments' );

			if ( null === $this->customer_error_message ) {
				throw new Exception( esc_html( $message ) );
			}

			return;
		}

		$this->payment_status      = $raw->getStatus();
		$this->payment_uuid        = $raw->getPaymentId();
		$this->provider_payment_id = $raw->getProviderPaymentId();
		$this->registered_at       = $raw->getRegisteredAt();

		$order_data->update_selected_payment_method( $this );

		simplyin()->get_simplyin_logger()->log_if_wpdebug_on(
			sprintf( "[Payment_Type_Blik] [process_payment] %s",
				wp_json_encode( [
					'request'      => $debug,
					'raw response' => $raw,
				] ),
			),
			'payments' );


	}

	private function find_customer_message_error( string $response_body
	): string {
		foreach (
			[
				'AUTH_CODE_USED'    => 'Authorization code has already been used',
				'AUTH_CODE_EXPIRED' => 'Authorization code expired',
				'AUTH_CODE_CANCEL'  => 'Authorization code was cancelled',

			] as $key => $message
		) {
			if ( false !== strpos( $response_body, $key ) ) {
				return $message;
			}
		}

		return "BLIK transaction FAILED";
	}


	public function configure_on_checkout() {
		if ( isset( $_POST['simplyin_checkout_token'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['simplyin_checkout_token'] ) ),
				'simplyin_checkout_nonce' ) ) {

			throw new Exception( 'wp_verify_nonce classic checkout failed' );

		} elseif ( isset( $_POST['simplyin_blocks_token'] ) && ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['simplyin_blocks_token'] ) ),
				'simplyin_blocks_nonce' ) ) {
			throw new Exception( 'wp_verify_nonce block checkout failed' );

		} elseif ( ! isset( $_POST['simplyin_checkout_token'] ) && ! isset( $_POST['simplyin_blocks_token'] ) ) {
			throw new Exception( 'Nonce not found' );
		}


		if ( isset( $_POST['simplyin_blik_code'] ) ) {
			$this->blik_code = sanitize_text_field( wp_unslash( $_POST['simplyin_blik_code'] ) );
		} else {
			throw new Exception( 'Blik Code not found' );
		}
	}

	public function order_received_actions(
		Order_Data $order_data
	) {

		$this->order_id = $order_data->get_order()->get_id();
		add_action( 'woocommerce_before_thankyou',
			[ $this, 'output_blik_modal' ] );
		// Fallback to broaden theme compatibility (mirrors card behavior)
		add_action( 'woocommerce_thankyou', [ $this, 'output_blik_modal' ] );
		// Extra fallback used by some themes/templates (order details area)
		add_action( 'woocommerce_order_details_after_order_table',
			[ $this, 'output_blik_modal' ] );
		add_action( 'wp_footer',
			[ $this, 'enqueue_scripts' ] );
	}

	public function output_blik_modal() {
		if ( self::$modal_rendered ) {
			return;
		}
		self::$modal_rendered = true;

		simplyin()->locate_template( 'blik.php',
			[ 'blik_payment' => $this ],
			'src/Payments/views/order_received' );
	}

	public function enqueue_scripts() {
		$public_url = simplyin()->get_plugin_url() . 'public';
		$payment_uuid   = (string) ( $this->get_payment_uuid() ?? '' );
		$enqueue_order  = wc_get_order( $this->order_id );
		$timeout_uuid   = $enqueue_order ? (string) $enqueue_order->get_meta( '_simplyin_payment_timeout_failed_payment_uuid' ) : '';
		$legacy_timeout = $enqueue_order ? (string) $enqueue_order->get_meta( '_simplyin_payment_timeout_failed' ) : '';
		if ( $enqueue_order && $timeout_uuid === '' && $legacy_timeout === 'true' && $payment_uuid !== '' ) {
			$enqueue_order->update_meta_data( '_simplyin_payment_timeout_failed_payment_uuid', $payment_uuid );
			$enqueue_order->delete_meta_data( '_simplyin_payment_timeout_failed' );
			$enqueue_order->save();
			$timeout_uuid = $payment_uuid;
		}
		$timeout_failed = ( $payment_uuid !== '' && $timeout_uuid !== '' && $timeout_uuid === $payment_uuid );

		wp_enqueue_script(
			'SimplyInThankYouPageJs',
			$public_url . '/thankyoupage/status/src/js/status.js',
			[ 'jquery' ],
			wp_rand(),
			true
		);

		wp_localize_script( 'SimplyInThankYouPageJs',
			'simplyInStatus',
			[
				'nonce'    => wp_create_nonce( 'simplyin_blik_status' ),
				'ajaxUrl'  => esc_url( admin_url( 'admin-ajax.php' ) ),
				'blikCode' => esc_attr( $this->blik_code ),
				'orderId'  => esc_attr( $this->order_id ),
				'paymentUuid' => esc_attr( $payment_uuid ),
				'timeoutFailed' => $timeout_failed,
			]
		);
	}

	public function set_payment_status( string $payment_status ) {
		$this->payment_status = $payment_status;
	}
}
