<?php
/**
 * 2007-2019 PrestaShop SA and Contributors.
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Academic Free License (AFL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * https://opensource.org/licenses/AFL-3.0
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@prestashop.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
 * versions in the future. If you wish to customize PrestaShop for your
 * needs please refer to http://www.prestashop.com for more information.
 *
 * @author    PrestaShop SA <contact@prestashop.com>
 * @copyright 2007-2019 PrestaShop SA and Contributors
 * @license   https://opensource.org/licenses/AFL-3.0  Academic Free License (AFL 3.0)
 * International Registered Trademark & Property of PrestaShop SA
 */

use Sibs\Models\SibsCardTokens;
use Sibs\Models\SibsOrderRef;
use Sibs\Models\SibsTransaction;
use Sibs\SibsConstants;
use Sibs\SibsException;
use Sibs\SibsLogger;
use Sibs\SibsPaymentCore;
use Sibs\SibsUtils;

/**
 * @property Sibs $module
 */
class SibsValidationModuleFrontController extends ModuleFrontController
{
    /**
     * POST Process.
     *
     * @return void
     */
    public function postProcess()
    {
        SibsLogger::info('start postProcess');

        $transactionID = Tools::getValue('id');
        $credentials   = SibsUtils::getCredentials();

        SibsLogger::info("transactionID: $transactionID");
        SibsLogger::info('credentials: ' . SibsLogger::prettify($credentials));

        $resultJson = SibsPaymentCore::getPaymentStatus($transactionID, $credentials);
        SibsLogger::info('resultJson of getPaymentStatus: ' . json_encode($resultJson));

        try {
            if (! $resultJson) {
                throw new SibsException('ERROR_GENERAL_NORESPONSE');
            }

            $this->validatePaymentResponse($resultJson['response']);
        } catch (SibsException $e) {
            $this->redirectErrorResponse($e->getMessage());
        }
    }

    /**
     * Validate Payment Response.
     *
     * @param array $response
     * @return void
     * @throws SibsException
     */
    private function validatePaymentResponse($response)
    {
        SibsLogger::info('validatePaymentResponse()');

        $returnCode    = $response['returnStatus']['statusCode'];
        $paymentStatus = $response['paymentStatus'];

        SibsLogger::info("returnCode: $returnCode");
        SibsLogger::info("paymentStatus: $paymentStatus");
        SibsLogger::info('Response: ' . SibsLogger::prettify($response));

        $transactionResult = SibsPaymentCore::getTransactionResult($returnCode, $paymentStatus);
        SibsLogger::info("transactionResult: $transactionResult");

        switch($transactionResult) {
            case SibsConstants::SIBS_ACK:
                SibsLogger::info('ACK payment');
                $this->doSuccessPayment($response, $paymentStatus);

                break;
            case SibsConstants::SIBS_NOK:
                try {
                    SibsTransaction::deleteTransactionsSibs($response['transactionID']);
                } catch (Exception $e) {
                    SibsLogger::info('transactionResult ERRO : ' . $e->getMessage());
                }

                throw new SibsException($returnCode);

                break;
            default:
                throw new SibsException('ERROR_UNKNOWN');
        }
    }

    /**
     * Order Exists.
     *
     * @param int $cart_id
     * @return bool
     */
    public function orderExists($cart_id)
    {
        $sql    = 'SELECT count(*) FROM `' . _DB_PREFIX_ . 'orders` WHERE `id_cart` = ' . (int) $cart_id;
        $result = (bool) Db::getInstance()->getValue($sql);

        return $result;
    }

    /**
     * Order ID.
     *
     * @param int $cart_id
     * @return array
     */
    public function orderID($cart_id)
    {
        $sql    = 'SELECT * FROM `' . _DB_PREFIX_ . 'orders` WHERE `id_cart` = ' . (int) $cart_id;
        $result = Db::getInstance()->getValue($sql);

        return $result;
    }

    /**
     * Do Success payment.
     *
     * @param array $response
     * @param string $paymentStatus
     * @return void
     * @throws SibsException
     */
    public function doSuccessPayment($response, $paymentStatus)
    {
        SibsLogger::info('doSuccessPayment()');

        $paymentMethodTools = Tools::getValue('payment_method');
        $paymentMethod      = $response['paymentMethod'];
        $paymentType        = $response['paymentType'];
        $id_transaction     = $response['transactionID'];
        $id_order_state     = SibsPaymentCore::sibs_convert_response_status_to_payment_status($paymentMethod, $paymentStatus);

        SibsLogger::info("paymentMethodTools: $paymentMethodTools");
        SibsLogger::info("paymentMethod: $paymentMethod");
        SibsLogger::info("paymentType: $paymentType");
        SibsLogger::info("transactionID: $id_transaction");
        SibsLogger::info("id_order_state: $id_order_state");

        SibsLogger::info("id_order_state: $id_order_state");
        SibsLogger::info("paymentStatus: $paymentStatus");
        SibsLogger::info('merchant: ' . ($response['merchant']['merchantTransactionId'] ?? 0));
        SibsLogger::info('id_order_state: ' . SibsConstants::ORDER_STATUS_CANCELED);

        if ($id_order_state === SibsConstants::ORDER_STATUS_CANCELED) {
            throw new SibsException('ORDER_CANCELED');
        }

        $customer = new Customer($this->context->cart->id_customer);
        $currency = new Currency($this->context->cart->id_currency);

        $id_module          = $this->module->id;
        $id_cart            = (int) $this->context->cart->id;
        $id_customer        = $customer->id;
        $secure_key         = $customer->secure_key;
        $currency_id        = (int) $currency->id;
        $extraVars          = ['transaction_id' => $id_transaction];
        $amountPaid         = (float) $this->context->cart->getOrderTotal(true, Cart::BOTH);
        $paymentDescription = $this->module->getPaymentDescription($paymentMethodTools);
        $message            = $this->l('Paid by SIBS');

        SibsLogger::info("id_module: $id_module");
        SibsLogger::info("id_cart: $id_cart");
        SibsLogger::info("id_customer: $id_customer");
        SibsLogger::info("secure_key: $secure_key");
        SibsLogger::info("id_currency: $currency_id");
        SibsLogger::info('extraVars: ' . SibsLogger::prettify($extraVars));
        SibsLogger::info("orderTotal: $amountPaid");
        SibsLogger::info("paymentDescription: $paymentDescription");
        SibsLogger::info("message: $message");

        SibsOrderRef::saveTransactionLog($id_cart, $paymentMethod, $response);

        $tmp_order = $response['merchant']['merchantTransactionId'] ?? 0;

        $validateOrder = $this->orderExists($tmp_order);
        $orderID       = $this->orderID($tmp_order);

        SibsLogger::info('validateOrder: (orderID: ' . $orderID . ')');

        if ($validateOrder != true) {
            $this->module->validateOrder(
                $id_cart,
                $id_order_state,
                $amountPaid,
                $paymentDescription,
                $message,
                $extraVars,
                $currency_id,
                false,
                $secure_key
            );
            SibsLogger::info('validateOrder()');

            $id_order = $this->module->currentOrder;
            SibsLogger::info("id_order: $id_order");
        } else {
            $id_order = $orderID;
            SibsLogger::info("id_order: $id_order");
        }

        SibsOrderRef::updateTransLogId($id_order, $id_transaction);

        // SAVE PAYMENT TOKEN
        $hasToken = isset($response['token']);
        SibsLogger::info('hasToken ' . var_export($hasToken, true));

        if ($hasToken) {
            $customerID = $this->context->cart->id_customer;
            $token      = $response['token'];

            SibsLogger::info('customerID: ' . $customerID);
            SibsLogger::info('token: ' . SibsLogger::prettify($token));

            SibsCardTokens::saveToken($customerID, $token);
        }

        SibsLogger::info('end doSuccessPayment()');

        Tools::redirect(
            "index.php?controller=order-confirmation&id_cart={$id_cart}&id_module={$id_module}&id_order={$id_order}&key={$secure_key}"
        );
    }

    /**
     * Redirect Error Response.
     *
     * @param string $returnMessage
     * @return void
     */
    public function redirectErrorResponse($returnMessage)
    {
        $this->errors[] = $returnMessage;
        $this->redirectWithNotifications(
            $this->context->link->getPageLink('order', true, null, ['step' => '3'])
        );
    }
}
