<?php

namespace twa\omnipay\facades;

use Illuminate\Support\Facades\DB;
use twa\omnipay\models\EcomPurchasesAttemptModel;
use twa\omnipay\models\EcomStoresPaymentProvidersModel;
use Illuminate\Support\Facades\Session;

class OmniPayFacade
{
    private $payment;

    private $currencies;

    public function __construct($store_id = null, $provider = null)
    {
        if (!$provider) {
            //we query the store information
            $Check = EcomStoresPaymentProvidersModel::where('ecom_stores_id', $store_id)->where('cancelled', 0)->orderBy('orders', 'ASC')->first();
            if (! $Check) {
                $response = ['location' => 'OmniPayFacade', 'status' => 'error', 'message' => 'the store provided does not have a preferred paymenet gateway provider'];
                echo json_encode($response);
                exit();
            }

            $config = config('omnipay.'.$Check->provider);

            switch ($config['provider']) {
                case 'BNP':
                    $payment = new \twa\omnipay\controllers\BNPController($config['data'], $Check->provider);
                    break;
                case 'TransactionGlobal':
                    $payment = new \twa\omnipay\controllers\TransactionGlobalController($config['data'], $Check->provider);
                    break;
                case 'areeba':
                    $payment = new \twa\omnipay\controllers\AreebaController($config['data'], $Check->provider);
                    break;
                case 'payfort':
                    $payment = new \twa\omnipay\controllers\PayfortController($config['data'], $Check->provider);
                    break;
                case 'paypal':
                    $payment = new \twa\omnipay\controllers\PaypalController($config['data'], $Check->provider);
                    break;
                case 'airwallex':
                    $payment = new \twa\omnipay\controllers\AirwallexController($config['data'], $Check->provider);
                    break;
                case 'tap':
                    $payment = new \twa\omnipay\controllers\TapController($config['data'], $provider);
                break;
                case 'coinbase':
                    $payment = new \twa\omnipay\controllers\CoinbaseController($config['data'], $Check->provider);
                    break;
                case 'noon':
                    $payment = new \twa\omnipay\controllers\NoonController($config['data'], $Check->provider);
                    break;
                case 'bob':
                    $payment = new \twa\omnipay\controllers\BobController($config['data'], $Check->provider);
                    break;
                case 'simplify':
                    $payment = new \twa\omnipay\controllers\SimplifyController($config['data'], $Check->provider);
                    break;
                case 'paystack':
                    $payment = new \twa\omnipay\controllers\PaystackController($config['data'], $provider);
                    break;
                case 'apgateway':
                    $payment = new \twa\omnipay\controllers\APGatewayMastercardController($config['data'], $provider);
                    break;
                case 'benefit':
                    $payment = new \twa\omnipay\controllers\BenefitController($config['data'], $provider);
                    break;
                case 'globalpay':
                    $payment = new \twa\omnipay\controllers\GlobalPayController($config['data'], $provider);
                    break;
                case 'tabby':
                    $payment = new \twa\omnipay\controllers\TabbyController($config['data'], $provider);
                    break;
                case 'mollie':
                    $payment = new \twa\omnipay\controllers\MollieController($config['data'], $provider);
                    break;
                case 'mollie_inpage':
                    $payment = new \twa\omnipay\controllers\MollieInPageController($config['data'], $provider);
                    break;
                case 'paytabs':
                    $payment = new \twa\omnipay\controllers\PayTabsController($config['data'], $provider);
                    break;
                case 'paypal_pro' :
                    $payment = new \twa\omnipay\controllers\PaypalProController($config['data'] , $provider);
                    break;
                case 'stripe' :
                    $payment = new \twa\omnipay\controllers\StripeController($config['data'] , $provider);
                    break;
                case 'ngenius' :
                    $payment = new \twa\omnipay\controllers\NGeniusController($config['data'] , $provider);
                    break;
                case 'telr' :
                    $payment = new \twa\omnipay\controllers\TelrController($config['data'] , $provider);
                    break;
                default:
                    $response = ['location' => 'OmniDeliveryFacade', 'status' => 'error', 'message' => 'the gateway used by this store ['.$config['provider'].'] is not supported by the omni delivery library'];
                    echo json_encode($response); exit();
            }
        } else {
            $config = config('omnipay.'.$provider);
            switch ($config['provider']) {
                case 'BNP':
                    $payment = new \twa\omnipay\controllers\BNPController($config['data'], $provider);
                    break;
                case 'TransactionGlobal':
                    $payment = new \twa\omnipay\controllers\TransactionGlobalController($config['data'], $provider);
                    break;
                case 'areeba':
                    $payment = new \twa\omnipay\controllers\AreebaController($config['data'], $provider);
                    break;
                case 'payfort':
                    $payment = new \twa\omnipay\controllers\PayfortController($config['data'], $provider);
                    break;
                case 'paypal':
                    $payment = new \twa\omnipay\controllers\PaypalController($config['data'], $provider);
                    break;
                case 'airwallex':
                    $payment = new \twa\omnipay\controllers\AirwallexController($config['data'], $provider);
                    break;
                case 'tap':
                    $payment = new \twa\omnipay\controllers\TapController($config['data'], $provider);
                break;
                case 'coinbase':
                    $payment = new \twa\omnipay\controllers\CoinbaseController($config['data'], $provider);
                    break;
                case 'noon':
                    $payment = new \twa\omnipay\controllers\NoonController($config['data'], $provider);
                    break;
                case 'bob':
                    $payment = new \twa\omnipay\controllers\BobController($config['data'], $provider);
                    break;
                case 'simplify':
                    $payment = new \twa\omnipay\controllers\SimplifyController($config['data'], $provider);
                    break;
                case 'paystack':
                    $payment = new \twa\omnipay\controllers\PaystackController($config['data'], $provider);
                    break;
                case 'apgateway':
                    $payment = new \twa\omnipay\controllers\APGatewayMastercardController($config['data'], $provider);
                    break;
                case 'benefit':
                    $payment = new \twa\omnipay\controllers\BenefitController($config['data'], $provider);
                    break;
                case 'globalpay':
                    $payment = new \twa\omnipay\controllers\GlobalPayController($config['data'], $provider);
                    break;
                case 'tabby':
                    $payment = new \twa\omnipay\controllers\TabbyController($config['data'], $provider);
                    break;
                case 'mollie':
                    $payment = new \twa\omnipay\controllers\MollieController($config['data'], $provider);
                    break;
                case 'mollie_inpage':
                    $payment = new \twa\omnipay\controllers\MollieInPageController($config['data'], $provider);
                    break;
                case 'paytabs':
                    $payment = new \twa\omnipay\controllers\PayTabsController($config['data'], $provider);
                    break;
                case 'paypal_pro' :
                    $payment = new \twa\omnipay\controllers\PaypalProController($config['data'] , $provider);
                    break;
                case 'stripe' :
                    $payment = new \twa\omnipay\controllers\StripeController($config['data'] , $provider);
                    break;
                case 'ngenius' :
                    $payment = new \twa\omnipay\controllers\NGeniusController($config['data'] , $provider);
                    break;
                case 'telr' :
                    $payment = new \twa\omnipay\controllers\TelrController($config['data'] , $provider);
                    break;
                default:
                    $response = ['location' => 'OmniDeliveryFacade', 'status' => 'error', 'message' => 'the gateway used by this store ['.$config['provider'].'] is not supported by the omni delivery library'];
                    echo json_encode($response); exit();
            }
        }
        $this->payment = $payment;
        if (isset($config['currencies']) && is_array($config['currencies'])) {
            $this->currencies = $config['currencies'];
        } else {
            $this->currencies = ['USD'];
        }
    }

    public function createPayment($id, $value, $currency, $customer_name = null, $customer_email = null, $url_success = null, $url_cancel = null)
    {
        if(session('login') && isset(collect(session('login'))['token'])){
            $url_success = twaURL()->addParameter($url_success,[ 't' => collect(session('login'))['token'] ]);
        }
        return $this->payment->createPayment($id, $value, $currency, $customer_name, $customer_email, $url_success, $url_cancel);
    }

    public function checkPayment($id)
    {
        return $this->payment->checkPayment($id);
    }

    public function capturePayment($id)
    {
        return $this->payment->capturePayment($id);
    }

    public static function responseCallback($status = null, $paid = null, $api = null)
    {
        $lang = false;
        if (request()->input('lang')) {
            $lang = request()->input('lang');
            $lang = str_replace('/', '', $lang);
        }

        if ($lang && in_array($lang, lang()->list()->pluck('prefix')->toArray())) {
            app()->setLocale($lang);
        }
        $api == 'api';

        $attempt = EcomPurchasesAttemptModel::where('id', request()->input('paid', $paid))->where('cancelled', 0)->first();

        //        if (request()->has('response_gateway')) {
//            $attempt->response_gateway = request()->input('response_gateway');
//            $attempt->save();
//        }

        if (! $attempt) {
            if ($api) {
                return response()->json([], 400);
            }
            abort(404);
        }
        $provider = EcomStoresPaymentProvidersModel::where('id', $attempt->ecom_stores_payment_methods_id)->where('cancelled', 0)->first();
        if (! $provider) {
            abort(404);
        }
        $gatewayInit = json_decode($attempt->gateway_init);
        $response = (new self(null, $provider->provider))->payment->checkPayment($attempt->id);
        if (request()->input('debug')) {
            dd($response->getOriginalContent());
        }
        if ($response->getStatusCode() == 200) {
            $answer = 'SUCCESS';
        } else {
            $answer = 'FAIL';
        }
        $response = $response->getOriginalContent();

        if (! request()->has('response_gateway')) {
            $attempt->response_gateway = json_encode($response);
            $attempt->save();
        }

        if (request()->input('t')) {

            //first we try to attemtp to restore the login in case it was los
            if (! session('login') || ! session('login') == '' || ! is_array(session('login'))) {
                try {
                    $token = \twa\ecomauth\models\EcomUsersTokenModel::select('ecom_users_id')->where('token',request()->input('t'))->where('cancelled',0)->first();
                    if($token){
                        $User = \twa\ecomauth\models\EcomUsersModel::where('id', $token['ecom_users_id'])->where('cancelled', 0)->first();
                    }else{
                        $User = false;
                    }

                    if ($User) {
                        session(['login' => collect($User)->recursive()]);
                    }
                } catch (\Throwable $e) {
                    dd($e);
                }
            }
        }

        //  we attempt to place the order from the attempt using the \twa\ecomcart\
        $purchaseID = null;
        $store = null;

        try {
            $store = DB::table('ecom_stores')->where('id', $attempt->ecom_stores_id)->first();
        } catch (\Throwable $e) {
        }

        if ($answer == 'SUCCESS') {
            try {
                if ($attempt->completed != 1) {
                    $attempt->completed = 1;
                    $attempt->save();

                    if (is_array($attempt->billing_address_details) && array_key_exists('id', $attempt->billing_address_details)) {
                        $billingAddressID = $attempt->billing_address_details['id'];
                    }
                    $update = (new \twa\ecomcart\controllers\EcomPurchasesController)->placeOrderFromAttempt($attempt->id);
                    $update = $update->getOriginalContent();
                    $purchaseID = $update['pid'];
                }
            } catch (\Throwable $e) {
                if ($api) {
                    return response()->json([], 400);
                }
                if (config('omnipay.success.debug')) {
                    dd(['status' => 'error', 'triggered_by' => 'debug in the config.success', 'function' => '(new \twa\ecomcart\controllers\EcomPurchasesController)->placeOrderFromCart()', 'trace' => $e]);
                }
            }
        }

        //we check if there's any function for success callback
        $function = str_replace(['()'], ['('.$attempt->id.')'], config('omnipay.success.function'));
        if ($answer == 'SUCCESS') {
            try {
                eval((string) $function.';');
            } catch (\Throwable $e) {
                if ($api) {
                    return response()->json([], 400);
                }

                if (config('omnipay.success.debug')) {
                    Throw $e;
                    dd(['status' => 'error', 'triggered_by' => 'debug in the config.success', 'function' => $function, 'trace' => $e]);
                }
            }

            if (config('omnipay.success.action') == 'redirect') {
                $link = ecom('url')->setStore($store)->prefix(true).config('omnipay.success.redirect');
                $link = str_replace('/{store}/{lang}','',$link);
                $link = twaURL()->addParameter($link,[ "pid" => $purchaseID ]);
                if(request()->input('t')){
                    $link = twaURL()->addParameter($link,[ "t" => request()->input('t') ]);
                }
                if(request()->input('webview')){
                    $link = twaURL()->addParameter($link,[ "webview" => true ]);
                }
                return $api ? response()->json(['link' => $link], 200) : redirect($link);
            }
        } else {
            if (config('omnipay.fail.action') == 'redirect') {
                $link = ecom('url')->setStore($store)->prefix(true).'/checkout/payment?title=Payment could not be processed&message=Your payment was declined. Please try again using a different payment method';
                if(request()->input('t')){
                    $link = twaURL()->addParameter($link,[ "t" => request()->input('t') ]);
                }
                if(request()->input('webview')){
                    $link = twaURL()->addParameter($link,[ "webview" => true ]);
                }

                return $api ? response()->json(['link' => $link], 200) : redirect($link);
            }
        }

        return ['answer' => $answer, 'resonse' => $response];
    }
}
