<?php

namespace App\Traits\PaymentGateway;

use Exception;
use Carbon\Carbon;
use App\Models\Transaction;
use Illuminate\Support\Str;
use Jenssegers\Agent\Agent;
use App\Models\TemporaryData;
use App\Models\UserNotification;
use App\Traits\TransactionAgent;
use Illuminate\Support\Facades\DB;
use App\Constants\NotificationConst;
use App\Models\Admin\PaymentGateway;
use Illuminate\Http\Client\Response;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Http;
use App\Constants\PaymentGatewayConst;
use App\Traits\PayLink\TransactionTrait;
use App\Http\Helpers\PushNotificationHelper;
use App\Models\Admin\PaymentGatewayCurrency;
use Illuminate\Http\Client\RequestException;

trait PaystackTrait
{
    use TransactionAgent,TransactionTrait;
    public function paystackInit($output = null) {
        if(!$output) $output = $this->output;
        $credentials = $this->getPaystackCredentials($output);
        if($output['type'] === PaymentGatewayConst::TYPEADDMONEY){
            return  $this->setupPaystackInitAddMoney($output,$credentials);
         }else{
             return  $this->setupPaystackInitPayLink($output,$credentials);
         }
    }
    public function setupPaystackInitAddMoney($output,$credentials){
        $amount = $output['amount']->total_amount ? number_format($output['amount']->total_amount,2,'.','') : 0;
        $currency = $output['currency']['currency_code']??"USD";

        if(auth()->guard(get_auth_guard())->check()){
            $user = auth()->guard(get_auth_guard())->user();
            $user_email = $user->email;
        }

        $temp_record_token = generate_unique_string('temporary_datas', 'identifier', 60);
        $this->setUrlParams("token=" . $temp_record_token); // set Parameter to URL for identifying when return success/cancel

        $redirection = $this->getRedirection();
        $url_parameter = $this->getUrlParams();

        $url = "https://api.paystack.co/transaction/initialize";

        $fields   = [
            'email'         => $user_email,
            'amount'        => get_amount($amount) * 100,
            'currency'      => $currency,
            'callback_url'  => $this->setGatewayRoute($redirection['return_url'], PaymentGatewayConst::PAYSTACK, $url_parameter),
            'reference'     => $temp_record_token,
        ];

        $fields_string = http_build_query($fields);
        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Authorization: Bearer $credentials->secret_key",
            "Cache-Control: no-cache",
        ));

        //So that curl_exec returns the contents of the cURL; rather than echoing it
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

        //execute post
        $result = curl_exec($ch);
        $response   = json_decode($result);
        if($response->status == true) {
            $this->paystackJunkInsert($response,$temp_record_token);
            return redirect($response->data->authorization_url)->with('output',$output);
        }else{
            throw new Exception($response->message??" "."Something Is Wrong, Please Contact With Owner");
        }

    }
    public function setupPaystackInitPayLink($output,$credentials){
        $amount = $output['charge_calculation']['requested_amount'] ? number_format($output['charge_calculation']['requested_amount'],2,'.','') : 0;
        $currency = $output['charge_calculation']['sender_cur_code']??"USD";

        $user_email = $output['validated']['email'];

        $temp_record_token = generate_unique_string('temporary_datas', 'identifier', 60);
        $this->setUrlParams("token=" . $temp_record_token); // set Parameter to URL for identifying when return success/cancel

        $redirection = $this->getRedirection();
        $url_parameter = $this->getUrlParams();

        $url = "https://api.paystack.co/transaction/initialize";

        $fields = [
            'email'         => $user_email,
            'amount'        => get_amount($amount) * 100,
            'currency'      => $currency,
            'callback_url'  => $this->setGatewayRoute($redirection['return_url'], PaymentGatewayConst::PAYSTACK, $url_parameter),
            'reference'     => $temp_record_token,
        ];

        $fields_string = http_build_query($fields);
        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Authorization: Bearer $credentials->secret_key",
            "Cache-Control: no-cache",
        ));

        //So that curl_exec returns the contents of the cURL; rather than echoing it
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

        //execute post
        $result = curl_exec($ch);
        $response   = json_decode($result);
        if($response->status == true) {
            $this->paystackJunkInsertPayLink($response,$temp_record_token);
            return redirect($response->data->authorization_url)->with('output',$output);
        }else{
            throw new Exception($response->message??" "."Something Is Wrong, Please Contact With Owner");
        }
    }
    public function getPaystackCredentials($output) {
        $gateway = $output['gateway'] ?? null;
        if(!$gateway) throw new Exception(__("Payment gateway not available"));
        $public_key_sample = ['public_key','Public Key','public-key'];
        $secret_key_sample = ['secret_key','Secret Key','secret-key'];

        $public_key = '';
        $outer_break = false;
        foreach($public_key_sample as $item) {
            if($outer_break == true) {
                break;
            }
            $modify_item = $this->paystackPlainText($item);
            foreach($gateway->credentials ?? [] as $gatewayInput) {
                $label = $gatewayInput->label ?? "";
                $label = $this->paystackPlainText($label);

                if($label == $modify_item) {
                    $public_key = $gatewayInput->value ?? "";
                    $outer_break = true;
                    break;
                }
            }
        }


        $secret_key = '';
        $outer_break = false;
        foreach($secret_key_sample as $item) {
            if($outer_break == true) {
                break;
            }
            $modify_item = $this->paystackPlainText($item);
            foreach($gateway->credentials ?? [] as $gatewayInput) {
                $label = $gatewayInput->label ?? "";
                $label = $this->paystackPlainText($label);

                if($label == $modify_item) {
                    $secret_key = $gatewayInput->value ?? "";
                    $outer_break = true;
                    break;
                }
            }
        }
        $mode = $gateway->env;

        $paypal_register_mode = [
            PaymentGatewayConst::ENV_SANDBOX => "sandbox",
            PaymentGatewayConst::ENV_PRODUCTION => "live",
        ];
        if(array_key_exists($mode,$paypal_register_mode)) {
            $mode = $paypal_register_mode[$mode];
        }else {
            $mode = "sandbox";
        }

        return (object) [
            'public_key'     => $public_key,
            'secret_key' => $secret_key,
            'mode'          => $mode,

        ];

    }

    public function paystackPlainText($string) {
        $string = Str::lower($string);
        return preg_replace("/[^A-Za-z0-9]/","",$string);
    }

    public function paystackJunkInsert($response,$temp_identifier) {
        $output = $this->output;
        $creator_table = $creator_id = $wallet_table = $wallet_id = null;

        if(authGuardApi()['type']  == "AGENT"){
            $creator_table = authGuardApi()['user']->getTable();
            $creator_id = authGuardApi()['user']->id;
            $creator_guard = authGuardApi()['guard'];
            $wallet_table = $output['wallet']->getTable();
            $wallet_id = $output['wallet']->id;
        }else{
            $creator_table = auth()->guard(get_auth_guard())->user()->getTable();
            $creator_id = auth()->guard(get_auth_guard())->user()->id;
            $creator_guard = get_auth_guard();
            $wallet_table = $output['wallet']->getTable();
            $wallet_id = $output['wallet']->id;
        }

            $data = [
                'gateway'       => $output['gateway']->id,
                'currency'      => $output['currency']->id,
                'amount'        => json_decode(json_encode($output['amount']),true),
                'response'      => $response,
                'wallet_table'  => $wallet_table,
                'wallet_id'     => $wallet_id,
                'creator_table' => $creator_table,
                'creator_id'    => $creator_id,
                'creator_guard' => $creator_guard,
            ];

        return TemporaryData::create([
            'type'          => PaymentGatewayConst::PAYSTACK,
            'identifier'    => $temp_identifier,
            'data'          => $data,
        ]);
    }
    public function paystackJunkInsertPayLink($response,$temp_identifier) {
        $output = $this->output;
        $wallet_table = $output['wallet']->getTable();
        $wallet_id = $output['wallet']->id;
        $user_relation_name = strtolower($output['user_type'])??'user';

            $data = [
                'type'                  => $output['type'],
                'gateway'               => $output['gateway']->id,
                'currency'              => $output['currency']->id,
                'validated'             => $output['validated'],
                'charge_calculation'    => json_decode(json_encode($output['charge_calculation']),true),
                'response'              => $response,
                'wallet_table'          => $wallet_table,
                'wallet_id'             => $wallet_id,
                'creator_guard'         => $output['user_guard']??'',
                'user_type'             => $output['user_type']??'',
                'user_id'               => $output['wallet']->$user_relation_name->id??'',
            ];

        return TemporaryData::create([
            'type'          => PaymentGatewayConst::PAYSTACK,
            'identifier'    => $temp_identifier,
            'data'          => $data,
        ]);
    }

    public function paystackSuccess($output = null) {
        $temp_data = $output['tempData'];
        // verify payStack transaction
        $response_data  = $temp_data['data']->callback_data;
        $reference      = $response_data->reference;

        $credentials    = $this->getPayStackCredentials($output);
        $secret_key     = $credentials->secret_key;

        $verify_url = "https://api.paystack.co/transaction/verify/" . $reference;

        $response = Http::withHeaders([
            "Authorization"     => "Bearer $secret_key",
            "Cache-Control"     => "no-cache",
        ])->get($verify_url)->throw(function (Response $response, RequestException $e) {
            $message = $response->json()['message'] ?? 'Something went wrong! Please try again';
            throw new Exception($message);
        })->json();

        $status = $response['status'] ?? false;
        if ($status != true) {
            $transaction_status = PaymentGatewayConst::STATUSREJECTED;
        } else {
            if ($response['data']['status'] == "success") {
                $transaction_status = PaymentGatewayConst::STATUSSUCCESS;
            } else {
                $transaction_status = PaymentGatewayConst::STATUSPENDING;
            }
        }
        $output['capture']      = $response;
        $output['callback_ref'] = $response['data']['reference']; // it's also temporary identifier

        if (!$this->searchWithReferenceInTransaction($output['callback_ref'])) {

            try {
                if($output['type'] === PaymentGatewayConst::TYPEADDMONEY){
                    $user_guard = request()->expectsJson() ? authGuardApi()['type'] : userGuard()['type'];
                    if($user_guard == "USER"){
                        return $this->createTransactionPaystack($output,$transaction_status);
                    }else{
                        return $this->createTransactionChildRecords($output,$transaction_status);
                    }
                }else{
                    return $this->createTransactionPayLink($output,$transaction_status);
                }
            } catch (Exception $e) {
                throw new Exception($e->getMessage());
            }
        }
    }

    public function createTransactionPaystack($output,$status) {
        $trx_id = 'AM'.getTrxNum();
        $inserted_id = $this->insertRecordPaystack($output,$trx_id,$status);
        $this->insertChargesPaystack($output,$inserted_id);
        $this->adminNotification($trx_id,$output,$status);
        $this->insertDevicePaystack($output,$inserted_id);
        // $this->removeTempDataPaystack($output);
        try{
            //send sms & email notifications
            $this->sendNotifications($output,$trx_id);
       }catch(Exception $e){}

        if($this->requestIsApiUser()) {
            // logout user
            $api_user_login_guard = $this->output['api_login_guard'] ?? null;
            if($api_user_login_guard != null) {
                auth()->guard($api_user_login_guard)->logout();
            }
        }

    }

    public function insertRecordPaystack($output,$trx_id,$status) {

        $trx_id = $trx_id;
        DB::beginTransaction();
        try{
            if($this->predefined_user) {
                $user = $this->predefined_user;
            }elseif(Auth::guard(get_auth_guard())->check()){
                $user = auth()->guard(get_auth_guard())->user();
            }
            $user_id = $user->id;
            $id = DB::table("transactions")->insertGetId([
                'user_id'                       =>  $user_id,
                'user_wallet_id'                => $output['wallet']->id,
                'payment_gateway_currency_id'   => $output['currency']->id,
                'type'                          => "ADD-MONEY",
                'trx_id'                        => $trx_id,
                'request_amount'                => $output['amount']->requested_amount,
                'payable'                       => $output['amount']->total_amount,
                'available_balance'             => $output['wallet']->balance + $output['amount']->requested_amount,
                'remark'                        => ucwords(remove_speacial_char(PaymentGatewayConst::TYPEADDMONEY," ")) . " With " . $output['gateway']->name,
                'details'                       => PaymentGatewayConst::PAYSTACK." payment successful",
                'status'                        => $status,
                'attribute'                     => PaymentGatewayConst::SEND,
                'callback_ref'                  => $output['callback_ref'] ?? null,
                'created_at'                    => now(),
            ]);
            if($status == PaymentGatewayConst::STATUSSUCCESS){
                $this->updateWalletBalancePaystack($output);
            }
            DB::commit();
        }catch(Exception $e) {
            DB::rollBack();
            throw new Exception(__("Something went wrong! Please try again."));
        }
        return $id;
    }

    public function updateWalletBalancePaystack($output) {
        $update_amount = $output['wallet']->balance + $output['amount']->requested_amount;
        $output['wallet']->update([
            'balance'   => $update_amount,
        ]);
    }

    public function insertChargesPaystack($output,$id) {
        if($this->predefined_user) {
            $user = $this->predefined_user;
        }elseif(Auth::guard(get_auth_guard())->check()){
            $user = auth()->guard(get_auth_guard())->user();
        }
        DB::beginTransaction();
        try{
            DB::table('transaction_charges')->insert([
                'transaction_id'    => $id,
                'percent_charge'    => $output['amount']->percent_charge,
                'fixed_charge'      => $output['amount']->fixed_charge,
                'total_charge'      => $output['amount']->total_charge,
                'created_at'        => now(),
            ]);
            DB::commit();

            //notification
            $notification_content = [
                'title'         => __("Add Money"),
                'message'       => __("Your Wallet")." (".$output['wallet']->currency->code.")  ".__("balance  has been added")." ".$output['amount']->requested_amount.' '. $output['wallet']->currency->code,
                'time'          => Carbon::now()->diffForHumans(),
                'image'         =>  get_image($user->image,'user-profile')
            ];

            UserNotification::create([
                'type'      => NotificationConst::BALANCE_ADDED,
                'user_id'  =>  $user->id,
                'message'   => $notification_content,
            ]);

            //Push Notifications
            try{
                (new PushNotificationHelper())->prepare([$user->id],[
                    'title' => $notification_content['title'],
                    'desc'  => $notification_content['message'],
                    'user_type' => 'user',
                ])->send();
            }catch(Exception $e) {}
        }catch(Exception $e) {
            DB::rollBack();
            throw new Exception(__("Something went wrong! Please try again."));
        }
    }

    public function insertDevicePaystack($output,$id) {
        $client_ip = request()->ip() ?? false;
        $location = geoip()->getLocation($client_ip);
        $agent = new Agent();

        // $mac = exec('getmac');
        // $mac = explode(" ",$mac);
        // $mac = array_shift($mac);
        $mac = "";

        DB::beginTransaction();
        try{
            DB::table("transaction_devices")->insert([
                'transaction_id'=> $id,
                'ip'            => $client_ip,
                'mac'           => $mac,
                'city'          => $location['city'] ?? "",
                'country'       => $location['country'] ?? "",
                'longitude'     => $location['lon'] ?? "",
                'latitude'      => $location['lat'] ?? "",
                'timezone'      => $location['timezone'] ?? "",
                'browser'       => $agent->browser() ?? "",
                'os'            => $agent->platform() ?? "",
            ]);
            DB::commit();
        }catch(Exception $e) {
            DB::rollBack();
            throw new Exception(__("Something went wrong! Please try again."));
        }
    }

    public function removeTempDataPaystack($output) {
        TemporaryData::where("identifier",$output['tempData']['identifier'])->delete();
    }
    public function isPayStack($gateway)
    {
        $search_keyword = ['Paystack','paystack','payStack','pay-stack','paystack gateway', 'paystack payment gateway'];
        $gateway_name = $gateway->name;

        $search_text = Str::lower($gateway_name);
        $search_text = preg_replace("/[^A-Za-z0-9]/","",$search_text);
        foreach($search_keyword as $keyword) {
            $keyword = Str::lower($keyword);
            $keyword = preg_replace("/[^A-Za-z0-9]/","",$keyword);
            if($keyword == $search_text) {
                return true;
                break;
            }
        }
        return false;
    }
    //for api
    public function paystackInitApi($output = null) {
        if(!$output) $output = $this->output;
        $credentials = $this->getPaystackCredentials($output);;
        $amount = $output['amount']->total_amount ? number_format($output['amount']->total_amount,2,'.','') : 0;
        $currency = $output['currency']['currency_code']??"USD";

        if(authGuardApi()['guard'] == 'agent_api'){
            $user = authGuardApi()['user'];
            $user_email = $user->email;
        }elseif(auth()->guard(get_auth_guard())->check()){
            $user = auth()->guard(get_auth_guard())->user();
            $user_email = $user->email;
        }

        $temp_record_token = generate_unique_string('temporary_datas', 'identifier', 60);
        $this->setUrlParams("token=" . $temp_record_token); // set Parameter to URL for identifying when return success/cancel

        $redirection = $this->getRedirection();
        $url_parameter = $this->getUrlParams();

        $url = "https://api.paystack.co/transaction/initialize";

        $fields   = [
            'email'         => $user_email,
            'amount'        => get_amount($amount) * 100,
            'currency'      => $currency,
            'callback_url'  => $this->setGatewayRoute($redirection['return_url'], PaymentGatewayConst::PAYSTACK, $url_parameter),
            'reference'     => $temp_record_token,
        ];


        $fields_string = http_build_query($fields);
        //open connection
        $ch = curl_init();

        //set the url, number of POST vars, POST data
        curl_setopt($ch,CURLOPT_URL, $url);
        curl_setopt($ch,CURLOPT_POST, true);
        curl_setopt($ch,CURLOPT_POSTFIELDS, $fields_string);
        curl_setopt($ch, CURLOPT_HTTPHEADER, array(
            "Authorization: Bearer $credentials->secret_key",
            "Cache-Control: no-cache",
        ));

        //So that curl_exec returns the contents of the cURL; rather than echoing it
        curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);

        //execute post
        $result = curl_exec($ch);
        $response   = json_decode($result);

        if($response->status == true) {
            $this->paystackJunkInsert($response,$temp_record_token);
            $data['link'] = $response->data->authorization_url;
            $data['trx'] =  $temp_record_token;
            return $data;
        }else{
            throw new Exception($response->message??" "."Something Is Wrong, Please Contact With Owner");

        }

    }


     /**
     * paystack webhook response
     * @param array $response_data
     * @param \App\Models\Admin\PaymentGateway $gateway
     */
    public function paystackCallbackResponse(array $response_data, PaymentGateway $gateway)
    {
        $output = $this->output;
        if($output['type'] === PaymentGatewayConst::TYPEADDMONEY){
            return $this->paystackCallbackResponseAddMoney($response_data, $gateway);
        }else{
            return $this->paystackCallbackResponsePayLink($response_data, $gateway);
        }
    }

    public function paystackCallbackResponseAddMoney($response_data, $gateway){
        $output = $this->output;

        $event_type = $response_data['event'] ?? "";

        if ($event_type == "charge.success") {
            $reference = $response_data['data']['reference'];

            // verify signature START -----------------------------
            $credentials = $this->getPayStackCredentials(['gateway' => $gateway]);
            $secret_key = $credentials->secret_key;

            $hash = hash_hmac('sha512', request()->getContent(), $secret_key);

            if($hash != request()->header('x-paystack-signature')) {
                return false;
            }
            // verify signature END -----------------------------

            // temp data
            $temp_data = TemporaryData::where('identifier', $reference)->first();

            // if transaction is already exists need to update status, balance & response data
            $transaction = Transaction::where('callback_ref', $reference)->first();

            $status = PaymentGatewayConst::STATUSSUCCESS;

            if($temp_data) {
                $gateway_currency_id = $temp_data->data->currency ?? null;
                $gateway_currency = PaymentGatewayCurrency::find($gateway_currency_id);
                if($gateway_currency) {

                    $requested_amount = $temp_data['data']->amount->requested_amount ?? 0;
                    $wallet_currency  = $temp_data['data']->amount->receiver_cur_code ?? "USD";

                    $validator_data = [
                        $this->currency_input_name          => $gateway_currency->alias,
                        $this->amount_input                 => $requested_amount,
                        $this->wallet_currency_input_name   => $wallet_currency,
                    ];

                    $get_wallet_model = PaymentGatewayConst::registerWallet()[$temp_data->data->creator_guard];
                    $user_wallet = $get_wallet_model::find($temp_data->data->wallet_id);
                    $this->predefined_user_wallet = $user_wallet;
                    if($temp_data->data->creator_guard  == 'agent_api' || $temp_data->data->creator_guard == 'agent'){
                        $this->predefined_guard = $user_wallet->agent->modelGuardName(); // need to update
                        $this->predefined_user = $user_wallet->agent;
                    }else{
                        $this->predefined_guard = $user_wallet->user->modelGuardName(); // need to update
                        $this->predefined_user = $user_wallet->user;
                    }

                    $this->output['tempData'] = $temp_data;
                }

                $this->request_data = $validator_data;
                $this->gateway();
            }

            $output                     = $this->output;
            $output['callback_ref']     = $reference;
            $output['capture']          = $response_data;

            if($transaction && $transaction->status != PaymentGatewayConst::STATUSSUCCESS) {

                $update_data                        = json_decode(json_encode($transaction->details), true);
                $update_data['gateway_response']    = $response_data;

                // update information
                $transaction->update([
                    'status'    => $status,
                    'details'   => $update_data
                ]);

                // update balance
                $this->updateWalletBalancePaystack($output);
            }

            if(!$transaction){

                // create new transaction with success
                if($output['tempData']->data->creator_guard  == 'agent_api' || $output['tempData']->data->creator_guard == 'agent'){
                    $this->createTransactionChildRecords($output,$status);
                }else{
                    $this->createTransactionPaystack($output,$status);
                }
            }
            logger("Transaction Created Successfully! Status: " . $event_type);

        }
    }

    public function paystackCallbackResponsePayLink($response_data, $gateway){
        $output = $this->output;

        $event_type = $response_data['event'] ?? "";

        if ($event_type == "charge.success") {
            $reference = $response_data['data']['reference'];

            // verify signature START -----------------------------
            $credentials = $this->getPayStackCredentials(['gateway' => $gateway]);
            $secret_key = $credentials->secret_key;

            $hash = hash_hmac('sha512', request()->getContent(), $secret_key);

            if($hash != request()->header('x-paystack-signature')) {
                return false;
            }
            // verify signature END -----------------------------

            // temp data
            $temp_data = TemporaryData::where('identifier', $reference)->first();

            // if transaction is already exists need to update status, balance & response data
            $transaction = Transaction::where('callback_ref', $reference)->first();

            $status = PaymentGatewayConst::STATUSSUCCESS;

            if($temp_data) {
                $gateway_currency_id = $temp_data->data->currency ?? null;
                $gateway_currency = PaymentGatewayCurrency::find($gateway_currency_id);
                if($gateway_currency) {

                    $requested_amount = $temp_data['data']->charge_calculation->requested_amount ?? 0;
                    $validator_data = [
                        $this->currency_input_name => $gateway_currency->alias,
                        $this->amount_input        => $requested_amount,
                        $this->target              => $temp_data['data']->validated->target,
                        $this->email               => $temp_data['data']->validated->email,
                        $this->full_name           => $temp_data['data']->validated->full_name,
                        $this->phone               => $temp_data['data']->validated->phone,
                    ];

                    $get_wallet_model = PaymentGatewayConst::registerWallet()[$temp_data->data->creator_guard];
                    $user_wallet = $get_wallet_model::find($temp_data->data->wallet_id);
                    $this->predefined_user_wallet = $user_wallet;
                    if($temp_data->data->creator_guard  == 'merchant' || $temp_data->data->user_type == 'MERCHANT'){
                        $this->predefined_guard = $user_wallet->merchant->modelGuardName(); // need to update
                        $this->predefined_user = $user_wallet->merchant;
                    }else{
                        $this->predefined_guard = $user_wallet->user->modelGuardName(); // need to update
                        $this->predefined_user = $user_wallet->user;
                    }

                    $this->output['tempData'] = $temp_data;
                }

                $this->request_data = $validator_data;
                $this->payLinkGateway();
            }

            $output                     = $this->output;
            $output['callback_ref']     = $reference;
            $output['capture']          = $response_data;

            if($transaction && $transaction->status != PaymentGatewayConst::STATUSSUCCESS) {

                $update_data                        = json_decode(json_encode($transaction->details), true);
                $update_data['gateway_response']    = $response_data;

                // update information
                $transaction->update([
                    'status'    => $status,
                    'details'   => $update_data
                ]);

                // update balance
                $this->updateWalletBalancePayLink($output);
            }

            if(!$transaction){
                // create new transaction with success
                $this->createTransactionPayLink($output,$status);
            }
            logger("Transaction Pay Link  Created Successfully! Status: " . $event_type);

        }

    }

}
