<?php
/**
 * @package     CMGiftCard
 * @subpackage  plg_cmgiftcard_stripe
 * @copyright   Copyright (C) 2016-2024 CMExension
 * @license     GNU General Public License version 2 or later
 */

defined('_JEXEC') or die;

require_once JPATH_ROOT . '/plugins/cmgiftcard/stripe/vendor/autoload.php';
require_once JPATH_ROOT . '/administrator/components/com_cmgiftcard/helpers/plugin/cmgiftcard.php';

use Joomla\CMS\Factory;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Stripe\Stripe;

/**
 * Stripe payment method for CMGiftCard.
 *
 * @package     CMGiftCard
 * @subpackage  plg_cmgiftcard_stripe
 * @since       2.1.0
 */
class PlgCMGiftCardStripe extends CMGiftCardPlugin
{
	/**
	 * Constructor
	 *
	 * @param   object  &$subject  The object to observe
	 * @param   array   $config    An optional associative array of configuration settings.
	 *                             Recognized key values include 'name', 'group', 'params', 'language'
	 *                             (this list is not meant to be comprehensive).
	 *
	 * @since   2.1.0
	 */
	public function __construct(&$subject, $config = array())
	{
		$this->gatewayId = 'stripe';
		$this->gatewayName = 'PLG_CMGIFTCARD_STRIPE_NAME';

		parent::__construct($subject, $config);
	}

	/**
	 * Generate payment form.
	 *
	 * @param   array  $data  Billing data.
	 *
	 * @return  array
	 *
	 * @since   2.1.0
	 */
	public function onCMGCGetPaymentForm($data)
	{
		$gatewayId = isset($data['billing']['payment_method']) ? $data['billing']['payment_method'] : '';

		if ($gatewayId != $this->gatewayId)
			return false;

		$params = $this->params;
		$mode = $params->get('mode', 'test');
		$currencyCode = $params->get('currency_code');

		if ($mode == 'live')
		{
			$secretKey = $params->get('live_secret_key');
		}
		else
		{
			$secretKey = $params->get('test_secret_key');
		}

		$stripe = new \Stripe\StripeClient($secretKey);

		$orderNumber = $data['billing']['order_number'];

		$db = Factory::getDbo();
		$query = $db->getQuery(true)
			->select($db->qn('id'))
			->from($db->qn('#__cmgiftcard_orders'))
			->where($db->qn('order_number') . ' = ' . $db->q($orderNumber));
		$orderId = $db->setQuery($query)->loadResult();

		$lineItems = [];

		foreach ($data['items'] as $item)
		{
			$lineItems[] = [
				'price_data' => [
					'currency' => $currencyCode,
					'product_data' => [
						'name' => $item['design_title'],
					],
					'unit_amount' => $item['amount'] * 100,
				],
				'quantity' => 1,
			];
		}

		$siteUrl = str_replace(Uri::root(true), '', substr(Uri::root(), 0, -1));
		$cancelUrl = $siteUrl . CMGiftCardHelper::prepareRoute('index.php?option=com_cmgiftcard&view=checkout') . '?layout=cancel';
		$successUrl = Uri::root() . 'index.php?option=com_cmgiftcard&task=callback&gateway=' . $this->gatewayId . '&number=' . $orderNumber . '&id=' . $orderId;

		$session = $stripe->checkout->sessions->create([
			'line_items'	=> $lineItems,
			'mode'			=> 'payment',
			'success_url'	=> $successUrl,
			'cancel_url'	=> $cancelUrl,
		]);

		$query->clear()
			->update($db->qn('#__cmgiftcard_orders'))
			->set($db->qn('transaction_id') . ' = ' . $db->q($session->id))
			->where($db->qn('id') . ' = ' . $db->q($orderId));
		$db->setQuery($query)->execute();

		Factory::getApplication()->redirect($session->url);
	}

	/**
	 * Update order after successful payment.
	 *
	 * @return  boolean
	 *
	 * @since   2.1.0
	 */
	public function onCMGCValidateCallback()
	{
		require_once JPATH_ROOT . '/components/com_cmgiftcard/models/order.php';

		$app = Factory::getApplication();
		$jinput = $app->input;
		$gatewayId = $jinput->get('gateway');
		$orderNumber = $jinput->getUint('number', 0);
		$orderId = $jinput->getUint('id', 0);

		$result = [
			'validation'	=> false,
			'gateway_id'	=> '',
			'transaction_id'=> '',
			'order_id'		=> ''
		];

		if ($gatewayId != $this->gatewayId)
		{
			return $result;
		}

		$success = false;
		$siteUrl = str_replace(Uri::root(true), '', substr(Uri::root(), 0, -1));
		$redirectUrl = $siteUrl . CMGiftCardHelper::prepareRoute('index.php?option=com_cmgiftcard&view=cart');

		$logData = [
			'order_id'		=> $orderId,
			'order_number'	=> $orderNumber,
		];

		if ($orderNumber <= 0 || $orderId <= 0)
		{
			$logData['reason'] = 'Order not found';
			$this->logNotification($logData, $success);
			$app->enqueueMessage(Text::_('PLG_CMGIFTCARD_STRIPE_ORDER_NOT_FOUND'), 'error');
			$app->redirect($redirectUrl);
		}

		$db = Factory::getDbo();
		$query = $db->getQuery(true)
			->select('*')
			->from($db->qn('#__cmgiftcard_orders'))
			->where($db->qn('id') . ' = ' . $db->q($orderId))
			->where($db->qn('order_number') . ' = ' . $db->q($orderNumber));
		$order = $db->setQuery($query)->loadObject();

		if (empty($order) || empty($order->transaction_id))
		{
			$logData['reason'] = 'Order not found';
			$this->logNotification($logData, $success);
			$app->enqueueMessage(Text::_('PLG_CMGIFTCARD_STRIPE_ORDER_NOT_FOUND'), 'error');
			$app->redirect($redirectUrl);
		}

		// Order was already paid.
		if ($order->order_status == 'paid')
		{
			$app->redirect($siteUrl);
		}

		$params = $this->params;
		$mode = $params->get('mode', 'test');
		$currencyCode = $params->get('currency_code');

		if ($mode == 'live')
		{
			$secretKey = $params->get('live_secret_key');
		}
		else
		{
			$secretKey = $params->get('test_secret_key');
		}

		$stripe = new \Stripe\StripeClient($secretKey);

		try {
			$session = $stripe->checkout->sessions->retrieve($order->transaction_id, []);
		} catch(\Exception $e) {
			$logData['reason'] = $e->getMessage();
			$this->logNotification($logData, $success);
			$app->enqueueMessage(Text::_('PLG_CMGIFTCARD_STRIPE_ORDER_NOT_FOUND'), 'error');
			$app->redirect($redirectUrl);
		}

		if (!$session)
		{
			$logData['reason'] = $e->getMessage();
			$this->logNotification($logData, $success);
			$app->enqueueMessage(Text::_('PLG_CMGIFTCARD_STRIPE_ORDER_NOT_FOUND'), 'error');
			$app->redirect($redirectUrl);
		}

		if (isset($session->payment_status) && $session->payment_status == 'paid')
		{
			$success = true;
			$redirectUrl = $siteUrl . CMGiftCardHelper::prepareRoute('index.php?option=com_cmgiftcard&view=checkout') . '?layout=success';

			$orderModel = BaseDatabaseModel::getInstance('Order', 'CMGiftCardModel');
			$orderModel->updatePaidOrder($order->id, $order->transaction_id);
			CMGiftCardHelper::sendOrderEmail($order->id);
			CMGiftCardHelper::sendElectronicCardEmail($order->id);
			CMGiftCardHelper::sendPhysicalCardEmail($order->id);
		}

		if (!$success)
		{
			$app->enqueueMessage(Text::_('PLG_CMGIFTCARD_STRIPE_PAYMENT_FAILED'), 'error');
		}

		$this->logNotification($logData, $success);
		$app->redirect($redirectUrl);
	}
}
