<?php

/**
 * @package com_spbooking
 * @author JoomShaper http://www.joomshaper.com
 * @copyright Copyright (c) 2010 - 2023 JoomShaper
 * @license http://www.gnu.org/licenses/gpl-2.0.html GNU/GPLv2 or later
 */

// No Direct Access
defined('_JEXEC') or die('Resticted Aceess');
require_once JPATH_ROOT . '/components/com_spbooking/assets/vendor/autoload.php';


use Joomla\CMS\Factory;
use Joomla\CMS\Log\Log;
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Language\Text;
use Joomla\CMS\Component\ComponentHelper;
use Joomla\CMS\MVC\Model\BaseDatabaseModel;
use Joomla\CMS\MVC\Controller\FormController;

class SpbookingControllerPayment extends FormController
{

	public function getModel($name = 'Package', $prefix = 'SpbookingController', $config = array('ignore_request' => true))
	{
		$model = parent::getModel($name, $prefix, $config);

		return $model;
	}

	public function success()
	{
		$input = Factory::getApplication()->input;

		if ($input->get('st') == 'Completed')
		{
			Factory::getApplication()->enqueueMessage(Text::_('COM_SPBOOKING_PAYMENT_SUCCESSFUL'), 'success');
		}
		elseif ($input->get('st') == 'Pending')
		{
			Factory::getApplication()->enqueueMessage(Text::_('COM_SPBOOKING_PAYMENT_PENDING'), 'success');
		}
	}

	// If cancel payment
	public function paymencancel()
	{
		$output = '<div class="alert alert-danger">';
			$output .= '<p>' . Text::_('COM_SPBOOKING_PAYMENT_ERROR') . '</p>';
		$output .= '</div>';
		echo $output;

		return;
	}

	// Payment notify
	public function notify()
	{
		$input = Factory::getApplication()-> input;
		$params = ComponentHelper::getParams('com_spbooking');

		// Load Lessons model
		BaseDatabaseModel::addIncludePath(JPATH_SITE . '/components/com_spbooking/models');
		$model = BaseDatabaseModel::getInstance('Payment', 'SpbookingModel');

		if ($input->get('txn_id') && $input->get('txn_type'))
		{
			$raw_post_data = file_get_contents('php://input');
			$raw_post_array = explode('&', $raw_post_data);
			$myPost = array();

			foreach ($raw_post_array as $keyval)
			{
				$keyval = explode('=', $keyval);

				if (count($keyval) == 2)
				{
					if ($keyval[0] === 'payment_date')
					{
						if (substr_count($keyval[1], '+') === 1)
						{
							$keyval[1] = str_replace('+', '%2B', $keyval[1]);
						}
					}

					$myPost[$keyval[0]] = urldecode($keyval[1]);
				}
			}

			$req = 'cmd=_notify-validate';
			$get_magic_quotes_exists = false;

			if (function_exists('get_magic_quotes_gpc'))
			{
				$get_magic_quotes_exists = true;
			}

			foreach ($myPost as $key => $value)
			{
				if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1)
				{
					$value = urlencode(stripslashes($value));
				}
				else
				{
					$value = urlencode($value);
				}

				$req .= "&$key=$value";
			}

			$verify_url = ( $params->get('shop_environment') == 'sandbox' ) ? 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr' : 'https://ipnpb.paypal.com/cgi-bin/webscr';

			$ch = curl_init($verify_url);
			curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
			curl_setopt($ch, CURLOPT_POST, 1);
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
			curl_setopt($ch, CURLOPT_SSLVERSION, 6);
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
			curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
			curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
			$res = curl_exec($ch);

			if (! ($res))
			{
				$errno = curl_errno($ch);
				$errstr = curl_error($ch);
				Log::add("cURL error: [$errno] $errstr", Log::WARNING, 'com_spbooking');

				// Curl_close($ch);
			}

			$info = curl_getinfo($ch);
			$http_code = $info['http_code'];

			if ($http_code != 200)
			{
				Log::add("PayPal responded with http code $http_code", Log::WARNING, 'com_spbooking');
			}

			curl_close($ch);

			if ($res == 'VERIFIED')
			{
				// Check whether the payment_status is Completed
				if ($params->get('shop_environment') == 'sandbox')
				{
					$payment_conditions = $params->get('paypal_id') == $input->get('receiver_email', null, 'RAW');
				}
				else
				{
					$payment_conditions = ($input->get('payment_status') == 'Completed') && ($params->get('paypal_id') == $input->get('receiver_email', null, 'EMAIL'));
				}

				if ($payment_conditions)
				{
					for ($i = 1; $i <= $input->get('num_cart_items', 1); $i++)
					{
						$custom             = $input->get('custom', 'NULL', 'STRING');
						$custom_decode      = json_decode($custom);
						$user_id            = $custom_decode->userid;

						// $user_info          = Factory::getUser($custom_decode->userid);
						$order_type         = $custom_decode->order_type;
						$itemid             = $custom_decode->itemid;
						$useremail          = $custom_decode->useremail;
						$username 	        = $custom_decode->username;
						$item_number        = $input->get('item_number' . $i, null, 'STRING');
						$item_name			= $input->get('item_name' . $i, '', 'STRING');
						$payment_amount     = $input->get('mc_gross_' . $i);
						$payment_currency   = $input->get('mc_currency');
						$txn_id             = $input->get('txn_id');
						$booked_id          = $input->get('invoice');
						$payment_status     = $input->get('payment_status', null, 'WORD');

						$orderinfo = array(
							'user_id' => $user_id,
							'order_type' => $order_type,
							'itemid' => $itemid,
							'payment_amount' => $payment_amount,
							'payment_currency' => $payment_currency,
							'txn_id' => $txn_id,
							'item_number' => $item_number,
							'booked_id' => $booked_id,
							'order_type' => $order_type,
							'payment_type' => 'paypal',
							'payment_status' => $payment_status);

						$dublicate_item = $model->getDublicateTransaction($booked_id, $order_type, $txn_id);

						if ($dublicate_item == false)
						{
							// File_put_contents( __DIR__ .'/iteminfob.txt', json_encode('success') );
							$insertorder = $model->storeOrder($orderinfo);

							if ($insertorder && isset($useremail) && $useremail)
							{
								// Self::sendPurchasdeMail($useremail);
								$msgBody = $params->get('success_mail_template', '');
								$emailData = array(
									"username" => $username,
									"item_title" => $item_name,
									"booking_id" => $booked_id,
									'item_id' => $itemid,
									"payment_for" => $order_type
								);
								$this->sendPurchasedEmail($useremail, $msgBody, $emailData, 'COM_SPBOOKING_PAYLATER_ORDER_SUBMITED');
							}
						}
					}
				} // END:: payment_conditions
			}
			elseif (($input->get('payment_status') == 'Pending'))
			{
				for ($i = 1; $i <= $input->get('num_cart_items', 1); $i++)
				{
					$custom             = $input->get('custom', 'NULL', 'STRING');
					$custom_decode      = json_decode($custom);
					$user_id            = $custom_decode->userid;

					// $user_info          = Factory::getUser($custom_decode->userid);
					$order_type         = $custom_decode->order_type;
					$itemid             = $custom_decode->itemid;
					$useremail          = $custom_decode->useremail;
					$username 	        = $custom_decode->username;
					$item_number        = $input->get('item_number' . $i, null, 'STRING');
					$item_name			= $input->get('item_name' . $i, '', 'STRING');
					$payment_amount     = $input->get('mc_gross_' . $i, null, 'STRING');
					$payment_currency   = $input->get('mc_currency', null, 'STRING');
					$txn_id             = $input->get('txn_id', null, 'STRING');
					$booked_id          = $input->get('invoice', null, 'STRING');
					$payment_status     = $input->get('payment_status', null, 'WORD');

					$orderinfo = array(
						'user_id' => $user_id,
						'order_type' => $order_type,
						'itemid' => $itemid,
						'payment_amount' => $payment_amount,
						'payment_currency' => $payment_currency,
						'txn_id' => $txn_id,
						'item_number' => $item_number,
						'booked_id' => $booked_id,
						'order_type' => $order_type,
						'payment_type' => 'paypal',
						'payment_status' => $payment_status);

					$dublicate_item = $model->getDublicateTransaction($booked_id, $order_type, $txn_id);

					if ($dublicate_item == false)
					{
						$insertorder = $model->storeOrder($orderinfo);

						if ($insertorder && isset($useremail) && $useremail)
						{
							// Self::sendPurchasdeMail($useremail);
							$msgBody = $params->get('success_mail_template', '');
							$emailData = array(
								"username" => $username,
								"item_title" => $item_name,
								"booking_id" => $booked_id,
								'item_id' => $itemid,
								"payment_for" => $order_type
							);
							$this->sendPurchasedEmail($useremail, $msgBody, $emailData, 'COM_SPBOOKING_PAYLATER_ORDER_SUBMITED');
						}
					}
				}
			}
			else
			{
				// End Verified
				if (($input->get('payment_status') == 'Refunded') || ($input->get('payment_status') == 'Reversed'))
				{
					$txn_id 			= $input->get('txn_id');
					$custom             = $input->get('custom', 'NULL', 'STRING');
					$custom_decode      = json_decode($custom);
					$itemid             = $custom_decode->itemid;
					$booked_id          = $input->get('invoice', 'NULL', 'STRING');
					$payment_status     = $input->get('payment_status', null, 'WORD');

					$orderinfo = array(
						'txn_id' => $txn_id,
						'itemid' => $itemid,
						'payment_type' => 'paypal',
						'booked_id' => $booked_id,
						'payment_status' => $payment_status
					);

					$model->refundOrder($orderinfo);
				}
			}
		}
	}

	// Pay later
	public function paylater()
	{

		$input = Factory::getApplication()->input;
		$cartdata = $input->get('cdata', '', 'STRING');
		$cartdata_decode = unserialize(base64_decode($cartdata));
		$params = ComponentHelper::getParams('com_spbooking');

		// Load payment model
		BaseDatabaseModel::addIncludePath(JPATH_SITE . '/components/com_spbooking/models');
		$model = BaseDatabaseModel::getInstance('Payment', 'SpbookingModel');

		if (isset($cartdata_decode) && is_array($cartdata_decode))
		{
			if (count((array) $cartdata_decode))
			{
				$model->storeOrder($cartdata_decode);
				$msgBody = $params->get('success_mail_template', '');
				$emailData = array(
					"username" => $cartdata_decode['username'],
					"item_title" => $cartdata_decode['item_title'],
					"booking_id" => $cartdata_decode['booked_id'],
					"item_id" => $cartdata_decode['itemid'],
					"payment_for" => $cartdata_decode['order_type']
				);
				$this->sendPurchasedEmail($cartdata_decode['useremail'], $msgBody, $emailData, 'COM_SPBOOKING_PAYLATER_ORDER_SUBMITED');

				// Factory::getApplication()-> enqueueMessage(Text::_('COM_SPBOOKING_PAYLATER_ORDER_SUBMITED'), 'success');
			}
			else
			{
				Factory::getApplication()-> enqueueMessage(Text::_('COM_SPBOOKING_NO_ITEM_IN_CART'), 'warning');
			}
		}
		else
		{
			Factory::getApplication()-> enqueueMessage(Text::_('COM_SPBOOKING_SOMETHING_WRONG'), 'warning');
		}
	}

	private function sendPurchasedEmail($receiver, $msgBody, $emailData, $success_message)
	{
		$mailer = Factory::getMailer();
		$config = Factory::getConfig();
		$app    = Factory::getApplication();
		$sender = array($config->get('mailfrom', 'install@install.com'), $config->get('fromname', 'travus'));
		$cParams = ComponentHelper::getParams('com_spbooking');
		$subject = Text::sprintf('COM_SPBOOKING_INVOICE_SUBJECT', $emailData['item_title']);

		$invoice_link = Uri::root() . 'index.php?option=com_spbooking&view=invoice';

		if ($emailData['payment_for'] == 'package')
		{
			$invoice_link .= '&layout=package';
		}
		elseif ($emailData['payment_for'] == 'transport')
		{
			$invoice_link .= '&layout=transport';
		}

		$invoice_link .= '&id=' . $emailData['item_id'] . '&booking_id=' . $emailData['booking_id'];

		$body = nl2br($msgBody);

		$body = str_replace("{name}", $emailData['username'], $body);
		$body = str_replace("{item_title}", "<strong>" . $emailData['item_title'] . "</strong>", $body);
		$body = str_replace("{invoice_link}", "<p><a class='spbooking-btn spbooking-btn-primary' href='" . $invoice_link . "'>Invoice Link</a></p>", $body);
		$body = str_replace("{site_name}", "<p>" . $config->get('fromname', 'travus') . "</p>", $body);

		$mailer->setSender($sender);
		$mailer->addRecipient(trim($receiver));
		$mailer->setSubject($subject);
		$mailer->isHTML(true);
		$mailer->Encoding = 'base64';
		$mailer->setBody($body);

		// Send email
		if ($mailer->Send())
		{
			$this->setRedirect($invoice_link, Text::_($success_message));
		}
		else
		{
			$app->enqueueMessage(Text::_('COM_SPBOOKING_ERROR_OCCUR_SENDING_EMAIL'), 'error');
		}
	}

	public function savePaymentInfo()
	{
		$input  = Factory::getApplication()->input->post;
		$app    = Factory::getApplication();
		$payment_type       = $input->get('payment_type', '', 'STRING');
		$paypal_paid        = $input->get('paypal_paid', 0, 'NUMBER');
		$paylater_paid      = $input->get('paylater_paid', 0, 'NUMBER');
		$stripe_paid        = $input->get('stripe_paid', 0, 'NUMBER');
		$booked_id          = $input->get('booked_id', '', 'STRING');
		$pay_for            = $input->get('pay_for', '', 'STRING');
		$paid               = 0;

		if ($payment_type == 'paypal')
		{
			$paid = $paypal_paid;
		}
		elseif ($payment_type == 'pay_later')
		{
			$paid = $paylater_paid;
		}
		elseif ($payment_type == 'stripe')
		{
			$paid = $stripe_paid;
		}

		// Generating invoice link
		$invoice_link = Uri::root() . 'index.php?option=com_spbooking&view=invoice';

		if ($pay_for == 'package')
		{
			$invoice_link .= '&layout=package';
		}
		elseif ($pay_for == 'transport')
		{
			$invoice_link .= '&layout=transport';
		}

		// Update the booking status from in_approve to pending
		$fields = array();
		$conditions = array();
		$db = Factory::getDbo();
		$query = $db->getQuery(true);

		$fields[] = $db->quoteName('payment_type') . ' = ' . $db->quote($payment_type);
		$fields[] = $db->quoteName('total_paid') . ' = ' . $db->quote($paid);
		$fields[] = $db->quoteName('booking_status') . ' = ' . $db->quote('pending');

		$conditions[] = $db->quoteName('booked_id') . ' = ' . $db->quote($booked_id);
		$conditions[] = $db->quoteName('published') . ' = 1';

		$query->update($db->quoteName('#__spbooking_bookings'))->set($fields)->where($conditions);

		$db->setQuery($query);
		$result = $db->execute();
		unset($db, $query);

		if (!empty($result))
		{
			// Send mail to the user with invoice link
			$db = Factory::getDbo();
			$query = $db->getQuery(true);
			$query->select('id, email, booked_id')
				->from($db->quoteName('#__spbooking_bookings'))
				->where($db->quoteName('booked_id') . ' = ' . $db->quote($booked_id))
				->where($db->quoteName('published') . ' = 1');

			$db->setQuery($query);
			$booking = $db->loadObject();

			$invoice_link .= '&id=' . $booking->id . '&booking_id=' . $booking->booked_id;

			if (!empty($booking))
			{
				$mailer = Factory::getMailer();
				$config = Factory::getConfig();

				$subject = Text::sprintf('COM_SPBOOKING_INVOICE_SUBJECT');
				$body = array();
				$body[] = "<p>" . Text::_('COM_SPBOOKING_RESERVATION_CONGRATULATIONS') . "</p>";
				$body[] = "<p>" . Text::sprintf('COM_SPBOOKING_RESERVATION_INVOICE_LINK', $invoice_link) . "</p>";

				$sender = array($config->get('mailfrom', 'install@install.com'), $config->get('fromname', 'jeetravel'));
				$mailer->setSender($sender);
				$mailer->addRecipient(trim($booking->email));
				$mailer->setSubject($subject);
				$mailer->isHTML(true);
				$mailer->Encoding = 'base64';
				$mailer->setBody(implode("\n", $body));

				if ($mailer->Send())
				{
					$app->redirect($invoice_link, Text::_('COM_SPBOOKING_BOOKING_COMPLETED'));
				}
				else
				{
					$app->enqueueMessage(Text::_('COM_SPBOOKING_ERROR_OCCUR_SENDING_EMAIL'), 'error');
				}
			}
			else
			{
				$app->enqueueMessage(Text::_('COM_SPBOOKING_INVOICE_ERROR'), 'error');
			}
		}
		else
		{
			$app->enqueueMessage(Text::_('COM_SPBOOKING_ERROR_UPDATING_RECORDS'), 'error');
		}
	}

	public function stripeSuccess()
	{
		$input = Factory::getApplication()->input;

		$params = ComponentHelper::getParams('com_spbooking');

		// Load Lessons model
		BaseDatabaseModel::addIncludePath(JPATH_SITE . '/components/com_spbooking/models');
		$model = BaseDatabaseModel::getInstance('Payment', 'SpbookingModel');

		$stripe = new Stripe\StripeClient($params->get('stripe_key'));

		$stripe_retrieve = $stripe->checkout->sessions->retrieve(
			$input->get('session_id'),
			[]
		);

		if ($stripe_retrieve->payment_status == 'paid' && $stripe_retrieve->status == 'complete')
		{
			$orderinfo = array(
				'user_id' 			=> $stripe_retrieve->metadata->user_id,
				'order_type' 		=> $stripe_retrieve->metadata->order_type,
				'itemid' 			=> $stripe_retrieve->metadata->itemid,
				'booked_id' 		=> $stripe_retrieve->metadata->booked_id,
				'order_type' 		=> $stripe_retrieve->metadata->order_type,
				'payment_type' 		=> 'stripe',
				'payment_status'	=> $stripe_retrieve->metadata->payment_status,
				'payment_amount'	=> $stripe_retrieve->metadata->payment_amount,
				'txn_id'			=> $stripe_retrieve->payment_intent
			);

			$useremail = $stripe_retrieve->metadata->useremail;
			$insertorder = $model->storeOrder($orderinfo);

			if ($insertorder && isset($useremail) && $useremail)
			{
				$msgBody = $params->get('success_mail_template', '');
				$emailData = array(
					"username" 		=> $stripe_retrieve->metadata->username,
					"item_title" 	=> $stripe_retrieve->metadata->item_title,
					"booking_id" 	=> $stripe_retrieve->metadata->booked_id,
					'item_id' 		=> $stripe_retrieve->metadata->itemid,
					"payment_for"	=> $stripe_retrieve->metadata->order_type,
				);
				self::sendPurchasedEmail($useremail, $msgBody, $emailData, 'COM_SPBOOKING_PAYMENT_SUCCESSFUL');
			}

			// Factory::getApplication()->enqueueMessage(Text::_('COM_SPBOOKING_PAYMENT_SUCCESSFUL'), 'success');
		}

	}
}

