<?php

namespace App\Http\Controllers\Gateway;

use Carbon\Carbon;
use App\Models\Plan;
use App\Models\User;
use App\Models\Board;
use App\Models\Deposit;
use App\Models\Investment;
use App\Models\Withdrawal;
use App\Models\Transaction;
use App\Models\Gateway;
use Illuminate\Http\Request;
use App\Models\GeneralSetting;
use App\Models\GatewayCurrency;
use App\Rules\FileTypeValidate;
use App\Models\AdminNotification;
use App\Models\FundTransfer;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

class PaymentController extends Controller
{
    public function __construct()
    {
        return $this->activeTemplate = activeTemplate();
    }

    public function deposit()
    {
        $user = auth()->user();
        $plans = Plan::orderBy('min_amount')->get();
        $pend = Deposit::where('user_id', $user->id)->where('status', '2')->first();
        // if($pend){
        //     $notify[] = ['error', 'You currently have a pending deposit, please wait for confirmation or cancellation and try again'];
        //     return back()->withNotify($notify);
        // }
        $gatewayCurrency = GatewayCurrency::whereHas('method', function ($gate) {
            $gate->where('status', 1);
        })->with('method')->orderby('name')->get();
        $pageTitle = 'Recharge';
        return view($this->activeTemplate . 'user.payment.deposit', compact('gatewayCurrency', 'pageTitle', 'plans'));
    }

    public function depositInsert(Request $request)
    {

        $request->validate([
            'amount' => 'required|numeric|gt:0',
            //'method_code' => 'required',
            //'currency' => 'required',
        ]);

        if ($request->deposit_method == 1) {

            $user = auth()->user();


            $gate = GatewayCurrency::whereHas('method', function ($gate) {
                $gate->where('status', 1);
            })->first();
            if (!$gate) {
                $notify[] = ['error', 'Invalid gateway'];
                return back()->withNotify($notify);
            }

            if ($gate->min_amount > $request->amount || $gate->max_amount < $request->amount) {
                $notify[] = ['error', 'Please follow deposit limit'];
                return back()->withNotify($notify);
            }


            //check pending
            /*$pend = Deposit::where('user_id', $user->id)->where('status','0')->first();
            if($pend){
                $notify[] = ['error', 'You currently have a pending deposit, please wait for confirmation or cancellation and try again'];
                return back()->withNotify($notify);
            }*/


            $pend = Deposit::where('user_id', $user->id)->where('status', '2')->first();
            if ($pend) {
                $notify[] = ['error', 'You currently have a pending deposit, please wait for confirmation or cancellation and try again'];
                return back()->withNotify($notify);
            }

            $charge = $gate->fixed_charge + ($request->amount * $gate->percent_charge / 100);
            $payable = $request->amount + $charge;
            $final_amo = $payable * $gate->rate;

            $data = new Deposit();
            $data->user_id = $user->id;
            $data->method_code = $gate->method_code;
            $data->method_currency = strtoupper($gate->currency);
            $data->amount = $request->amount;
            $data->charge = $charge;
            $data->rate = $gate->rate;
            $data->final_amo = $final_amo;
            $data->btc_amo = 0;
            $data->btc_wallet = "";
            $data->trx = getTrx();
            $data->try = 0;
            $data->status = 0;
            $data->save();
            session()->put('Track', $data->trx);

            if (1000 > $data->method_code) {
                //route('user.deposit.confirm')
                return redirect()->route('user.deposit.confirm');

            } else {
                return redirect()->route('user.deposit.manual.confirm');

            }

        } else {
            $user = auth()->user();


            $gate = GatewayCurrency::where('gateway_alias', 'usdt')->first();
            if (!$gate) {
                $notify[] = ['error', 'Invalid gateway'];
                return back()->withNotify($notify);
            }

            if ($gate->min_amount > $request->amount || $gate->max_amount < $request->amount) {
                $notify[] = ['error', 'Please follow deposit limit'];
                return back()->withNotify($notify);
            }


            //check pending
            /*$pend = Deposit::where('user_id', $user->id)->where('status','0')->first();
            if($pend){
                $notify[] = ['error', 'You currently have a pending deposit, please wait for confirmation or cancellation and try again'];
                return back()->withNotify($notify);
            }*/


            $pend = Deposit::where('user_id', $user->id)->where('status', '2')->first();
            if ($pend) {
                $notify[] = ['error', 'You currently have a pending deposit, please wait for confirmation or cancellation and try again'];
                return back()->withNotify($notify);
            }

            $charge = $gate->fixed_charge + ($request->amount * $gate->percent_charge / 100);
            $payable = $request->amount + $charge;
            $final_amo = $payable * $gate->rate;

            $data = new Deposit();
            $data->user_id = $user->id;
            $data->method_code = $gate->method_code;
            $data->method_currency = strtoupper($gate->currency);
            $data->amount = $request->amount;
            $data->charge = $charge;
            $data->rate = $gate->rate;
            $data->final_amo = $final_amo;
            $data->btc_amo = 0;
            $data->btc_wallet = "";
            $data->trx = getTrx();
            $data->try = 0;
            $data->status = 0;
            $data->save();
            session()->put('Track', $data->trx);

            return redirect()->route('user.usdt-funding');
        }

        //return redirect()->route('user.deposit.preview');
    }


    public function depositPreview()
    {

        $track = session()->get('Track');
        $data = Deposit::where('trx', $track)->where('status', 0)->orderBy('id', 'DESC')->firstOrFail();
        $pageTitle = 'Payment Preview';
        return view($this->activeTemplate . 'user.payment.preview', compact('data', 'pageTitle'));
    }


    public function depositConfirm()
    {
        $track = session()->get('Track');
        //dd($track);


        $deposit = Deposit::where('trx', $track)->where('status', 0)->orderBy('id', 'DESC')->with('gateway')->firstOrFail();


        if ($deposit->method_code >= 1000) {
            $this->userDataUpdate($deposit);
            $notify[] = ['success', 'Your deposit request is queued for approval.'];
            return back()->withNotify($notify);
        }


        $dirName = $deposit->gateway->alias;
        $new = __NAMESPACE__ . '\\' . $dirName . '\\ProcessController';

        $data = $new::process($deposit);
        $data = json_decode($data);


        if (isset($data->error)) {
            $notify[] = ['error', $data->message];
            return redirect()->route(gatewayRedirectUrl())->withNotify($notify);
        }
        if (isset($data->redirect)) {
            return redirect($data->redirect_url);
        }

        // for Stripe V3
        if (@$data->session) {
            $deposit->btc_wallet = $data->session->id;
            $deposit->save();
        }

        $pageTitle = 'Payment Confirm';
        return view($this->activeTemplate . $data->view, compact('data', 'pageTitle', 'deposit'));
    }


    public static function userDataUpdate($trx)
    {
        $general = GeneralSetting::first();
        $data = Deposit::where('trx', $trx)->first();
        if ($data->status == 0) {
            $data->status = 1;
            $data->save();

            $user = User::find($data->user_id);
            $user->balance += $data->amount;
            $user->save();

            $transaction = new Transaction();
            $transaction->user_id = $data->user_id;
            $transaction->amount = $data->amount;
            $transaction->post_balance = $user->balance;
            $transaction->charge = $data->charge;
            $transaction->trx_type = '+';
            $transaction->details = 'Deposit Via ' . $data->gatewayCurrency()->name;
            $transaction->trx = $data->trx;
            $transaction->save();


            $referral = User::where('id', $user->ref_by)->first();
            if ($referral) {
                $refAmo = ($data->amount * $general->depo_com) / 100;
                $referral->balance += $refAmo;
                $referral->save();

                $transaction = new Transaction();
                $transaction->user_id = $referral->id;
                $transaction->amount = $refAmo;
                $transaction->post_balance = getAmount($referral->balance);
                $transaction->charge = 0;
                $transaction->trx_type = '+';
                $transaction->details = 'Deposit Commission from ' . $user->username;
                $transaction->trx = $data->trx;
                $transaction->save();

            }

            $adminNotification = new AdminNotification();
            $adminNotification->user_id = $user->id;
            $adminNotification->title = 'Deposit successful via ' . $data->gatewayCurrency()->name;
            $adminNotification->click_url = urlPath('admin.deposit.successful');
            $adminNotification->save();

            notify($user, 'DEPOSIT_COMPLETE', [
                'method_name' => $data->gatewayCurrency()->name,
                'method_currency' => $data->method_currency,
                'method_amount' => showAmount($data->final_amo),
                'amount' => showAmount($data->amount),
                'charge' => showAmount($data->charge),
                'currency' => $general->cur_text,
                'rate' => showAmount($data->rate),
                'trx' => $data->trx,
                'post_balance' => showAmount($user->balance)
            ]);


        }
    }

    public function manualDepositConfirm()
    {
        $track = session()->get('Track');
        $data = Deposit::with('gateway')->where('status', 0)->where('trx', $track)->first();
        if (!$data) {
            return redirect()->route(gatewayRedirectUrl());
        }
        if ($data->method_code > 999) {

            $pageTitle = 'Manual Deposit Step Confirm';
            $method = $data->gatewayCurrency();
            return view($this->activeTemplate . 'user.manual_payment.manual_confirm', compact('data', 'pageTitle', 'method'));
        }
        abort(404);
    }

    public function manualDepositUpdate(Request $request)
    {
        $track = session()->get('Track');
        $data = Deposit::with('gateway')->where('status', 0)->where('trx', $track)->first();
        if (!$data) {
            return redirect()->route(gatewayRedirectUrl());
        }

        $params = json_decode($data->gatewayCurrency()->gateway_parameter);

        $rules = [];
        $inputField = [];
        $verifyImages = [];

        if ($params != null) {
            foreach ($params as $key => $custom) {
                $rules[$key] = [$custom->validation];
                if ($custom->type == 'file') {
                    array_push($rules[$key], 'image');
                    array_push($rules[$key], new FileTypeValidate(['jpg', 'jpeg', 'png']));
                    array_push($rules[$key], 'max:2048');

                    array_push($verifyImages, $key);
                }
                if ($custom->type == 'text') {
                    array_push($rules[$key], 'max:191');
                }
                if ($custom->type == 'textarea') {
                    array_push($rules[$key], 'max:300');
                }
                $inputField[] = $key;
            }
        }
        $this->validate($request, $rules);


        $directory = date("Y") . "/" . date("m") . "/" . date("d");
        $path = imagePath()['verify']['deposit']['path'] . '/' . $directory;
        $collection = collect($request);
        $reqField = [];
        if ($params != null) {
            foreach ($collection as $k => $v) {
                foreach ($params as $inKey => $inVal) {
                    if ($k != $inKey) {
                        continue;
                    } else {
                        if ($inVal->type == 'file') {
                            if ($request->hasFile($inKey)) {
                                try {
                                    $reqField[$inKey] = [
                                        'field_name' => $directory . '/' . uploadImage($request[$inKey], $path),
                                        'type' => $inVal->type,
                                    ];
                                } catch (\Exception $exp) {
                                    $notify[] = ['error', 'Could not upload your ' . $inKey];
                                    return back()->withNotify($notify)->withInput();
                                }
                            }
                        } else {
                            $reqField[$inKey] = $v;
                            $reqField[$inKey] = [
                                'field_name' => $v,
                                'type' => $inVal->type,
                            ];
                        }
                    }
                }
            }
            $data->detail = $reqField;
        } else {
            $data->detail = null;
        }


        $data->status = 2; // pending
        $data->save();


        $adminNotification = new AdminNotification();
        $adminNotification->user_id = $data->user->id;
        $adminNotification->title = 'Deposit request from ' . $data->user->username;
        $adminNotification->click_url = urlPath('admin.deposit.details', $data->id);
        $adminNotification->save();

        $message = Split_Hide_Name($data->user->username) . " deposited " . amount_format($data->final_amo);
        $board = new Board();
        $board->messages = $message;
        $board->save();
        $general = GeneralSetting::first();
        notify($data->user, 'DEPOSIT_REQUEST', [
            'method_name' => $data->gatewayCurrency()->name,
            'method_currency' => $data->method_currency,
            'method_amount' => showAmount($data->final_amo),
            'amount' => showAmount($data->amount),
            'charge' => showAmount($data->charge),
            'currency' => $general->cur_text,
            'rate' => showAmount($data->rate),
            'trx' => $data->trx
        ]);

        $notify[] = ['success', 'You have deposit request has been taken.'];
        return redirect()->route('user.deposit.history')->withNotify($notify);
    }


    // public function shpay(Request $request)
    // {
    //     $request->validate([
    //         'amount' => 'required|numeric|gt:0',
    //         //'method_code' => 'required',
    //         //'currency' => 'required',
    //     ]);

    //     $gateway = Gateway::where('alias','Shpay')->first();

    //     $user = auth()->user();
    //     $ref = getTrx();
    //     $url = route('shpay');


    //     $gate = GatewayCurrency::whereHas('method', function ($gate) {
    //         $gate->where('status', 1);
    //     })->first();

    //     if ($gate->min_amount > $request->amount || $gate->max_amount < $request->amount) {
    //         $notify[] = ['error', 'Please follow deposit limit'];
    //         return back()->withNotify($notify);
    //     }

    //     $curl = curl_init();

    //     curl_setopt_array($curl, array(
    //     CURLOPT_URL => 'https://cashier.ptpay001.com/v1/trans/payIn',
    //     CURLOPT_RETURNTRANSFER => true,
    //     CURLOPT_ENCODING => '',
    //     CURLOPT_MAXREDIRS => 10,
    //     CURLOPT_TIMEOUT => 0,
    //     CURLOPT_FOLLOWLOCATION => true,
    //     CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
    //     CURLOPT_CUSTOMREQUEST => 'POST',
    //     CURLOPT_POSTFIELDS =>'{
    //         "mchtNo": "1010583301481141",
    //         "orderNo": "'.$ref.'",
    //         "amount": "'.$request->amount.'",
    //         "callBackUrl": "'.$url.'",
    //         "returnUrl": "https://forge-ng.com"
    //     }',
    //     CURLOPT_HTTPHEADER => array(
    //         'Content-Type: text/json'
    //     ),
    //     ));

    //     $response = curl_exec($curl);

    //     curl_close($curl);

    //     //dd($response);

    //     $result = json_decode($response, true);

    //     //dd($result);


    //     //echo $result['message'];
    //     if ($result['msg'] == 'success') {

    //         $charge = $gate->fixed_charge + ($request->amount * $gate->percent_charge / 100);
    //         $payable = $request->amount + $charge;
    //         $final_amo = $payable * $gate->rate;

    //         $data = new Deposit();
    //         $data->user_id = $user->id;
    //         $data->method_code = $gate->method_code;
    //         $data->method_currency = strtoupper($gate->currency);
    //         $data->amount = $request->amount;
    //         $data->charge = $charge;
    //         $data->rate = $gate->rate;
    //         $data->final_amo = $final_amo;
    //         $data->btc_amo = 0;
    //         $data->btc_wallet = "";
    //         $data->trx = $ref;
    //         $data->try = 0;
    //         $data->status = 2;
    //         $data->save();

    //         $link = $result['data']['payUrl'];
    //         return redirect($link);

    //     }else{

    //         //dd($response);

    //         $notify[] = ['error', $result['msg']];
    //         return back()->withNotify($notify);
    //     }
    // }


    public function shpay(Request $request)
    {
        $request->validate([
            'amount' => 'required|numeric|gt:0',
            //'method_code' => 'required',
            //'currency' => 'required',
        ]);

        //dd($request->amount);

        $user = auth()->user();


        $gate = GatewayCurrency::whereHas('method', function ($gate) {
            $gate->where('status', 1);
        })->first();
        if (!$gate) {
            $notify[] = ['error', 'Invalid gateway'];
            return back()->withNotify($notify);
        }

        if ($gate->min_amount > $request->amount || $gate->max_amount < $request->amount) {
            $notify[] = ['error', 'Please follow deposit limit'];
            return back()->withNotify($notify);
        }

        $gateway = Gateway::where('alias', 'Qepay')->first();

        $ref = getTrx();
        $url = route('shpay');
        $time = Carbon::now()->format('Y-m-d H:i:s');


        // Retrieve merchant and security keys from the environment variables
        $version = "1.0";
        $mch_id = env('mchtId'); // Merchant ID
        $sha256_key = env('sha256_key');
        $mch_private_key = env('mch_private_key');

        // Generate a unique order number (out_trade_no)
        $out_trade_no = date('YmdHis') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);

        // URLs for notification and page redirect
        $notifyUrl = route('shpay');
        $pageUrl = route('user.home');

        // Prepare the data (exclude 'sign' and empty parameters from the query string)
        $data = [
            "merNo" => $mch_id,
            "merOrderNo" => $out_trade_no,
            "name" => "customer",
            "email" => "test@gmail.com",
            "phone" => $user->mobile,
            "orderAmount" => number_format($request->amount, 2, '.', ''),
            "currency" => "MYR",
            "busiCode" => "111002", // Malaysian Wallet
            "pageUrl" => $pageUrl,
            "notifyUrl" => $notifyUrl,
            "timestamp" => $this->milliseconds(),
        ];

        // Generate HMAC-SHA256 signature
        $data["sign"] = $this->makeSign($data);

        // Convert to JSON
        $jsonData = json_encode($data);

        // CURL INIT
        $ch = curl_init();

        curl_setopt_array($ch, [
            CURLOPT_URL => "https://naskl.gctpk.com/payin/createOrder",
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POST => true,
            CURLOPT_HTTPHEADER => [
                "Content-Type: application/json",
                "Content-Length: " . strlen($jsonData)
            ],
            CURLOPT_POSTFIELDS => $jsonData,
        ]);

        $response = curl_exec($ch);
        $error = curl_error($ch);

        curl_close($ch);


        $result = json_decode($response, true);

        //return $response->json();

        dd($result);

        // Check if the response is successful
        if (!isset($result["code"]) || $result["code"] != 0) {
            $notify[] = ['error', $result["msg"] ?? "Payment failed"];
            return back()->withNotify($notify);
        }

        // Calculate charges and final amount
        $charge = $gate->fixed_charge + ($request->amount * $gate->percent_charge / 100);
        $payable = $request->amount + $charge;
        $final_amo = $payable * $gate->rate;

        // Save the deposit details in the database
        $data = new Deposit();
        $data->user_id = $user->id;
        $data->method_code = $gate->method_code;
        $data->method_currency = strtoupper($gate->currency);
        $data->amount = $request->amount;
        $data->charge = $charge;
        $data->rate = $gate->rate;
        $data->final_amo = $final_amo;
        $data->btc_amo = 0;
        $data->btc_wallet = "";
        $data->trx = $ref;
        $data->try = 0;
        $data->status = 2; // Pending status
        $data->save();

        // Redirect to the payment URL provided in the response
        $link = $result["data"]["payUrl"];
        return redirect($link);
    }


    /**
     * CloudPay Gateway Integration
     * Supports GCash and PayMaya payment methods
     */
    public function cloudpay(Request $request)
    {
        $request->validate([
            'amount' => 'required|numeric|min:20',
            'gateway' => 'required|in:gcash,paymaya',
        ]);

        $user = auth()->user();

        // Get gateway configuration
        $gate = GatewayCurrency::whereHas('method', function ($gate) {
            $gate->where('status', 1);
        })->first();

        if (!$gate) {
            $notify[] = ['error', 'Invalid gateway'];
            return back()->withNotify($notify);
        }

        if ($gate->min_amount > $request->amount || $gate->max_amount < $request->amount) {
            $notify[] = ['error', 'Please follow deposit limit'];
            return back()->withNotify($notify);
        }

        // CloudPay Configuration
        $MERCHANT_ID = env('CLOUDPAY_MERCHANT_ID');
        $SECRET_KEY = env('CLOUDPAY_SECRET_KEY');
        $API_URL = "https://cloud.la2568.site/api/transfer";

        // Callback URLs
        $CALLBACK_URL = route('shpay');
        $RETURN_URL = route('user.home');

        // Channel mapping
        $channelMap = [
            "gcash" => [
                "payment_type" => "7",
                "bank_code" => "mya",
                "name" => "GCash"
            ],
            "paymaya" => [
                "payment_type" => "3",
                "bank_code" => "PMP",
                "name" => "PayMaya"
            ]
        ];

        $method = $request->gateway;
        $amount = number_format($request->amount, 2, '.', '');
        $order_id = "ZIA" . date("YmdHis") . rand(1000, 9999);

        // Build request data
        $requestData = [
            "merchant" => $MERCHANT_ID,
            "payment_type" => $channelMap[$method]['payment_type'],
            "amount" => $amount,
            "order_id" => $order_id,
            "bank_code" => $channelMap[$method]['bank_code'],
            "callback_url" => $CALLBACK_URL,
            "return_url" => $RETURN_URL,
        ];

        // Generate signature
        $requestData['sign'] = $this->makeCloudPaySign($requestData, $SECRET_KEY);

        // Log request
        Log::info('[CloudPay] Payment Request', $requestData);

        // Send request to CloudPay
        $ch = curl_init($API_URL);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($requestData));
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        $response = curl_exec($ch);
        $curlError = curl_error($ch);
        curl_close($ch);

        // Log response
        Log::info('[CloudPay] Payment Response', ['response' => $response, 'error' => $curlError]);

        $result = json_decode($response, true);
        //dd($result);

        if (!$result || (string) $result['status'] !== "1") {
            $notify[] = ['error', 'Payment gateway error: ' . ($result['msg'] ?? 'Unknown error')];
            return back()->withNotify($notify);
        }

        // Extract payment URL
        $pay_url = $result['redirect_url']
            ?? $result['qrcode_url']
            ?? $result['gcash_qr_url']
            ?? '';

        if (!$pay_url) {
            $notify[] = ['error', 'Payment URL not received'];
            return back()->withNotify($notify);
        }

        // Calculate charges
        $charge = $gate->fixed_charge + ($request->amount * $gate->percent_charge / 100);
        $payable = $request->amount + $charge;
        $final_amo = $payable * $gate->rate;

        // Save deposit record
        $deposit = new Deposit();
        $deposit->user_id = $user->id;
        $deposit->method_code = $gate->method_code;
        $deposit->method_currency = strtoupper($gate->currency);
        $deposit->amount = $request->amount;
        $deposit->charge = $charge;
        $deposit->rate = $gate->rate;
        $deposit->final_amo = $final_amo;
        $deposit->btc_amo = 0;
        $deposit->btc_wallet = $pay_url;
        $deposit->trx = $order_id;
        $deposit->try = 0;
        $deposit->status = 2; // Pending
        $deposit->detail = json_encode([
            'method' => $channelMap[$method]['name'],
            'response' => $result
        ]);
        $deposit->save();

        // Redirect to payment URL
        return redirect($pay_url);
    }


    public function shpayipn(Request $request)
    {
        Log::info('[CloudPay Deposit] Callback received', $request->all());

        $MERCHANT_ID = env('CLOUDPAY_MERCHANT_ID', 'Zia');
        $SECRET_KEY = env('CLOUDPAY_SECRET_KEY', '5844d3b3d2127a6f39fe80ac7866b442');

        $data = $request->all();

        if (empty($data)) {
            Log::error('[CloudPay Deposit] IPN Error: Empty Data');
            return response('NO DATA', 400);
        }

        // Basic Validation
        if (!isset($data['merchant'], $data['order_id'], $data['amount'], $data['status'], $data['sign'])) {
            Log::error('[CloudPay Deposit] IPN Error: Invalid Parameters', $data);
            return response('INVALID PARAMS', 400);
        }

        if ($data['merchant'] !== $MERCHANT_ID) {
            Log::error('[CloudPay Deposit] IPN Error: Invalid Merchant', ['received' => $data['merchant'], 'expected' => $MERCHANT_ID]);
            return response('INVALID MERCHANT', 400);
        }

        // Signature Verification
        $receivedSign = $data['sign'];
        $expectedSign = $this->makeCloudPaySign($data, $SECRET_KEY);

        // if ($receivedSign !== $expectedSign) {
        //     Log::error('[CloudPay Deposit] IPN Error: Invalid Sign', [
        //         'received' => $receivedSign,
        //         'expected' => $expectedSign
        //     ]);
        //     return response('INVALID SIGN', 400);
        // }

        $order_id = $data['order_id'];
        $status = (int) $data['status'];
        $message = $data['message'] ?? 'Payment Status Update';

        // Fetch deposit
        $deposit = Deposit::where('trx', $order_id)->first();

        if (!$deposit) {
            Log::error('[CloudPay Deposit] IPN Error: Order not found', ['order_id' => $order_id]);
            return response('ORDER NOT FOUND', 404);
        }

        // Already Processed
        if ($deposit->status == 1) {
            return "SUCCESS";
        }

        $raw = json_encode($data);

        // Failed Payment (5 = success, anything else is failure)
        if ($status !== 5) {
            $deposit->status = 3; // Rejected
            $deposit->detail = $raw;
            $deposit->save();
            Log::info('[CloudPay Deposit] IPN: Payment rejected', ['order_id' => $order_id, 'status' => $status]);
            return "SUCCESS";
        }

        // Success - Credit User
        $deposit->status = 1; // Approved
        $deposit->detail = $raw;
        $deposit->save();

        $user = User::find($deposit->user_id);
        $user->balance += $deposit->amount;
        $user->save();

        // Create transaction record
        $transaction = new Transaction();
        $transaction->user_id = $deposit->user_id;
        $transaction->amount = $deposit->amount;
        $transaction->post_balance = $user->balance;
        $transaction->charge = $deposit->charge;
        $transaction->trx_type = '+';
        $transaction->details = 'Deposit Via CloudPay';
        $transaction->trx = $deposit->trx;
        $transaction->save();

        // Admin notification
        $adminNotification = new AdminNotification();
        $adminNotification->user_id = $user->id;
        $adminNotification->title = 'Deposit successful via CloudPay';
        $adminNotification->click_url = urlPath('admin.deposit.successful');
        $adminNotification->save();

        Log::info('[CloudPay Deposit] IPN: Payment processed successfully', ['order_id' => $order_id]);

        return "SUCCESS";
    }

    // public function shpayipn(Request $request)
    // {

    //         $traderesult = $request->payStatus;
    //         $ref = $request->orderNo;

    //         if($traderesult == '1')
    //         {
    //             $deposit = Deposit::where('trx',$ref)->where('status',2)->firstOrFail();
    //             $deposit->status = 1;
    //             $deposit->save();

    //             $user = User::find($deposit->user_id);
    //             $user->balance = $user->balance + $deposit->amount;
    //             $user->save();

    //             //$general = GeneralSetting::first();

    //             //$referral = User::where('id',$user->ref_by)->first();


    //             $transaction = new Transaction();
    //             $transaction->user_id = $deposit->user_id;
    //             $transaction->amount = $deposit->amount;
    //             $transaction->post_balance = $user->balance;
    //             $transaction->charge = $deposit->charge;
    //             $transaction->trx_type = '+';
    //             $transaction->details = 'Deposit Via PTPAY';
    //             $transaction->trx =  $deposit->trx;
    //             $transaction->save();
    //         }
    //         else{
    //             $deposit = Deposit::where('trx',$ref)->where('status',2)->firstOrFail();
    //             $deposit->status = 3;
    //             $deposit->save();
    //         }

    // }

    public function shpaywithdraw(Request $request)
    {
        $gateway = Gateway::where('alias', 'Shpay')->first();


        $ref = getTrx();
        $date = date("Y-m-d H:i:s");
        $mchid = json_decode($gateway->gateway_parameters)->mchtId->value;
        $appid = json_decode($gateway->gateway_parameters)->appId->value;
        $key = json_decode($gateway->gateway_parameters)->key->value;


        $p = array(
            "mchtId" => $mchid,
            "appId" => $appid,
            'countryCode' => "NG",
            'notifyUrl' => "test",
            'subject' => "withdraw",
            'accountName' => $request->account_name,
            'accountNo' => $request->account_number,
            'bankCode' => $request->bank_code,
            "requestTime" => $date,
            "signType" => "MD5",
            "subject" => "withdraw",
            "transAmt" => $request->amount,
            "outTradeNo" => $ref,
        );

        ksort($p);
        $string = '';
        foreach ($p as $oneKey => $oneValue)
            $string .= $oneKey . "=" . $oneValue . "&";
        $string_without_last_and = substr($string, 0, -1);
        $digest = $string_without_last_and . $key;
        $sign = strtoupper(md5($digest));

        // Construct the URL with the endpoint
        $url = "https://transapi.shpays.com/v1/trans/payOut";

        // Make the API request
        $response = Http::post($url, [
            'mchtId' => "$mchid",
            'appId' => "$appid",
            'countryCode' => "NG",
            'requestTime' => "$date",
            'notifyUrl' => "test",
            'outTradeNo' => "$ref",
            'signType' => "MD5",
            'subject' => "withdraw",
            'transAmt' => "$request->amount",
            'accountName' => $request->account_name,
            'accountNo' => $request->account_number,
            'bankCode' => $request->bank_code,
            'sign' => "$sign",
        ]);

        // You can process the response as needed (e.g., convert JSON to array)
        $responseData = $response->json();

        // Handle the API response here...

        try {
            $notify[] = ['success', $responseData['result']['message']];
            return back()->withNotify($notify);
        } catch (\Throwable $th) {
            $notify[] = ['error', 'Failed'];
            return back()->withNotify($notify);
        }
    }

    public function flutterwaveipn(Request $request)
    {


        $general = GeneralSetting::first();
        $ref = $request['data']['reference'];
        if ($request->event == "transfer.completed") {

            $curl = curl_init();

            curl_setopt_array($curl, array(
                CURLOPT_URL => 'https://api.flutterwave.com/v3/transfers/' . $request['data']['id'],
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => '',
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 0,
                CURLOPT_FOLLOWLOCATION => true,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => 'GET',
                CURLOPT_HTTPHEADER => array(
                    'Authorization: Bearer ' . $general->flutterwave_key
                ),
            ));

            $responses = curl_exec($curl);

            curl_close($curl);
            $res = json_decode($responses);
            if ($res->data->status == "SUCCESSFUL") {
                //true
                $fund = FundTransfer::where('reference', $ref)->first();

                $withdrawal = Withdrawal::where('id', $fund->withdrawal_id)->first();

                $withdrawal->status = 1;
                $withdrawal->save();

            } elseif ($res->data->status == "FAILED") {

                $fund = FundTransfer::where('reference', $ref)->first();

                $withdrawal = Withdrawal::where('id', $fund->withdrawal_id)->first();

                $withdrawal->status = 3;
                $q = $withdrawal->save();
                if ($q) {
                    $user = User::where('id', $withdrawal->user_id)->first();
                    $user->bonus_balance += $withdrawal->amount;
                    $user->save();
                }
            } else {
                $withdrawal = Withdrawal::where('trx', $ref)->first();
                $withdrawal->status = 3;
                $q = $withdrawal->save();
                if ($q) {
                    $user = User::where('id', $withdrawal->user_id)->first();
                    $user->bonus_balance += $withdrawal->amount;
                    $user->save();
                }
            }



        }

    }


    public function shpaywithdrawipn(Request $request)
    {
        Log::info('[CloudPay Payout] Callback received', $request->all());

        $MERCHANT_ID = env('CLOUDPAY_MERCHANT_ID', 'Zia');
        $SECRET_KEY = env('CLOUDPAY_SECRET_KEY', '5844d3b3d2127a6f39fe80ac7866b442');

        $data = $request->all();

        if (empty($data)) {
            Log::error('[CloudPay Payout] IPN Error: Empty Data');
            return response('NO DATA', 400);
        }

        // Basic Validation
        if (!isset($data['merchant'], $data['order_id'], $data['status'], $data['sign'])) {
            Log::error('[CloudPay Payout] IPN Error: Invalid Parameters', $data);
            return response('INVALID PARAMS', 400);
        }

        if ($data['merchant'] !== $MERCHANT_ID) {
            Log::error('[CloudPay Payout] IPN Error: Invalid Merchant', ['received' => $data['merchant'], 'expected' => $MERCHANT_ID]);
            return response('INVALID MERCHANT', 400);
        }

        // Signature Verification
        $receivedSign = $data['sign'];
        $expectedSign = $this->makeCloudPaySign($data, $SECRET_KEY);

        // if ($receivedSign !== $expectedSign) {
        //     Log::error('[CloudPay Payout] IPN Error: Invalid Sign', [
        //         'received' => $receivedSign,
        //         'expected' => $expectedSign
        //     ]);
        //     return response('INVALID SIGN', 400);
        // }

        $order_id = $data['order_id'];
        $status = (int) $data['status'];

        // Fetch FundTransfer/Withdrawal
        $payment = FundTransfer::where('reference', $order_id)->first();
        if (!$payment) {
            $withdrawal = Withdrawal::where('trx', $order_id)->first();
        } else {
            $withdrawal = Withdrawal::find($payment->withdrawal_id);
        }

        if (!$withdrawal) {
            Log::error('[CloudPay Payout] IPN Error: Withdrawal not found', ['order_id' => $order_id]);
            return response('WITHDRAWAL NOT FOUND', 404);
        }

        // Already Processed
        if ($withdrawal->status == 1) {
            return "SUCCESS";
        }

        // Status: 5 = success, 3 = failure (rejection)
        if ($status == 5) {
            $withdrawal->status = 1; // Approved
            $withdrawal->save();
            Log::info('[CloudPay Payout] IPN: Withdrawal approved', ['order_id' => $order_id]);
        } elseif ($status == 3) {
            if ($withdrawal->status != 3) {
                $withdrawal->status = 3; // Rejected
                $withdrawal->save();

                // Refund user
                $user = User::find($withdrawal->user_id);
                if ($withdrawal->is_bonus) {
                    $user->bonus_balance += $withdrawal->amount;
                } else {
                    $user->balance += $withdrawal->amount;
                }
                $user->save();

                Log::info('[CloudPay Payout] IPN: Withdrawal rejected and refunded', ['order_id' => $order_id]);
            }
        }

        return "SUCCESS";
    }


    /**
     * Generate HmacSHA256 signature
     */
    private function makeSign(array $data)
    {
        // Sort ASC by ASCII
        ksort($data);

        $str = '';
        foreach ($data as $k => $v) {
            if (!empty($v)) {
                $str .= $k . '=' . $v . '&';
            }
        }

        $str = rtrim($str, '&');

        return hash_hmac("sha256", $str, env('sha256_key'));
    }

    /**
     * RSA Encrypt (only needed for payout, not payin)
     */
    private function rsaEncrypt($signA)
    {
        $privateKey = chunk_split(env('mch_private_key'), 64, "\n");
        $privateKey = "-----BEGIN PRIVATE KEY-----\n" . $privateKey . "-----END PRIVATE KEY-----\n";

        $opensslKey = openssl_pkey_get_private($privateKey);

        openssl_private_encrypt($signA, $encryptData, $opensslKey);

        return base64_encode($encryptData);
    }

    /**
     * Generate 13-digit timestamp
     */
    private function milliseconds()
    {
        return (int) floor(microtime(true) * 1000);
    }

    /**
     * Generate unique order number
     */
    private function generateOrderNo()
    {
        return date('YmdHis') . substr(implode('', array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    }

    /**
     * Generate CloudPay signature (MD5)
     */
    private function makeCloudPaySign(array $data, $key)
    {
        ksort($data);
        $str = "";
        foreach ($data as $k => $v) {
            if ($v !== "" && $k !== "sign") {
                $str .= $k . "=" . $v . "&";
            }
        }
        $str .= "key=" . $key;
        return md5($str);
    }

    /**
     * CloudPay Callback Handler
     */


}