<?php

namespace WooCommerce\Plugin\AddonPayments;

use ComerciaGlobalPayments\AddonPayments\SDK\Api\EPGJs;
use ComerciaGlobalPayments\AddonPayments\SDK\Request\AccountDisable;
use WooCommerce\Plugin\AddonPayments\Entities\CardAttempts;
use WooCommerce\Plugin\AddonPayments\Entities\CardToken;

class CardVault {

	public function __construct() {
		add_action( 'init', array( $this, 'create_endpoints' ) );
		add_filter( 'query_vars', array( $this, 'create_query_vars' ), 0 );
		add_filter( 'woocommerce_account_menu_items', array( $this, 'add_menu_items' ) );
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_action( 'woocommerce_account_card-vault_endpoint', array( $this, 'endpoint_content' ) );
		add_action( 'wp_ajax_card-vault', array( $this, 'cardVaultPetition' ) );
		add_action( 'wp_ajax_card-vault-delete', array( $this, 'cardVaultDeletePetition' ) );
	}

	public function create_endpoints() {
		add_rewrite_endpoint( 'card-vault', EP_PAGES );
	}

	public function create_query_vars( $vars ) {
		$vars[] = 'card-vault';

		return $vars;
	}

	public function add_menu_items( $items ) {
		// Remove the logout menu item.
		$logout = $items['customer-logout'];
		unset( $items['customer-logout'] );

		// Insert the item
		$items['card-vault'] = __( 'Card Vault', 'addonpayments' );

		// Insert back the logout item.
		$items['customer-logout'] = $logout;

		return $items;
	}

	public function enqueue_scripts() {
		if ( ! is_account_page() ) {
			return;
		}

		$payment_gateways = \WC_Payment_Gateways::instance();
		$payment_gateway  = $payment_gateways->payment_gateways()[ ID_EPG ];

		$rendererJsLocation = EPGJs::getEndpoints( $payment_gateway->getLiveMode() )['render'];
		$jsLocation         = esc_url( plugins_url( '../../assets/js/cardVault.js', __FILE__ ) );
		wp_enqueue_script( 'jquery' );
		wp_enqueue_script( 'epg-renderer', $rendererJsLocation, false );
		wp_enqueue_script( 'cardVault', $jsLocation, false );
		wp_enqueue_style( 'cardVaultStyle', esc_url( plugins_url( '../../assets/css/front.css', __FILE__ ) ), false );

		$locale = substr( get_locale(), 0, 2 );
		$i18n   = $payment_gateway->getI18n( $locale );

		wp_localize_script(
			'cardVault',
			'cardVault_object',
			array(
				'locale' => $locale,
				'i18n'   => array( $locale => $i18n ),
				'texts'  => array(
					'unknownError'       => __( 'An unexpected error occurred and your action cannot be performed. Please try reloading the page and if the problem persists contact us.', 'addonpayments' ),
					'reachedPaysolLimit' => __( 'Sorry, you have reached the registration limit for payment methods.', 'addonpayments' ),
				),
			)
		);
	}

	public function endpoint_content() {
		$current_user     = wp_get_current_user();
		$payment_gateways = \WC_Payment_Gateways::instance();
		$payment_gateway  = $payment_gateways->payment_gateways()[ ID_EPG ];
		$apiClient        = $payment_gateway->getApiClient();
		$authToken        = $payment_gateway->get_auth_token( $apiClient );
		$isLive           = $payment_gateway->settings['live_mode'] === 'yes';
		$tokenValidity    = \WC_Gateway_EasyPaymentGateway::AUTH_TOKEN_VALIDITY_THRESHOLD;
		$validUntil       = ( time() * 1000 ) + (int) $tokenValidity;
		$cashierMode      = 'setShowAllPaysolToRegisterAndQuickDeposit';
		$instanceId       = sha1( microtime() );
		$payment_methods  = $this->getRegisteredPaymentMethods();
		$url              = admin_url( 'admin-ajax.php' );
		$timeoutText      = __( 'This operation has timed out, please reload the page.', 'addonpayments' );

		require_once EPG_BASE_DIR . '/templates/vault.php';
	}

	public function cardVaultPetition() {
		$registerResponse = $_POST['registerResponse'];

		if ( empty( $registerResponse ) ) {
			wp_die(
				json_encode(
					array(
						'status' => 'error',
						'msg'    => __( 'The request contains an invalid payload', 'addonpayments' ),
					)
				)
			);
		}

		if ( 'registered' !== $registerResponse['action'] ) {
			wp_die( json_encode( array( 'status' => 'nothing' ) ) );
		}

		$current_user = wp_get_current_user();

		if ( $current_user->ID != $registerResponse['customer'] ) {
			wp_die(
				json_encode(
					array(
						'status'   => 'error',
						'errorMsg' => 'Not the same as the customer registered',
					)
				)
			);
		}

		// Register card attempt
		$cardAttempt              = new CardAttempts();
		$cardAttempt->customer_id = $current_user->ID;
		$cardAttempt->rawData     = json_encode( $_POST['registerResponse'] ); // @TODO: Encrypt this data
		$cardAttempt->date        = date( 'Y-m-d H:i:s' );
		$ok                       = $cardAttempt->save() !== false;

		// Add card to vault
		$cardToken                = new CardToken();
		$cardToken->customer_id   = $current_user->ID;
		$cardToken->accountId     = $registerResponse['accountId'];
		$cardToken->paymentMethod = $registerResponse['paymentMethod'];
		$cardToken->createdAt     = date( 'Y-m-d H:i:s' );
		$cardToken->lastUsed      = $cardToken->createdAt;

		$values = array_column( $registerResponse['values'], 'value', 'name' );

		foreach ( $values as $key => $value ) {
			switch ( true ) {
				case ( 'cardType' === $key ):
					$cardToken->cardType = $value;
					break;
				case ( 'cardHolderName' === $key ):
				case ( 'chName' === $key ):
					$cardToken->name = $value;
					break;
				case ( 'maskedCardNumber' === $key ):
				case ( 'cardNumber' === $key && ! array_key_exists( 'maskedCardNumber', $values ) ):
					$cardToken->cardNumber = $value;
					break;
				case ( 'cardNumber' === $key && array_key_exists( 'maskedCardNumber', $values ) ):
				case ( 'cardNumberToken' === $key ):
					$cardToken->cardToken = $value; // @TODO: Encrypt this data
					break;
				default:
			}
		}

		if ( CardToken::tokenExists( $cardToken->cardToken ) ) {
			wp_die(
				json_encode(
					array(
						'status' => 'error',
						'msg'    => __(
							'Card already in the database',
							'addonpayments'
						),
					)
				)
			);
		}

		$ok = $ok && ( $cardToken->save() !== false );

		if ( ! $ok ) {
			wp_die(
				json_encode(
					array(
						'status' => 'error',
						'msg'    => __( 'Could not save the card', 'addonpayments' ),
					)
				)
			);
		}

		wp_die( json_encode( array( 'status' => 'success' ) ) );

	}

	public function cardVaultDeletePetition() {
		$accountId        = $_POST['accountId'];
		$payment_gateways = \WC_Payment_Gateways::instance();
		$payment_gateway  = $payment_gateways->payment_gateways()[ ID_EPG ];
		$apiClient        = $payment_gateway->getApiClient();
		$authToken        = $payment_gateway->get_auth_token( $apiClient );
		$request          = ( new AccountDisable() )
			->setAccountId( $accountId )
			->setAuthToken( $authToken );
		$apiClient->accountDisable( $request );

		if ( ! CardToken::deleteByAccountId( $accountId ) ) {
			wp_die(
				json_encode(
					array(
						'status' => 'error',
						'msg'    => __( 'Could not delete account from database', 'addonpayments' ),
					)
				)
			);
		}

		wp_die( json_encode( array( 'status' => 'success' ) ) );
	}

	private function getRegisteredPaymentMethods() {
		$current_user = wp_get_current_user();
		$tokens       = CardToken::getByCustomer( $current_user->ID );
		if ( empty( $tokens ) ) {
			return array();
		}

		foreach ( $tokens as $key => $token ) {
			unset( $token['token'], $token['rawData'] );

			$tokens[ $key ]['createdAt'] = $token['createdAt'];
			$tokens[ $key ]['lastUsed']  = $token['lastUsed'];
		}

		return $tokens;
	}
}
