<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

use \Verifone\Core\DependencyInjection\Service\PaymentInfoImpl;
use \Verifone\Core\DependencyInjection\Service\TransactionImpl;
use \Verifone\Core\ExecutorContainer;
use \Verifone\Core\ServiceFactory;

class WC_Verifone_Recurring_Payment {

	private $config;
	private $order;
	private $amount;
	private $subscription_code;
	private $customer_object;
	private $payment_method;

	function __construct( $order, $amount, $subscription_code ) {
		$this->config = WC_Verifone_Config::getInstance();

		$this->order = $order;
		$this->amount = $amount;
		$this->subscription_code = $subscription_code;
	}

	public function process_renewal_payment() {
		$this->customer_object = $this->get_customer_object();
		$this->payment_method = $this->get_saved_payment_method();

		if ( is_wp_error( $this->payment_method ) ) {
			return $this->payment_method;
		}

		$payment_response = $this->make_payment_request();
		if ( is_wp_error( $payment_response ) ) {
			return $payment_response;
		}

		return $payment_response;
	}

	public function get_saved_payment_method_info() {
		$this->customer_object = $this->get_customer_object();
		$method = $this->get_saved_payment_method();

		if ( is_wp_error( $method ) ) {
			return false;
		}

		$code = $method->getCode();

		$methods_array = WC_Verifone_PaymentMethodsArray::getAllMethods();
		if ( ! array_key_exists( $code, $methods_array ) ) {
			return false;
		}

		$validity = $method->getValidity();
		$validity_year  = substr( $validity, -4 );
    	$validity_month = substr( $validity, 0, -4 );

		return [
			'code' => $method->getCode(),
			'title' => $method->getTitle(),
			'validity' => sprintf( '%02d/%04d', $validity_month, $validity_year ),
			'method' => $methods_array[ $code ],
		];
	}

	private function get_customer_object() {
		$customer_data = WC_Verifone_Data::collectCustomerData( $this->order );
		$customer_data['external_id'] = WC_Verifone_Woocommerce_Subscriptions::get_customer_external_id( $this->order );
		return WC_Verifone_Core::createCustomerObject( $customer_data );
	}

	private function get_saved_payment_method() {
		try {
			$service = ServiceFactory::createService( WC_Verifone_Core::getBackedConfigObject(), 'Backend\GetSavedCreditCardsService' );
			$service->insertCustomer( $this->customer_object );
			$service->insertRecurringPaymentSubscriptionCode( $this->subscription_code );

			$container = new ExecutorContainer();
			$exec = $container->getExecutor( ExecutorContainer::EXECUTOR_TYPE_BACKEND );

			$key_file = $this->config->getPaymentPublicKeyFile();

			$response = $exec->executeService( $service, $key_file );
		} catch ( Exception $e ) {
			return new WP_Error( 'verifone_error', 'Error retrieving saved payment methods: ' . $e->getMessage() );
		}

		$response_body = $response->getBody();
		if ( empty( $response_body ) || ! is_array( $response_body ) || count( $response_body ) === 0 ) {
			return new WP_Error( 'verifone_error', 'No saved payment methods found for this customer.' );
		}

		return $response_body[0];
	}

	private function make_payment_request() {
		$order_data = WC_Verifone_Data::collectData( $this->order, $this->payment_method->getCode() );

		try {
			$payment_info = new PaymentInfoImpl( $order_data['locale'], '0', $this->payment_method->getId(), '', (bool)$this->config->isSaveMaskedPanNumber(), true );

			$transaction_info = new TransactionImpl( $this->payment_method->getCode(), $this->amount );

			$service = ServiceFactory::createService( WC_Verifone_Core::getBackedConfigObject(), 'Backend\ProcessPaymentService' );
			$service->insertCustomer( $this->customer_object );
			$service->insertOrder( WC_Verifone_Core::createOrderObject( $order_data ) );
			$service->insertPaymentInfo( $payment_info );
			$service->insertTransaction( $transaction_info );

			$container = new ExecutorContainer();
			$exec = $container->getExecutor( ExecutorContainer::EXECUTOR_TYPE_BACKEND );

			$key_file = $this->config->getPaymentPublicKeyFile();

			$response = $exec->executeService( $service, $key_file );
		} catch ( Exception $e ) {
			return new WP_Error( 'verifone_error', 'Error processing payment: ' . $e->getMessage() );
		}

		return $response;
	}
}
