<?php

namespace WooCommerce\Plugin\AddonPayments;

use ComerciaGlobalPayments\AddonPayments\SDK\Request\Capture;
use ComerciaGlobalPayments\AddonPayments\SDK\Response\OperationInterface;
use WooCommerce\Plugin\AddonPayments\Entities\Transaction;
use WooCommerce\Plugin\AddonPayments\Operations\CaptureTransaction;
use WooCommerce\Plugin\AddonPayments\Operations\ProcessTransaction;
use WooCommerce\Plugin\AddonPayments\Operations\ValidateOrder;

class TransactionsController {
	public function __construct() {
		add_action( 'admin_menu', array( $this, 'add_plugin_page' ), 99 );
		add_action( 'add_meta_boxes', array( $this, 'register_meta_box' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
		add_action( 'wp_ajax_epg-capture', array( $this, 'capture_transaction' ) );
	}

	public function add_plugin_page() {
		add_submenu_page(
			'woocommerce',
			__( 'Transactions', 'addonpayments' ),
			__( 'Transactions', 'addonpayments' ),
			'manage_options',
			'wpg-transactions',
			array( $this, 'getContent' )
		);
	}

	public function getContent() {
		$elementsPerPage = 50;
		$totalRecords    = Transaction::getTotalTransactions();
		$totalPages      = ceil( $totalRecords / $elementsPerPage );
		$page            = 0;

		if ( isset( $_GET['transaction_page'] ) ) {
			$page = $_GET['transaction_page'];
			if ( $page + 1 > $totalPages ) {
				$page = $totalPages - 1;
			}
		}

		$transactions = Transaction::getTransactions( $page, $elementsPerPage );
		require_once EPG_BASE_DIR . '/templates/transactions.php';
	}

	public function enqueue_scripts( $hook ) {
		wp_enqueue_script( 'jquery' );
		wp_enqueue_script( 'epg_transactions', esc_url( plugins_url( '../../assets/js/transactions.js', __FILE__ ) ) );
		wp_enqueue_style(
			'transactions_style',
			esc_url( plugins_url( '../../assets/css/transactions.css', __FILE__ ) )
		);
	}

	public function capture_transaction() {
		$transactionId    = $_POST['transaction'];
		$transaction      = Transaction::getByPayFrexTransactionId( $transactionId )[0];
		$order            = wc_get_order( $transaction->id_order );

		$response = (new CaptureTransaction())($transactionId);
		$this->processResponse( $response, $order );
	}

	private function processResponse( $response, $order ) {
		if ( $response instanceof OperationInterface ) {
			// Captured transactions can only return SUCCESS, any other status should be considered an ERROR.
			// @FIXME Operation::hasSucceed does not properly check success status.
			if ( OperationInterface::STATUS_SUCCESS === $response->getStatus()
				 || OperationInterface::STATUS_SUCCESS === $response->getTransaction()->getStatus()
			) {

				$transactions = $response->getOperations();
				$this->registerTransactions( $response->getOperations(), $order );
				( new ValidateOrder() )( $transactions, $order );

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

			wp_die(
				json_encode(
					array(
						'status' => 'error',
						'msg'    => __( 'The transaction could not be captured', 'addonpayments' ),
					)
				)
			);
		}

		if ( null !== $response->getHttpResponse() ) {
			$errorContent = json_decode( (string) $response->getHttpResponse()->getBody(), true );

			if ( ! empty( $errorContent ) && ! empty( $errorContent['errorMessage'] )
			) {

				wp_die(
					json_encode(
						array(
							'status' => 'error',
							'msg'    => $errorContent['errorMessage'],
						)
					)
				);
			}
		}

		// If we have come this far is because its an unknown error.
		wp_die(
			json_encode(
				array(
					'status' => 'error',
					'msg'    => $response->getReason(),
				)
			)
		);
	}

	private function registerTransactions( $transactions, $order ) {
		$operations = count( $transactions );
		foreach ( $transactions as $transaction ) {
			( new ProcessTransaction() )( $transaction, $operations, $order->get_id() );
		}
	}

	/**
	 * Add metabox for order transactions
	 *
	 * @return void
	 */
	public function register_meta_box() {
		add_meta_box(
			'transactions',
			esc_html__( 'Transactions', 'addonpayments' ),
			array( $this, 'get_order_transactions' ),
			'shop_order',
			'normal',
			'low'
		);
	}

	/**
	 * Show  order transactions on admin order page.
	 *
	 * @param \WP_Post $post
	 *
	 * @return void
	 */
	public function get_order_transactions( $post ) {
		$transactions = Transaction::getByOrder( $post->ID );
		$order        = new \WC_Order( $post->ID );
		$transactions = $this->attach_capture_link( $order, $transactions );

		require_once EPG_BASE_DIR . '/templates/order-transactions.php';
	}

	/**
	 * Add capture link if necessary.
	 *
	 * @param \WC_Order $order
	 * @param array $transactions
	 *
	 * @return array
	 */
	private function attach_capture_link( \WC_Order $order, array $transactions ) {
		$status_pending = OperationInterface::STATUS_PENDING;

		if( 'on-hold' !== $order->get_status() ) {
			return $transactions;
		}

		foreach ( $transactions as $transaction ) {
			if( $status_pending !== $transaction->status) {
				continue;
			}

			$transaction->capture_link = '<button class="button button-primary epg-capture-order " ' .
			                             'data-order="'. $transaction->id_order .'" ' .
			                             'data-transaction="'. $transaction->payFrexTransactionId .'" ' .
			                             'data-url="'. admin_url( 'admin-ajax.php' ) .'">'. __( 'Capture', 'addonpayments' ) .'</button>';
		}

		return $transactions;
	}
}
