<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Created by DT Team.
 * AppName: NearbyStores
 */

require_once(APPPATH . 'modules/payment/libraries/paypal-php-sdk/autoload.php');


class Payment extends MAIN_Controller
{

    public $_api_context;

    const MODULE = "payment";
    const PAID_SUCCESS = "p_success";
    const PAID_FAILED = "p_failed";

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

        /////// register module ///////
        $this->init("payment");

    }

    public function onLoad()
    {
        define('CONFIG_PAYMENT', 'config_payment');
        define('DISPLAY_LIST_TRANSACTIONS', 'display_transactions');
        define('DISPLAY_LIST_BILLING', 'display_billing');
        define('MANAGE_TAXES', 'manage_taxes');

        //load model
        $this->load->model("payment/payment_model", 'mPaymentModel');
        $this->load->model("setting/currency_model", 'mCurrencyModel');
        $this->load->model("payment/tax_model", 'mTaxModel');
        $this->load->helper("payment/payment");

    }


    public function onCommitted($isEnabled)
    {

        if (!$isEnabled)
            return;

        $this->load->config('config');

        //init config
        if (!defined('DEFAULT_TAX'))
            $this->mConfigModel->save('DEFAULT_TAX', 0);


        AdminTemplateManager::registerMenu(
            'payment',
            "payment/menu",
            11
        );


        if ($this->mUserBrowser->isLogged()) {
            $user_id = $this->mUserBrowser->getData("id_user");
        }

        //setup payment for waller
        $payment_redirection = site_url("payment/make_payment");
        $payment_callback_success = site_url("payment/payment_success");
        $payment_callback_error = site_url("payment/payment_error");


        $payments = array(
            array(
                'id' => PaymentsProvider::PAYPAL_ID,
                'payment' => _lang("PayPal"),
                'image' => AdminTemplateManager::assets("payment", "img/paypal-logo.png"),
                'description' => 'Pay using PayPal.com',
                'processorCallback' => payPalProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::STRIPE_ID,
                'payment'=>  _lang("Debit & Credit Card"),
                'image'=> AdminTemplateManager::assets("payment","img/stripe.png"),
                'description'=>  _lang('Pay using Stripe.com'),
                'processorCallback' => stripeProcessorCallback()
            ),
            array(
                'id' => PaymentsProvider::RAZORPAY_ID,
                'payment' => _lang("Debit & Credit Card"),
                'image' => AdminTemplateManager::assets("payment", "img/razorpay-logo.png"),
                'description' => _lang('Pay using razorpay.com'),
                'processorCallback' => razorpayProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::FLUTTERWAVE,
                'payment'=> _lang('Debit & Credit Card'),
                'image'=> AdminTemplateManager::assets("payment","img/flutterwave-logo.png"),
                'description'=> 'Pay using flutterwave.com',
                'processorCallback' => flutterwaveProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::PAY_STACK,
                'payment'=> _lang('Debit & Credit Card'),
                'image'=> AdminTemplateManager::assets("payment","img/paystack.png"),
                'description'=> 'Pay using paystack.com',
                'processorCallback' => paystackProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::MERCADO_PAGO,
                'payment'=> _lang('Debit & Credit Card'),
                'image'=> AdminTemplateManager::assets("payment","img/mercadopago.png"),
                'description'=> 'Pay using mercadopago.com',
                'processorCallback' => mercadoPagoProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::BANK_TRANSFER,
                'payment'=> _lang('Transfer bank'),
                'image'=> AdminTemplateManager::assets("payment","img/bank.png"),
                'description'=> 'Make transfer to the bank',
                'processorCallback' => bankTransferProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::WALLET_ID,
                'payment'=> _lang('MyWallet'),
                'image'=> AdminTemplateManager::assets("payment","img/wallet-logo.png"),
                'description'=> 'Pay using your digital wallet',
                'processorCallback' => walletProcessorCallback()
            ),
            array(
                'id'=> PaymentsProvider::COD_ID,
                'payment'=> _lang('Cash payment'),
                'image'=> AdminTemplateManager::assets("payment","img/cod-logo.png"),
                'description'=> 'Pay when you receive your item(s)',
                'processorCallback' => codProcessorCallback()
            ),
        );



        PaymentsProvider::provide("default",$payments ,
            $payment_redirection,
            $payment_callback_success,
            $payment_callback_error
        );


        //add components
        AdminTemplateManager::addScript($this->load->view('payment/plug/header/header_script', NULL, TRUE));

    }

    private function setupWalletPayments(){

        //setup payment for waller
        $payment_redirection = site_url("payment/make_payment");
        $payment_callback_success = site_url("payment/wallet_payment_confirm");
        $payment_callback_error = site_url("payment/payment_error");


        $payments = PaymentsProvider::getPayments("default");


        PaymentsProvider::provide("wallet",$payments,
            $payment_redirection,
            $payment_callback_success,
            $payment_callback_error
        );

        PaymentsProvider::excludePayments('wallet',array(PaymentsProvider::WALLET_ID,PaymentsProvider::COD_ID));

        //disable taxes
        TaxManager::disable('wallet');

    }

    public function onEnable()
    {
        $this->registerModuleActions();
        $this->mPaymentModel->setup_config();
    }

    public function onInstall()
    {

        $this->mWalletModel->createTables();
        $this->mWalletModel->createTableWT();

        $this->mPaymentModel->createTables();
        $this->mPaymentModel->update_fields();
        $this->mPaymentModel->setup_config();


        return TRUE;
    }

    public function onUpgrade()
    {
        $this->mWalletModel->createTables();
        $this->mWalletModel->createTableWT();

        $this->mPaymentModel->createTables();
        $this->mPaymentModel->update_fields();
        $this->mPaymentModel->setup_config();

        $this->registerModuleActions();

        return TRUE;
    }

    private function registerModuleActions()
    {

        GroupAccess::registerActions("payment", array(
            CONFIG_PAYMENT,
            DISPLAY_LIST_TRANSACTIONS,
            DISPLAY_LIST_BILLING,
            MANAGE_TAXES
        ));

    }


    public function make_payment()
    {

        $css = AdminTemplateManager::assets("payment", 'css/style.css');
        AdminTemplateManager::addCssLibs($css);

        $id = RequestInput::get("id");
        $data['invoice'] = $this->mPaymentModel->getInvoice($id);
        $data['title'] = Translate::sprint("Payment");

        $data['cancel_url'] = admin_url();

        if ($data['invoice'] != NULL) {
            $this->load->view("payment/client_view/html/make-payment", $data);
        } else
            redirect(admin_url());

    }

    private function getPaymentParameters(){

        $id = intval(RequestInput::get("invoiceid"));
        $callback_s1 = RequestInput::get("callback_s1");
        $callback_e1 = RequestInput::get("callback_e1");
        $method_payment = intval(RequestInput::get("mp"));

        $invoice = $this->mPaymentModel->getInvoice($id);

        $token = TokenSetting::generateToken("processPayment", $id);
        $callback = PaymentsProvider::getErrorCallback($invoice->module);


        $inputs = array(
            'invoiceId' => $id,
            'callback_s1' => $callback_s1,
            'callback_e1' => $callback_e1,
            'method_payment' => $method_payment,
            'token' => $token,
            'callback' => $callback,
        );


        if ($invoice == NULL) {
            redirect(site_url('payment/payment_error?invoiceid=' . $id));
        }


        if ($invoice->status == 1){
            redirect("error404");
        }

        $params = array(
            'currency' => $invoice->currency,
            'details_tax' => 0,
            'discounts' => 0,
            'invoice' => $invoice,
            'details_subtotal' => $invoice->amount,
            'details_total' => $invoice->amount,
            'callback_error_url' => $callback . '?invoiceid=' . $id,
        );


        $callback = PaymentsProvider::getSuccessCallback($invoice->module);


        //create call payment when it's done
        if ($method_payment == 1)
            $params['callback_success_url'] = $callback . '?invoiceid=' . $id . '&method=paypal&key=' . $token;
        else if ($method_payment == 2)
            $params['callback_success_url'] = $callback . '?invoiceid=' . $id . '&method=stripe&key=' . $token;
        else
            $params['callback_success_url'] = $callback . '?invoiceid=' . $id . '&method='.$method_payment.'&key=' . $token;

        if($method_payment>0){
            $params['callback_success_url'] .= '&mp='.$method_payment;
        }

        //configure alternative callback for successful message
        if($callback_s1 != ""){
            $params['callback_success_url'] = $params['callback_success_url'].'&callbackAltSuccess='.$callback_s1;
        }

        //configure alternative callback for error message
        if($callback_e1 != ""){
            $params['callback_error_url'] = $params['callback_error_url'].'&callbackAltError='.$callback_e1;
        }

        $params['details_subtotal'] = 0;
        $params['details_total'] = 0;
        $params['number_items'] = 0;

        //adjust total
        $items = json_decode($invoice->items);
        $params['articles'] = $items;

        foreach ($items as $k => $item) {
            $params['details_subtotal'] = $params['details_subtotal'] + ($item->price * $item->qty);
            $params['number_items']++;
        }

        $params['details_total'] = $params['details_subtotal'];

        //apply discounts
        $discounts = json_decode($invoice->discounts,JSON_OBJECT_AS_ARRAY);
        if(empty($discounts))
            $discounts = array();

        if(count($discounts)>0 && !empty($discounts)){
            foreach ($discounts as $key => $value){
                $params['discounts'] += $value;
                $params['details_total'] += $value;
            }
        }

        if (!TaxManager::isDisabled($invoice->module)) {
            if (defined('DEFAULT_TAX') and DEFAULT_TAX > 0) {
                $tax = $this->mTaxModel->getTax(DEFAULT_TAX);
                if ($tax != NULL) {
                    $tax_value = (($tax['value'] / 100) * $params['details_total']);
                    $params['details_tax'] = $tax_value;
                    $params['details_total'] = $params['details_total'] + $tax_value;
                }
            } else if (defined('DEFAULT_TAX') and DEFAULT_TAX == -2) {
                if (defined('MULTI_TAXES') and count(MULTI_TAXES) > 0)
                    $litTaxes = json_decode(MULTI_TAXES, JSON_OBJECT_AS_ARRAY);
                $newAmount = $params['details_total'];
                $multiTaxes = 0;
                foreach ($litTaxes as $value) {
                    $mTax = $this->mTaxModel->getTax($value);
                    if ($mTax != NULL) {
                        $tax_value = (($mTax['value'] / 100) * $params['details_total']);
                        $multiTaxes = $multiTaxes + $tax_value;
                        $newAmount = $newAmount + $tax_value;
                    }
                }

                $params['details_tax'] = $multiTaxes;
                $params['details_total'] = $newAmount;
            }
        }


        $extras = jsonDecode($invoice->extras, JSON_OBJECT_AS_ARRAY);
        if ($extras != null && is_array($extras)) {
            foreach ($extras as $k => $value) {
                $params['extras'][$k] = doubleval($value);
                $params['details_total'] = $params['details_total'] + doubleval($value);
            }
        }

        return array(
            'parameters' => $params,
            'inputs' => $inputs
        );

    }

    public function process_payment()
    {

        $result = $this->getPaymentParameters();

        $params = $result['parameters'];
        $inputs = $result['inputs'];

        if (isset($params['details_subtotal'])) {
            $this->db->where('id', $params['invoice']->id);
            $this->db->update('invoice', array(
                'amount' => $params['details_total']
            ));
        }

        if ( $inputs['method_payment'] == PaymentsProvider::PAYPAL_ID) { //paypal

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::PAYPAL_ID);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        } else if ($inputs['method_payment'] == PaymentsProvider::STRIPE_ID) { //stripe

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::STRIPE_ID);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        } else if ($inputs['method_payment'] == PaymentsProvider::COD_ID) {

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::COD_ID);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        } else if ($inputs['method_payment'] == PaymentsProvider::WALLET_ID) {

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::WALLET_ID);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        } else if ($inputs['method_payment'] == PaymentsProvider::RAZORPAY_ID) { //razor pay

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::RAZORPAY_ID);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        } else if ($inputs['method_payment'] == PaymentsProvider::FLUTTERWAVE) { //FLUTTERWAVE

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::FLUTTERWAVE);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        } else if ($inputs['method_payment'] == PaymentsProvider::HYPERPAY) { //HYPERPAY

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::HYPERPAY);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        }else if ($inputs['method_payment'] == PaymentsProvider::PAYTM) { //PAYTM

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::PAYTM);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        }else if ($inputs['method_payment'] == PaymentsProvider::BANK_TRANSFER) {

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::BANK_TRANSFER);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);



        }else if ($inputs['method_payment'] == PaymentsProvider::PAY_STACK) { //stripe

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::PAY_STACK);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);


        }else if ($inputs['method_payment'] == PaymentsProvider::MERCADO_PAGO) { //Mercado pago

            $resultCallback = PaymentsProvider::getPaymentProcessorCallback(PaymentsProvider::MERCADO_PAGO);

            if($resultCallback!=NULL)
                return call_user_func($resultCallback,$params, $inputs);

        }

    }




    public function payment_success()
    {

        $invoiceId = intval(RequestInput::get("invoiceid"));
        $paymentMethodId = intval(RequestInput::get("mp"));
        $method = Text::input(RequestInput::get("method"));
        $transaction = Text::input(RequestInput::get("paymentId"));
        $key = Text::input(RequestInput::get("key"));

        $payerID = Text::input(RequestInput::get("PayerID"));
        $paymentId = Text::input(RequestInput::get("paymentId"));
        $token = Text::input(RequestInput::get("token"));



        if($paymentMethodId == 0){
            $paymentMethodId = PaymentsProvider::findIdByKey($method);
        }


        $invoice = $this->mPaymentModel->getInvoice($invoiceId);

        if($invoice == NULL){
            $this->payment_error();
        }


        foreach (PaymentsProvider::getPayments($invoice->module) as $payment){

            //check and change paypal status
            if($payment['id'] == $paymentMethodId && $payment['id'] == PaymentsProvider::PAYPAL_ID){
                $params = array(
                    'paymentId' => $paymentId,
                    'payerID' => $payerID,
                    'token' => $token
                );
                $result = Modules::run('payment/paypal/getPaymentStatus',$params);
                if(!$result)
                    break;
            }

            //change status of internal invoice
            if($payment['id'] == $paymentMethodId){
                $this->mPaymentModel->updateInvoice($invoice->id,$method,$transaction,$key);
                $data['title'] = _lang("Payment done");
                $this->load->view("payment/client_view/html/success",$data);
                return;
            }

        }


    }


    public function payment_error()
    {

        $id = intval(RequestInput::get("invoiceid"));
        $data["title"] = Translate::sprint('Payment with error');
        $data["invoiceid"] = $id;
        $this->load->view("payment/client_view/html/error", $data);

    }


    public function wallet_payment_confirm()
    {

        $invoiceid = RequestInput::get('invoiceid');
        $method = RequestInput::get('method');
        $key = RequestInput::get('key');
        $transaction = Text::input(RequestInput::get("paymentId"));

        $user_id = SessionManager::getData("id_user");

        $this->db->where("user_id", $user_id);
        $this->db->where("module", "wallet");
        $this->db->where("id", intval($invoiceid));

        $invoice = $this->db->get('invoice', 1);
        $invoice = $invoice->result();


        if ($method == "paypal" && isset($invoice[0])) {

            $payerID = Text::input(RequestInput::get("PayerID"));
            $paymentId = Text::input(RequestInput::get("paymentId"));
            $token = Text::input(RequestInput::get("token"));

            $params = array(
                'paymentId' => $paymentId,
                'payerID' => $payerID,
                'token' => $token
            );

            $result = Modules::run('payment/paypal/getPaymentStatus', $params);

            if ($result == 1) {

                $data["invoiceid"] = $invoiceid;

                $data["title"] = Translate::sprint('Payment successful');
                $this->load->view("payment/client_view/html/success", $data);

                //add balance
                $this->mWalletModel->add_BalanceTransaction(SessionManager::getData('id_user'), $invoice[0]->amount);

                $this->mPaymentModel->updateInvoice($invoiceid, $method, $transaction, $key);

            } else {
                $this->payment_error();
            }

        }else if( $method == "hyperpay" && isset($invoice[0]) ){


            $result = Modules::run("payment/hyperpay/get_hyperpay_status",RequestInput::get('id'));
            $result = json_decode($result,JSON_OBJECT_AS_ARRAY);

            if(!isset($result['id'])){
                $this->payment_error();
            }

            $data["title"] = Translate::sprint('Payment successful');
            $this->load->view("payment/client_view/html/success", $data);

            $this->mPaymentModel->updateInvoice(intval($invoiceid), $method, $transaction, $key);

            //add balance
            $this->mWalletModel->add_BalanceTransaction(SessionManager::getData('id_user'), $invoice[0]->amount);


        } else if (isset($invoice[0])) {

            $data["title"] = Translate::sprint('Payment successful');
            $this->load->view("payment/client_view/html/success", $data);

            $this->mPaymentModel->updateInvoice(intval($invoiceid), $method, $transaction, $key);

            //add balance
            $this->mWalletModel->add_BalanceTransaction(SessionManager::getData('id_user'), $invoice[0]->amount);

        }

        return FALSE;
    }


}
