<?php

namespace App\Http\Controllers\OnlinePayment;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Reseller\ResellerRechargeController;
use App\Models\PgwResponseLog;
use App\Models\ResellerRechargeReport;
use Brian2694\Toastr\Facades\Toastr;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;



class NagadResellerController extends Controller
{

    function getRandomString($length = 45)
    {
        $characters       = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomString     = '';
        for ($i = 0; $i < $length; $i++) {
            $randomString .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomString;
    }

    function getSensitiveData(string $invoice)
    {
        return [
            'merchantId' => config("app.nagad_merchant_id"),
            'datetime'   => Carbon::now(config("app.timezone"))->format("YmdHis"),
            'orderId'    => $invoice,
            'challenge'  => $this->getRandomString()
        ];
    }

    function headers()
    {
        return [
            "Content-Type"     => "application/json",
            "X-KM-IP-V4"       => request()->ip(),
            "X-KM-Api-Version" => "v-0.2.0",
            "X-KM-Client-Type" => "PC_WEB"
        ];
    }

    function encryptWithPublicKey(string $data)
    {
        $publicKey   = "-----BEGIN PUBLIC KEY-----\n" . config('app.nagad_public_key') . "\n-----END PUBLIC KEY-----";
        $keyResource = openssl_get_publickey($publicKey);
        $status      = openssl_public_encrypt($data, $cryptoText, $keyResource);
        if ($status) {
            return base64_encode($cryptoText);
        }
    }

    function signatureGenerate(string $data)
    {
        $private_key = "-----BEGIN RSA PRIVATE KEY-----\n" . config("app.nagad_private_key") . "\n-----END RSA PRIVATE KEY-----";
        $status      = openssl_sign($data, $signature, $private_key, OPENSSL_ALGO_SHA256);
        if ($status) {
            return base64_encode($signature);
        }

    }

    function decryptDataPrivateKey(string $data)
    {
        $private_key = "-----BEGIN RSA PRIVATE KEY-----\n" . config('app.nagad_private_key') . "\n-----END RSA PRIVATE KEY-----";
        openssl_private_decrypt(base64_decode($data), $plain_text, $private_key);
        return $plain_text;
    }

    public function createPayment(Request $request)
    {
        $amount = $request->amount;
        $OrderId = now()->timestamp . $request->reseller_id;

        $baseUrl       = config('app.nagad_base_url') . "check-out/initialize/" . config("app.nagad_merchant_id") . "/{$OrderId}";
        $sensitiveData = $this->getSensitiveData($OrderId);
        $body          = [
            "accountNumber" => config("app.nagad_merchant_number"),
            "dateTime"      => Carbon::now()->timezone(config("timezone"))->format('YmdHis'),
            "sensitiveData" => $this->encryptWithPublicKey(json_encode($sensitiveData)),
            'signature'     => $this->signatureGenerate(json_encode($sensitiveData)),
        ];

        $response = Http::withHeaders($this->headers())->post($baseUrl, $body);
        $initialize = json_decode($response->body());

        if(!isset($initialize->sensitiveData) && !isset($initialize->signature)){
            $data = [
                'message' => $initialize->message,
                'status' => 'error'
            ];
            return $data;
        }

        if ($initialize->sensitiveData && $initialize->signature) {
            $decryptData        = json_decode($this->decryptDataPrivateKey($initialize->sensitiveData));
            $url                = config('app.nagad_base_url') . "/check-out/complete/" . $decryptData->paymentReferenceId;
            $sensitiveOrderData = [
                'merchantId'   => config("app.nagad_merchant_id"),
                'orderId'      => $OrderId,
                'currencyCode' => '050',
                'amount'       => $amount,
                'challenge'    => $decryptData->challenge
            ];

            $response = Http::withHeaders($this->headers())
                ->post($url, [
                    'sensitiveData'       => $this->encryptWithPublicKey(json_encode($sensitiveOrderData)),
                    'signature'           => $this->signatureGenerate(json_encode($sensitiveOrderData)),
                    'merchantCallbackURL' => config("app.nagad_callbackurl")."/admin/nagad-reseller-recharge-callback"."?reseller_id=".$request->reseller_id."&",
                ]);

            try{
                $result = json_decode($response->body());
                $url = $result->callBackUrl;
                $split_url = explode('check-out/', $url);

                $pgw_responser_log = new PgwResponseLog();
                $pgw_responser_log->response = $response->body();
                $pgw_responser_log->payment_for = 'Reseller';
                $pgw_responser_log->payment_method = 'Nagad';
                $pgw_responser_log->source = 'Payment_initiate';
                $pgw_responser_log->user_id = $request->reseller_id;
                $pgw_responser_log->payment_ref_id = $split_url[1];
                $pgw_responser_log->added_by = auth()->user()->id;
                $pgw_responser_log->save();
            }catch(\Exception $e){

            }


            session()->put('nagad_reseller_recharge_reseller_id', $request->reseller_id);
            $result = json_decode($response->body());

            if (isset($result->reason)) {
                $data = [
                    'message' => $result->reason,
                    'status' => 'error'
                ];
                return $data;
            }
            $data = [
                        'message' => $result->callBackUrl,
                        'status' => 'success'
                    ];
            return $data;
        }
    }

    public function nagadResellerRechargeCallback(Request $request)
    {
        $pgw_responser_log = new PgwResponseLog();
        $pgw_responser_log->response = json_encode($request->all());
        $pgw_responser_log->payment_ref_id = $request->payment_ref_id;
        $pgw_responser_log->payment_for = 'Reseller';
        $pgw_responser_log->payment_method = 'Nagad';
        $pgw_responser_log->source = 'Call_back_url';
        $pgw_responser_log->user_id = $request->reseller_id;
        $pgw_responser_log->added_by = auth()->user()->id;
        $pgw_responser_log->save();

        $url      = config('app.nagad_base_url') . "verify/payment/{$request->payment_ref_id}";
        $response = Http::withHeaders($this->headers())->get($url);


        $response_payment = json_decode($response->body(), true);

        if($response_payment['status'] == "Success"){
            DB::beginTransaction();
            try {
                $recharge_report = ResellerRechargeReport::where('payment_gateway_transaction_id', $request->order_id)->count();
                $reseller_id = session()->get('nagad_reseller_recharge_reseller_id');
                if ( $recharge_report == 0 && $reseller_id == $request->reseller_id) {


                    $status =   (new ResellerRechargeController)->recharge(
                        $request->reseller_id,
                        $response_payment['amount'],
                        $request->order_id,
                        $response_payment['issuerPaymentRefNo'],
                        'Nagad-Online',
                        'Payment from Online useing Nagad Payment Gateway. Payment Process By: '.auth()->user()->email,
                    );
                }

                DB::commit();
                $pgw_responser_log->status = 'Success';
                $pgw_responser_log->save();

                if ($status == 'error') {
                    $pgw_responser_log->status = 'Failed';
                    $pgw_responser_log->error_massage = "Recharge UnSuccessfull or already Recharged or duplicate transaction";
                    $pgw_responser_log->save();
                    Toastr::error('Nagad Recharge UnSuccessfull', 'Recharge UnSuccessfull or already Recharged or duplicate transaction');
                } else {
                    Toastr::success('Nagad Recharge Successfull', 'Recharge Successfull');
                }

                return redirect()->route('onlineManagerRecharge', $request->reseller_id);
            } catch (\Throwable $th) {
                $pgw_responser_log->status = 'Failed';
                $pgw_responser_log->error_massage = $th->getMessage();
                $pgw_responser_log->save();

            }
        }else{
            $pgw_responser_log->status = 'Failed';
            $pgw_responser_log->error_massage = $response_payment['message'];
            $pgw_responser_log->save();

            Toastr::error('Nagad Recharge UnSuccessfull', 'Recharge Faild');
            return redirect()->route('onlineManagerRecharge', $request->reseller_id);
        }
        Toastr::error('Nagad Recharge UnSuccessfull', 'Recharge Faild');
        return redirect()->route('onlineManagerRecharge', $request->reseller_id);
    }

}
