<?php
/**
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License version 3.0
* that is bundled with this package in the file LICENSE.md
* It is also available through the world-wide-web at this URL:
* https://opensource.org/license/osl-3-0-php
* 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 support@qloapps.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade this module to a newer
* versions in the future. If you wish to customize this module for your needs
* please refer to https://store.webkul.com/customisation-guidelines for more information.
*
* @author Webkul IN
* @copyright Since 2010 Webkul
* @license https://opensource.org/license/osl-3-0-php Open Software License version 3.0
*/

class AdminPaypalCommerceTransactionController extends ModuleAdminController
{
    public function __construct()
    {
        $this->identifier = 'id_paypal_commerce_order';
        parent::__construct();

        $this->bootstrap = true;
        $this->list_no_link = true;

        $this->table = 'wk_paypal_commerce_order';
        $this->className = 'WKPayPalCommerceOrder';

        $this->_select = 'a.*, CONCAT(c.firstname, \' \', c.lastname) as customer_name, c.email';
        $this->_join = ' LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON (c.id_customer = a.id_customer)';
        $this->_where = ' AND a.`id_cart` != 0';
        $this->_orderBy = 'id_paypal_commerce_order';
        $this->_defaultOrderWay = 'DESC';

        $this->toolbar_title = $this->l('PayPal Transactions');

        $this->fields_list = array(
            'order_reference' => array(
                'title' => $this->l('Order Reference'),
                'align' => 'center',
                'havingFilter' => true,
                'hint' => $this->l('Order reference in QloApps of the PayPal transaction'),
            ),
            'pp_transaction_id' => array(
                'title' => $this->l('PayPal Transaction ID'),
                'align' => 'center',
                'class' => 'fixed-width-xs',
                'havingFilter' => true,
                'hint' => $this->l('Id of the PayPal transaction'),
            ),
            'pp_paid_total' => array(
                'title' => $this->l('Transaction Total'),
                'align' => 'center',
                'havingFilter' => true,
                'callback' => 'setCurrency',
                'hint' => $this->l('Total amount paid in the PayPal transaction'),
            ),
            'customer_name' => array(
                'title' => $this->l('Customer'),
                'align' => 'center',
                'havingFilter' => true,
                'align' => 'center',
                'callback' => 'getCustomerInfo',
                'havingFilter' => true,
                'filter_key' => 'customer_name',
                'hint' => $this->l('Customer in the QloApps who did PayPal transaction.'),
            ),
            'pp_payment_status' => array(
                'title' => $this->l('Status'),
                'align' => 'center',
                'class' => 'fixed-width-xs',
                'hint' => $this->l('Payment Status'),
                'orderBy' => false,
                'hint' => $this->l('Current status of the PayPal transaction.'),
            ),
            'order_date' => array(
                'title' => $this->l('Order Date'),
                'type' => 'datetime',
                'align' => 'center',
                'hint' => $this->l('Date of order creation.'),
            )
        );
    }

    public function getCustomerInfo($customerName, $row)
    {
        return '<a href="'.$this->context->link->getAdminLink('AdminCustomers').'&id_customer='.$row['id_customer'].'&viewcustomer">'.$customerName.'<br>'.'('.$row['email'].')</a>';
    }

    public function setCurrency($val, $row)
    {
        $objCart = new Cart($row['id_cart']);
        $currency = new Currency($objCart->id_currency);

        return Tools::displayPrice($val, $currency);
    }

    public function initPageHeaderToolbar()
    {
        if ($this->display == 'edit' || $this->display == 'add' || $this->display == 'view') {
            $this->page_header_toolbar_btn['back_to_list'] = array(
                'href' => Context::getContext()->link->getAdminLink(
                    'AdminPaypalCommerceTransaction',
                    true
                ),
                'desc' => $this->l('Back to list'),
                'icon' => 'process-icon-back'
            );
        }
        parent::initPageHeaderToolbar();
    }

    public function renderList()
    {
        $this->addRowAction('view');
        return parent::renderList();
    }

    public function initToolbar()
    {
        parent::initToolbar();
        unset($this->toolbar_btn['new']);
    }

    public function renderView()
    {
        $idTrans = (int)Tools::getValue('id_paypal_commerce_order');
        if ($idTrans > 0) {
            $smartyVars = array();
            $refundData = array();
            $totalRefunded = 0;
            $transactionData = WKPayPalCommerceOrder::getTransactionDetails((int)$idTrans);
            $orderCurrency = new Currency((int)$transactionData['id_currency']);
            $refundData = WkPaypalCommerceRefund::getRefundListByTransID((int)$idTrans);
            $totalRefundedFormatted = WkPaypalCommerceRefund::getTotalRefundedAmount((int)$idTrans, true);

            $totalRefunded = WkPaypalCommerceRefund::getTotalRefundedAmount((int)$idTrans, false);
            $remainingRefund = (float)($transactionData['pp_paid_total'] - $totalRefunded);
            $response = Tools::jsonDecode($transactionData['response'], true);

            // Buyer making a payment in a different currency (ex: EUR) which is different from the default currency of merchant (Ex: USD), In all those cross currency cases, After Capture, transaction will fall into Pending state and will require merchant to manually go to his PayPal account and accept the payment.
            $objPPOrder = new WKPayPalCommerceOrder();
            if (isset($response['data']['purchase_units'][0]['payments']['captures'][0]['status_details']['reason'])
                && ($transactionData['pp_payment_status'] == 'PENDING' || $transactionData['pp_payment_status'] == 'DENIED')
                && isset($response['data']['purchase_units'][0]['payments']['captures'][0]['status_details']['reason'])
            ) {
                if (isset($objPPOrder->ppStatusDetail[$response['data']['purchase_units'][0]['payments']['captures'][0]['status_details']['reason']])) {
                    $smartyVars['ppstatusDetailMsg'] = $objPPOrder->ppStatusDetail[$response['data']['purchase_units'][0]['payments']['captures'][0]['status_details']['reason']];
                }
            }

            $smartyVars['transaction_data'] = $transactionData;
            $smartyVars['refund_data'] = $refundData;
            $smartyVars['refunded_amount'] = $totalRefundedFormatted;
            $smartyVars['remaining_refund'] = $remainingRefund;
            $smartyVars['remaining_refund_format'] = Tools::displayPrice($remainingRefund, $orderCurrency);
            $smartyVars['currency'] = $orderCurrency;
            $smartyVars['WK_PAYPAL_COMMERCE_REFUND_TYPE_FULL'] = WkPaypalCommerceRefund::WK_PAYPAL_COMMERCE_REFUND_TYPE_FULL;
            $smartyVars['WK_PAYPAL_COMMERCE_REFUND_TYPE_PARTIAL'] = WkPaypalCommerceRefund::WK_PAYPAL_COMMERCE_REFUND_TYPE_PARTIAL;

            $this->context->smarty->assign($smartyVars);
        }
        $this->base_tpl_view = 'view.tpl';
        return parent::renderView();
    }

    public function postProcess()
    {

        if (Tools::getValue('refund_paypal_form')
            && (Tools::getValue('token')) == Tools::getAdminTokenLite('AdminPaypalCommerceTransaction')
        ) {
            $idTrans = (int)Tools::getValue('id_paypal_commerce_order');
            $refundAmt = (float)Tools::getValue('refund_amount');
            $refundReason = Tools::getValue('refund_reason');
            $refundType = (int)Tools::getValue('refund_type');

            if (!$refundType) {
                $this->errors[] = $this->l('Invalid refund type.');
            }
            if (!Validate::isPrice($refundAmt)) {
                $this->errors[] = $this->l('Invalid refund amount.');
            }
            if (!Validate::isMessage($refundReason)) {
                $this->errors[] = $this->l('Enter valid refund reason (only alphanumeric allowed).');
            }

            if ((!count($this->errors))) {
                $transactionData = WKPayPalCommerceOrder::getTransactionDetails((int)$idTrans);
                if ($transactionData) {
                    $totalRefunded = WkPaypalCommerceRefund::getTotalRefundedAmount((int)$idTrans, false);
                    if ($remainingRefund = (float)($transactionData['pp_paid_total'] - $totalRefunded)) {
                        // if refund type is partial then check the amount to be refunded
                        if (($refundType == WkPaypalCommerceRefund::WK_PAYPAL_COMMERCE_REFUND_TYPE_PARTIAL)
                            && ($refundAmt > $remainingRefund)
                        ) {
                            $orderCurrency = new Currency((int)$transactionData['id_currency']);
                            $this->errors[] = $this->l('Invalid refund amount. Max. available amount for refund is').' '.Tools::displayPrice($remainingRefund, $orderCurrency);
                        }

                        // if no errors the proceed for the refund
                        if ((!count($this->errors))) {
                            if ($refundType == WkPaypalCommerceRefund::WK_PAYPAL_COMMERCE_REFUND_TYPE_FULL) {
                                $refundAmt = (float)($transactionData['pp_paid_total'] - $totalRefunded);
                            }
                            if ($transactionData['pp_paid_total'] == $refundAmt) {
                                $refundType = WkPaypalCommerceRefund::WK_PAYPAL_COMMERCE_REFUND_TYPE_FULL;
                            }
                            if ($refundAmt) {
                                $postData = array();
                                $postData['amount'] = array(
                                    'currency_code' => $transactionData['pp_paid_currency'],
                                    'value' => $refundAmt
                                );
                                $postData['transaction_id'] = $transactionData['pp_transaction_id'];
                                $postData['refund_reason'] = $refundReason;
                                $postData['auth_assertion'] = WkPaypalCommerceHelper::payPalAuthAssertion();

                                WkPaypalCommerceHelper::logMsg('refund', 'Refund initiated...', true);
                                WkPaypalCommerceHelper::logMsg('refund', 'Environment: '. Configuration::get('MP_PAYPAL_PAYMENT_MODE'));
                                WkPaypalCommerceHelper::logMsg('refund', 'Order Ref: '. $transactionData['order_reference']);
                                WkPaypalCommerceHelper::logMsg('refund', 'Customer ID: '. $transactionData['id_customer']);
                                WkPaypalCommerceHelper::logMsg('refund', 'PayPal Transaction ID: '. $transactionData['pp_transaction_id']);
                                WkPaypalCommerceHelper::logMsg('refund', 'PayPal Order ID: '. $transactionData['pp_order_id']);
                                WkPaypalCommerceHelper::logMsg('refund', 'Refund request data: ');
                                WkPaypalCommerceHelper::logMsg('refund', Tools::jsonEncode($postData));

                                $objPPCommerce = new PayPalCommerce();
                                $refundData = $objPPCommerce->orders->refund($postData);

                                // check if refund id is there
                                if (isset($refundData['data']['status']) && isset($refundData['data']['id'])) {
                                    $refundID = $refundData['data']['id'];

                                    WkPaypalCommerceHelper::logMsg('refund', 'Refund success: ', true);
                                    WkPaypalCommerceHelper::logMsg('refund', 'PayPal Refund Id: '. $refundID);
                                    WkPaypalCommerceHelper::logMsg('refund', 'Refund reponse data: ');
                                    WkPaypalCommerceHelper::logMsg('refund', Tools::jsonEncode($refundData));
                                    WkPaypalCommerceHelper::logMsg('refund', '----------------------- ', true);

                                    $refundObj = new WkPaypalCommerceRefund();
                                    $refundObj->order_trans_id = (int)$idTrans;
                                    $refundObj->paypal_refund_id = $refundID;
                                    $refundObj->refund_amount = (float)$refundAmt;
                                    $refundObj->refund_type = (int)$refundType;
                                    $refundObj->currency_code = $transactionData['pp_paid_currency'];
                                    $refundObj->refund_reason = $refundReason;
                                    $refundObj->response = Tools::jsonEncode($refundData);
                                    $refundObj->refund_status = $refundData['data']['status'];
                                    if ($refundObj->save()) {
                                        $urlString = '&viewwk_paypal_commerce_order=&id_paypal_commerce_order=' . (int)Tools::getValue('id_paypal_commerce_order');

                                        Tools::redirectAdmin(self::$currentIndex.$urlString.'&conf=4&token='.$this->token);
                                    }
                                } else {
                                    WkPaypalCommerceHelper::logMsg('refund', 'Refund failed: ', true);
                                    WkPaypalCommerceHelper::logMsg('refund', 'Refund reponse data: ');
                                    WkPaypalCommerceHelper::logMsg('refund', Tools::jsonEncode($refundData));
                                    WkPaypalCommerceHelper::logMsg('refund', '----------------------- ', true);
                                    $this->errors[] = $refundData['data']['message'];
                                }
                            } else {
                                $this->errors[] = $this->l('Refund is already done for this transaction.');
                            }
                        }
                    } else {
                        $this->errors[] = $this->l('Refund is already done for this transaction.');
                    }
                } else {
                    $this->errors[] = $this->l('Invalid request');
                }
            }
        }

        parent::postProcess();
    }

    public function setMedia()
    {
        parent::setMedia();

        $this->addJS(_PS_MODULE_DIR_ . 'qlopaypalcommerce/views/js/admin/wk_paypal_transaction.js');
        $this->addCSS(_PS_MODULE_DIR_ . 'qlopaypalcommerce/views/css/admin/wk_paypal_transaction.css');
    }
}
