<?php
/**
 * @version		3.5.7
 * @package		Joomla
 * @subpackage	EShop
 * @author  	Giang Dinh Truong
 * @copyright	Copyright (C) 2012 Ossolution Team
 * @license		GNU/GPL, see LICENSE.php
 */
// no direct access
defined('_JEXEC') or die();

use Joomla\CMS\Factory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Router\Route;
use Joomla\CMS\Table\Table;
use Joomla\CMS\Uri\Uri;
use Joomla\Registry\Registry;
use Joomla\CMS\Plugin\PluginHelper;
use PayPalCheckoutSdk\Core\PayPalHttpClient;
use PayPalCheckoutSdk\Core\ProductionEnvironment;
use PayPalCheckoutSdk\Core\SandboxEnvironment;
use PayPalCheckoutSdk\Orders\OrdersCaptureRequest;

class os_paypalstc extends os_payment
{
	/**
	 * PayPal Client ID
	 *
	 * @var string
	 */
	private $clientId;

	/**
	 * PayPal Client Secret
	 *
	 * @var string
	 */
	private $clientSecret;

	/**
	 * Constructor functions, init some parameter
	 *
	 * @param   Registry  $params
	 */
	public function __construct($params, $config = [])
	{
        parent::__construct($params, $config);
		
		$this->mode = $params->get('mode');
		
		parent::__construct($params, $config);

		if ($this->mode)
		{
			$this->clientId     = $params->get('client_id');
			$this->clientSecret = $params->get('client_secret');
		}
		else
		{
			$this->clientId     = $params->get('sandbox_client_id');
			$this->clientSecret = $params->get('sandbox_client_secret');
		}
	}

	/**
	 * Process Payment
	 *
	 * @param   DMSTableOrder  $row
	 * @param   array          $data
	 */
	public function processPayment($data)
	{
		HTMLHelper::_('behavior.core');

		$document = Factory::getDocument();

		$query = [
			'client-id' => $this->clientId,
			'currency'  => $data['currency_code'],
		];

		if (!empty($this->params->get('disable_funding')))
		{
			$query['disable-funding'] = implode(',', $this->params->get('disable_funding'));
		}

		$document->addScript('https://www.paypal.com/sdk/js?' . http_build_query($query))
			->addScriptOptions('fullSiteUrl', Uri::root())
			->addScriptOptions('Itemid', Factory::getApplication()->input->getInt('Itemid'));

		$rootUri = Uri::root(true);

		// The command is needed here so that in case the js file is blocked, we can just copied to media/com_eshop/js folder
		$document->addScript($rootUri . '/components/com_eshop/plugins/payment/paypalstc/js/site-register-paypalstc.js');

		$customCssFile = JPATH_ROOT . '/components/com_eshop/themes/default/css/custom.css';

		if (file_exists($customCssFile) && filesize($customCssFile) > 0)
		{
			$document->addStyleSheet($rootUri . '/components/com_eshop/themes/default/css/custom.css');
		}
		
		$countryId = $data['payment_country_id'] ? $data['payment_country_id'] : EshopHelper::getConfigValue('country_id');
		
		$country = EshopHelper::getCountry($countryId);

		$orderData = [
			"intent"              => "CAPTURE",
			"purchase_units"      => [
				[
					"description" => Text::sprintf('ESHOP_PAYMENT_FOR_ORDER', $data['order_id']),
					"amount"      => [
						"value"         => round($data['total'], 2),
						"currency_code" => $data['currency_code'],
					],
				],
			],
			"payer"               => [
				'email_address' => $data['email'],
				'name'          => ['name' => trim($data['payment_firstname'] . ' ' . $data['payment_lastname'])],
				'address'       => [
					'address_line_1' => $data['payment_address_1'],
					'address_line_2' => $data['payment_address_2'],
					'postal_code'    => $data['payment_postcode'],
					'country_code'   => $country->iso_code_2,
				],
			],
			'application_context' => [
				'shipping_preference' => 'NO_SHIPPING',
			],
		];

		$document->addScriptOptions('orderData', $orderData)
			->addScriptOptions('order_number', $data['order_number']);

		$currency = new EshopCurrency();
		
		if (Factory::getApplication()->getLanguage()->hasKey('ESHOP_PAYPAL_STC_PAYMENT_INSTRUCTIONS'))
		{
			$paymentInstructions = Text::_('ESHOP_PAYPAL_STC_PAYMENT_INSTRUCTIONS');
		}
		else
		{
			$paymentInstructions = 'Please choose one of the payment options below to process payment for your order. The amount to pay is <strong>[AMOUNT]</strong>';
		}

		$paymentInstructions = str_replace("[AMOUNT]", $currency->format($data['total']), $paymentInstructions);
		
		$bootstrapHelper = new EshopHelperBootstrap(EshopHelper::getConfigValue('twitter_bootstrap_version'));
		?>
        <div class="eb-container paypal-standard-checkout <?php echo $bootstrapHelper->getClassMapping('row-fluid'); ?>">
            <h1 class="eb-page-heading"><?php echo Text::_('ESHOP_PROCESS_PAYMENT') ?></h1>
            <p class="text-info"><?php echo $paymentInstructions ?></p>
            <div id="paypal-button-container"></div>
        </div>
		<?php
	}

	/**
	 * Verify payment
	 *
	 * @return bool
	 */
	public function verifyPayment()
	{
		require_once JPATH_ROOT . '/components/com_eshop/plugins/payment/paypalstc/checkoutsdk/vendor/autoload.php';

		$app = Factory::getApplication();

		$orderId          = $app->input->getString('order_id', '');
		$orderNumber	  = $app->input->getString('order_number', '');
		$Itemid           = $app->input->getInt('Itemid', 0);
		$session          = Factory::getSession();
		$completeUrl      = Route::_('index.php?option=com_eshop&view=checkout&layout=complete&Itemid=' . $Itemid, false, 0, true);
		$failureUrl       = Route::_('index.php?option=com_eshop&view=checkout&layout=failure&Itemid=' . $Itemid, false, 0, true);

		if ($this->mode)
		{
			$environment = new ProductionEnvironment($this->clientId, $this->clientSecret);
		}
		else
		{
			$environment = new SandboxEnvironment($this->clientId, $this->clientSecret);
		}

		$client = new PayPalHttpClient($environment);

		try
		{
			$response = $client->execute(new OrdersCaptureRequest($orderId));

			if ($response->result->status === 'COMPLETED')
			{
				// Publish the order
				$db    = Factory::getDbo();
				$query = $db->getQuery(true)
					->select('id')
					->from('#__eshop_orders')
					->where('order_number = ' . $db->quote($orderNumber));
				$db->setQuery($query);
				$id = (int) $db->loadResult();

				$success      = true;
				$errorMessage = '';
				
				$row = Table::getInstance('Eshop', 'Order');

				if (!$row->load($id))
				{
					$success      = false;
					$errorMessage = 'Invalid Order Number';
				}

				$amount = $response->result->purchase_units[0]->payments->captures[0]->amount;

				// Validate currency code
				if ($success && ($amount->currency_code != strtoupper($row->currency_code)))
				{
					$success      = false;
					$errorMessage = 'Invalid Payment Currency Test';
				}

				// Validate payment amount
				if ($success && (($row->total - $amount->value) >= 0.05))
				{
					$success      = false;
					$errorMessage = 'Invalid Payment Amount';
				}

				if ($success)
				{
					$row->transaction_id = $orderId;
					$row->order_status_id = EshopHelper::getConfigValue('complete_status_id');
					$row->store();
					EshopHelper::completeOrder($row);
					PluginHelper::importPlugin('eshop');
					Factory::getApplication()->triggerEvent('onAfterCompleteOrder', array($row));
					
					//Send confirmation email here
					if (EshopHelper::getConfigValue('order_alert_mail'))
					{
						EshopHelper::sendEmails($row);
					}
					
					$response->result->redirectUrl = $completeUrl;
				}
				else
				{
					$session->set('omnipay_payment_error_reason', $errorMessage);
					$response->result->redirectUrl = $failureUrl;
				}
			}
			else
			{
				$session->set('omnipay_payment_error_reason', 'Payment was not completed');
				$response->result->redirectUrl = $failureUrl;
			}

			echo json_encode($response->result);
		}
		catch (\PayPalHttp\HttpException $e)
		{
			// Return the error so that
			$result = json_decode($e->getMessage());

			if ($result->name != 'INSTRUMENT_DECLINED')
			{
				Factory::getSession()->set('omnipay_payment_error_reason');
				$result->redirectUrl = $failureUrl;
			}

			echo json_encode($result);
		}
		catch (\PayPalHttp\IOException $e)
		{
			Factory::getSession()->set('omnipay_payment_error_reason', $e->getMessage());

			echo json_encode(['redirectUrl' => $failureUrl]);
		}

		$app->close();
	}
}