<?php
if (!defined("ROOT_PATH"))
{
	header("HTTP/1.1 403 Forbidden");
	exit;
}
class pjStripe extends pjStripeAppController
{
	protected static $logPrefix = "Payments | pjStripe plugin<br>";

	/* ------------------------------------------------------------------ *
	 *  Admin: settings form + transactions grid
	 * ------------------------------------------------------------------ */
	public function pjActionIndex()
	{
		$this->checkLogin();

		if ($this->isAdmin())
		{
			if (isset($_POST['stripe_post']))
			{
				$this->saveOption('plugin_stripe_public_key', @$_POST['plugin_stripe_public_key']);
				$this->saveOption('plugin_stripe_secret_key', @$_POST['plugin_stripe_secret_key']);
				$this->saveOption('plugin_stripe_cancel_url', @$_POST['plugin_stripe_cancel_url']);

				pjUtil::redirect($_SERVER['PHP_SELF'] . "?controller=pjStripe&action=pjActionIndex&err=PST02");
			}

			$this->appendJs('jquery.datagrid.js', PJ_FRAMEWORK_LIBS_PATH . 'pj/js/');
			$this->appendJs('pjStripe.js', $this->getConst('PLUGIN_JS_PATH'));
			$this->appendJs('index.php?controller=pjAdmin&action=pjActionMessages', PJ_INSTALL_URL, true);
		} else {
			$this->set('status', 2);
		}
	}

	private function saveOption($key, $value)
	{
		$pjOptionModel = pjOptionModel::factory();
		if (0 != $pjOptionModel
			->where('foreign_id', $this->getForeignId())
			->where('`key`', $key)
			->findCount()->getData()
		)
		{
			$pjOptionModel->limit(1)->modifyAll(array('value' => $value));
		} else {
			$pjOptionModel->reset()->setAttributes(array(
				'foreign_id' => $this->getForeignId(),
				'key' => $key,
				'tab_id' => '99',
				'value' => $value,
				'type' => 'string',
				'is_visible' => 0
			))->insert();
		}
	}

	public function pjActionGetStripe()
	{
		$this->setAjax(true);

		if ($this->isXHR() && $this->isLoged() && $this->isAdmin())
		{
			$pjStripeModel = pjStripeModel::factory();

			if (isset($_GET['q']) && !empty($_GET['q']))
			{
				$q = $pjStripeModel->escapeStr($_GET['q']);
				$q = str_replace(array('%', '_'), array('\%', '\_'), $q);
				$pjStripeModel->where("(t1.txn_id LIKE '%$q%' OR t1.reference_id LIKE '%$q%')");
			}

			$column = 'created';
			$direction = 'DESC';
			if (isset($_GET['direction']) && isset($_GET['column']) && in_array(strtoupper($_GET['direction']), array('ASC', 'DESC')))
			{
				$column = $_GET['column'];
				$direction = strtoupper($_GET['direction']);
			}

			$total = $pjStripeModel->findCount()->getData();
			$rowCount = isset($_GET['rowCount']) && (int) $_GET['rowCount'] > 0 ? (int) $_GET['rowCount'] : 10;
			$pages = ceil($total / $rowCount);
			$page = isset($_GET['page']) && (int) $_GET['page'] > 0 ? intval($_GET['page']) : 1;
			$offset = ((int) $page - 1) * $rowCount;
			if ($page > $pages)
			{
				$page = $pages;
			}

			$data = $pjStripeModel->orderBy("$column $direction")->limit($rowCount, $offset)->findAll()->getData();
			foreach ($data as &$item)
			{
				if (!empty($item['created']))
				{
					$ts = strtotime($item['created']);
					$date = date('Y-m-d', $ts);
					$time = date('H:i:s', $ts);
					if (!empty($this->option_arr['o_date_format']))
					{
						$date = date($this->option_arr['o_date_format'], $ts);
					}
					if (!empty($this->option_arr['o_time_format']))
					{
						$time = date($this->option_arr['o_time_format'], $ts);
					}
					$item['created'] = $date . ', ' . $time;
				} else {
					$item['created'] = NULL;
				}
			}

			pjAppController::jsonResponse(compact('data', 'total', 'pages', 'page', 'rowCount', 'column', 'direction'));
		}
		exit;
	}

	/* ------------------------------------------------------------------ *
	 *  Payment flow (reusable)
	 * ------------------------------------------------------------------ */

	/**
	 * Renders the redirect-to-Stripe view.
	 * Params: reference_id, amount, currency_code, item_name, return_url (optional)
	 */
	public function pjActionForm()
	{
		$this->setLayout('pjActionEmpty');
		$this->setAjax(true);
		$this->set('arr', $this->getParams());
	}

	/**
	 * Creates a Checkout Session and returns its id/url as JSON.
	 * Called by the redirect view (POST JSON body).
	 */
	public function pjActionCreateOrder()
	{
		$this->setAjax(true);
		$this->setLayout('pjActionEmpty');

		$input = file_get_contents('php://input');
		$post = json_decode($input, true);
		$cart = isset($post['cart']) ? $post['cart'] : array();

		$reference_id = isset($cart['reference_id']) ? $cart['reference_id'] : '';
		$return_url = isset($cart['return_url']) ? $cart['return_url'] : '';
		$currency = isset($cart['currency']) && $cart['currency'] !== '' ? $cart['currency'] : @$this->option_arr['o_currency'];
		$amount = isset($cart['amount']) ? $cart['amount'] : 0;
		$description = isset($cart['description']) ? $cart['description'] : '';

		$success_url = PJ_INSTALL_URL . "index.php?controller=pjStripe&action=pjActionReturn"
			. "&reference_id=" . rawurlencode($reference_id)
			. "&return_url=" . rawurlencode($return_url)
			. "&session_id={CHECKOUT_SESSION_ID}";

		$cancel_url = !empty($return_url)
			? $return_url
			: (!empty($this->option_arr['plugin_stripe_cancel_url'])
				? $this->option_arr['plugin_stripe_cancel_url']
				: PJ_INSTALL_URL . "index.php?controller=pjStripe&action=pjActionIndex");

		$pjStripeApi = new pjStripeApi();
		$result = $pjStripeApi
			->setSecretKey(@$this->option_arr['plugin_stripe_secret_key'])
			->createSession(array(
				'reference_id' => $reference_id,
				'amount' => $amount,
				'currency' => $currency,
				'description' => $description,
				'success_url' => $success_url,
				'cancel_url' => $cancel_url
			));

		if ($pjStripeApi->getError() !== NULL)
		{
			$this->log(self::$logPrefix . "createOrder error: " . $pjStripeApi->getError());
			pjAppController::jsonResponse(array('error' => $pjStripeApi->getError()));
		}

		pjAppController::jsonResponse(array(
			'id' => @$result['id'],
			'url' => @$result['url']
		));
	}

	/**
	 * Default hosted-checkout return handler: verifies the session, records the
	 * transaction, then redirects back to return_url (or the admin grid).
	 */
	public function pjActionReturn()
	{
		$reference_id = isset($_GET['reference_id']) ? $_GET['reference_id'] : '';
		$return_url = isset($_GET['return_url']) && !empty($_GET['return_url'])
			? $_GET['return_url']
			: PJ_INSTALL_URL . "index.php?controller=pjStripe&action=pjActionIndex";

		if (empty($_GET['session_id']))
		{
			pjUtil::redirect($return_url);
		}

		list($ok, $session) = $this->verifySession($_GET['session_id']);

		if ($ok)
		{
			$this->recordTransaction($reference_id, $session);
			$this->log(self::$logPrefix . "Payment recorded. Session: " . $session['id']);
			$glue = strpos($return_url, '?') === FALSE ? '?' : '&';
			pjUtil::redirect($return_url . $glue . "err=PST01");
		}

		pjUtil::redirect($return_url);
	}

	/**
	 * requestAction-callable verification for a custom trigger that wants to run
	 * its own activation logic. Mirrors the pjPaypal::pjActionConfirm contract.
	 * Params: session_id, key, [deposit], [currency], [reference_id]
	 */
	public function pjActionConfirm()
	{
		$this->setAjax(true);
		$this->setLayout('pjActionEmpty');

		$params = $this->getParams();
		$response = array('status' => 'FAIL');

		if (!isset($params['key']) || $params['key'] != md5($this->option_arr['private_key'] . PJ_SALT))
		{
			$this->log(self::$logPrefix . "Missing or invalid 'key' parameter.");
			return $response;
		}
		if (empty($params['session_id']))
		{
			$this->log(self::$logPrefix . "Missing 'session_id' parameter.");
			return $response;
		}

		list($ok, $session) = $this->verifySession($params['session_id']);
		if (!$ok)
		{
			$response['status'] = is_array($session) && isset($session['payment_status']) ? $session['payment_status'] : 'UNKNOW';
			return $response;
		}

		if (isset($params['deposit']))
		{
			$expected = pjStripeApi::toMinorUnits($params['deposit'], @$params['currency']);
			if (isset($session['amount_total']) && (int) $session['amount_total'] != $expected)
			{
				$this->log(self::$logPrefix . "AMOUNT didn't match.");
				return $response;
			}
		}
		if (isset($params['currency']) && isset($session['currency']) && strtolower($session['currency']) != strtolower($params['currency']))
		{
			$this->log(self::$logPrefix . "CURRENCY didn't match.");
			return $response;
		}

		$this->recordTransaction(@$params['reference_id'], $session);

		$txn_id = @$session['payment_intent'];
		$response['status'] = 'OK';
		$response['txn_id'] = $txn_id;
		$response['transaction_id'] = $txn_id;

		return $response;
	}

	/* ------------------------------------------------------------------ *
	 *  Internals
	 * ------------------------------------------------------------------ */
	private function verifySession($session_id)
	{
		$pjStripeApi = new pjStripeApi();
		$session = $pjStripeApi
			->setSecretKey(@$this->option_arr['plugin_stripe_secret_key'])
			->retrieveSession($session_id);

		if (!is_array($session) || $pjStripeApi->getError() !== NULL || !isset($session['id']))
		{
			$this->log(self::$logPrefix . "Unable to retrieve session " . $session_id);
			return array(FALSE, $session);
		}
		if (@$session['payment_status'] != 'paid')
		{
			$this->log(self::$logPrefix . "Session not paid: " . @$session['payment_status']);
			return array(FALSE, $session);
		}

		return array(TRUE, $session);
	}

	private function recordTransaction($reference_id, $session)
	{
		$currency = isset($session['currency']) ? strtoupper($session['currency']) : NULL;
		$amount = NULL;
		if (isset($session['amount_total']))
		{
			$zero = in_array((string) $currency, array('BIF','CLP','DJF','GNF','JPY','KMF','KRW','MGA','PYG','RWF','UGX','VND','VUV','XAF','XOF','XPF'));
			$amount = $zero ? (float) $session['amount_total'] : (float) $session['amount_total'] / 100;
		}

		return pjStripeModel::factory()->reset()->setAttributes(array(
			'reference_id' => $reference_id,
			'session_id'   => @$session['id'],
			'txn_id'       => @$session['payment_intent'],
			'amount'       => $amount,
			'currency'     => $currency,
			'payer_email'  => @$session['customer_details']['email'],
			'status'       => @$session['payment_status']
		))->insert()->getInsertId();
	}
}
?>
