<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Http\Controllers\Gateway\KrakenAPI;
use App\Models\BlockchainWallet;
use App\Models\Coins;
use App\Models\CryptoTradingProfitTransaction;
use App\Models\CryptoTradingTransaction;
use App\Models\CryptoTransaction;
use App\Models\TransactionHistory;
use App\Models\User;
use App\Models\VirtualAccounts;
use BitcoinPHP\BitcoinECDSA\BitcoinECDSA;
use BitWasp\Bitcoin\Address\PayToPubKeyHashAddress;
use BitWasp\Bitcoin\Key\Deterministic\HierarchicalKeyFactory;
use BitWasp\Bitcoin\Network\NetworkFactory;
use BitWasp\Bitcoin\PrivateKeyFactory;
use btc\HD;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\RequestException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Session;
use KingFlamez\Rave\Facades\Rave as Flutterwave;
use Nimiq\XPub;
use PrevailExcel\Nowpayments\Facades\Nowpayments;
use Samrap\Gemini\Gemini;
use stdClass;

class CryptoController extends Controller
{

    private $network = NULL;
    private $baseUrl='https://api.sandbox.gemini.com/v1';
    private $secretKey='master-oOI44bqYu7HeICPhV8ii';

    public function privateRequest(string $api, array $data = []) : array
    {


        $uri = $this->baseUrl.trim($api, '/');
        $endpoint = sprintf('/%s/%s', self::API_VERSION, trim($api, '/'));
        $payload = new Payload($endpoint, $data);
        $request = $this->messageFactory->createRequest('POST', $uri, [
            'Content-Type' => 'text/plain',
            'Content-Length' => 0,
            'X-GEMINI-APIKEY' => $this->key,
            'X-GEMINI-PAYLOAD' => $payload->encode(),
            'X-GEMINI-SIGNATURE' => Signature::generate($payload, $this->secret),
            'Cache-Control' => 'no-cache',
        ]);

        return $this->getResponseJson($this->send($request));
    }
    public function __construct($network = 'bitcoin')
    {
        $this->network = NetworkFactory::bitcoin();

    }
    public function tradeCrypto()
    {

        $coins = Coins::where('status', '1')->get();
        $assets = VirtualAccounts::where('user_id',Auth()->user()->id)->get();

        return view('user.crypto.trade_crypto', compact('coins', 'assets'));
    }
    //
    public function tradeCryptoTest(){
        $client = new \GuzzleHttp\Client();

// Validate and sanitize user input before using it
        $coin = trim(strtoupper('btc')); // Assuming coin comes from a GET parameter

        $url = sprintf('https://api.binance.us/api/v3/ticker/price?symbol=%sUSDT', $coin);

        try {
            $response = $client->get($url);
        } catch (Exception $e) {
            // Handle the error gracefully, e.g., log the error and provide a user-friendly message
            echo "An error occurred while fetching data: " . $e->getMessage();
            exit;
        }

// Assuming the response is successful, decode the JSON and check for errors
        $data = json_decode($response->getBody(), true);

        if (isset($data['error'])) {
            // Handle API error
            echo "API Error: " . $data['error']['message'];
            exit;
        } else {
            // Process the price data from $data
            echo "The current price of " . $coin . " is " . $data['price'];
        }
//test rate from binance
        $ch = curl_init('https://api.binance.us/api/v3/ticker/price?symbol=BTCUSDT');
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt($ch, CURLOPT_USERAGENT, 'r2t');
        curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
        curl_setopt($ch, CURLOPT_TIMEOUT, false ? $timeout : 7);
        curl_setopt($ch, CURLOPT_HEADER, false);
        //$crypto_rate_usd = json_decode(bxc_curl('https://api.binance.us/api/v3/ticker/price?symbol=' . 'btc' . 'USD'), true)['price'];
        // $rate = 1 / (floatval($crypto_rate_usd) * '1');

        $response = curl_exec($ch);
        if (curl_errno($ch) > 0) {
            $error = curl_error($ch);
            curl_close($ch);
            return $error;
        }
        curl_close($ch);
        dd(  $response);
        $key = 'account-D5mUBiT8OTcBqAxCjIGn';
        $secret = 'qTmYHwY6FKoJ4HSFjLagS52iAUr';
        $gemini = new Gemini($key, $secret);
        // $gemini = new Gemini();
        $symbols = $gemini->newDepositAddress('btc');

        dd($symbols['address']);
        /// Replace these with your actual API credentials
        $apiKey = 'YOUR_API_KEY';
        $apiSecret = 'YOUR_API_SECRET';

// URL for retrieving order book data
        $url = 'https://api.gemini.com/v1/addresses/bitcoin';

// Generate the signature for the request
        $timestamp = gmdate('Y-m-d\TH:i:s\Z');
        $payload = $timestamp . $url;
        $signature = hash_hmac('sha384', $payload, $apiSecret, true);
        $encodedSignature = base64_encode($signature);

// Set headers
        $headers = array(
            'X-GEMINI-APIKEY: ' . $apiKey,
            'X-GEMINI-PAYLOAD: ' . $payload,
            'X-GEMINI-SIGNATURE: ' . $encodedSignature,
            'Content-Type: application/json'
        );

// Send GET request and retrieve response
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);

// Decode the JSON response
        $data = json_decode($response, true);
        dd($data);
// Check for errors
        if (isset($data['error'])) {
            echo 'Error: ' . $data['error'];
        } else {
            // Process the market data (e.g., display ask and bid prices)
            echo 'Ask price: ' . $data['ask'] . '<br>';
            echo 'Bid price: ' . $data['bid'];
        }


        $apiKey = 'master-oOI44bqYu7HeICPhV8ii';
        $apiSecret = '3pXwYZwxfjiaXymaLP5jo4QcejQ';

        // URL for retrieving order book data
        $url = 'https://api.sandbox.gemini.com/v1/order/book/' . 'btcusd';

        // Generate the signature for the request
        $timestamp = gmdate('Y-m-d\TH:i:s\Z');
        $payload = $timestamp . $url;
        $signature = hash_hmac('sha384', $payload, $apiSecret, true);
        $encodedSignature = base64_encode($signature);

        // Set headers
        $headers = [
            'X-GEMINI-APIKEY' => $apiKey,
            'X-GEMINI-PAYLOAD' => $payload,
            'X-GEMINI-SIGNATURE' => $encodedSignature,
            'Content-Type' => 'application/json'
        ];

        // Send GET request using Laravel's Http facade
        $response = Http::withHeaders($headers)->get($url);

        // Check for errors
        /* if ($response->failed()) {
             return response()->json(['error' => $response->json('error')], $response->getStatusCode());
         }*/

        // Decode the JSON response
        $data = $response->json();

        dd($response);
        // phpinfo();
//die();

        $xpub = 'xpub6CU38b3dFGkZMFqNk9Zcvf3DWHCzQmk3n3hA8pTPMNwi6f6KzxjxvFfvatpXUJoYEqcWQhswChYS1nfxCeUVe52HjnL1jPtynHEMASDzr8c';
        $hdFactory = new HierarchicalKeyFactory();
        $key = $hdFactory->fromExtended($xpub, $this->network);
        $hardened = $key->derivePath("0/0");
        $privateKey =  $hardened->getPrivateKey()->toWif($this->network);
        $address = new PayToPubKeyHashAddress($hardened->getPublicKey()->getPubKeyHash($this->network));
        $address = $address->getAddress($this->network);



        $cred = new stdClass();
        $cred->balance = 0;
        $cred->address = $address;
        $cred->privateKey = $privateKey;

        return $json = json_encode($cred);



        $private = PrivateKeyFactory::create();
        echo $private->getAddress()->getAddress();
        $bitcoin = new BitcoinLib();
        $privateKey = 'cQ4E323v7n4s5zG3z8sM432v89n4s5zG3z8sM432v89n4s5zG3z8sM432';
        $bitcoin->importPrivateKey($privateKey);
        $address = $bitcoin->generateAddress();

        return response()->json(['address' => $address]);
        //  Create an XPub class instance from an xpub/tpub/ypub/upub/zpub/vpub string.
        $xpub = XPub::fromString( 'xpub6CU38b3dFGkZMFqNk9Zcvf3DWHCzQmk3n3hA8pTPMNwi6f6KzxjxvFfvatpXUJoYEqcWQhswChYS1nfxCeUVe52HjnL1jPtynHEMASDzr8c' ); // => BIP44 Original


# Derive a child extended public key from it.
        $xpub_i = $xpub->derive( 0 );
# You can also pass an array to derive a path.
//$xpub_i_k = $xpub->derive( [$i, $k]);

# An XPub can be serialized back into a string.
# Pass $asHex = true to serialize into a HEX string, base58 is the default.
//$xpub_string = $xpub_i->toString( $asHex = false );

# An XPub can be converted into an address.
# Pass $coin = 'eth' to convert into an ETH address.
#
# By default, xpubs are converted into standard addresses,
# ypubs are converted into nested segwit addresses,
# and zpubs are converted into native segwit addresses.
        $address = $xpub_i->toAddress( $coin = 'eth' );
        dd($address);

        $xpub = 'xpub6CU38b3dFGkZMFqNk9Zcvf3DWHCzQmk3n3hA8pTPMNwi6f6KzxjxvFfvatpXUJoYEqcWQhswChYS1nfxCeUVe52HjnL1jPtynHEMASDzr8c';
        $path = '0/0'; // 1st receiving address
// $path = '0/2'; // 3rd receiving address
// $path = '1/0'; // 1st change address
// $path = '1/1'; // 2nd change address
        $hd = new HD();
        $hd->set_xpub($xpub);
        $address = $hd->address_from_xpub($path);
        dd ($address);


        $bitcoinECDSA = new BitcoinECDSA();
        $bitcoinECDSA->setPrivateKey("L1cNafxv6YeP5MpWxBxcynYd7CMGDT7UwM5ZKX4Z7MpeJQCFG15A");
        dd($bitcoinECDSA->getAddress());

// Set your API key
        $api_key = "23fe60e0e783488985d6db1808cd1e57";

// Set the base URL for the BlockCypher API
        $base_url = "https://api.blockcypher.com/v1/btc/main";

// Set the endpoint for generating a BTC deposit address
        $endpoint = "/addresses";

// Set the request headers
        $headers = array(
            "Content-Type: application/json",
            "Authorization: Bearer " . $api_key
        );

// Make a POST request to the BlockCypher API
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $base_url . $endpoint);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);

// Decode the JSON response
        $json = json_decode($response, true);

// Print the BTC deposit address
        dd ($json["address"]);


        $coins = Coins::where('status','1')->get();

        return view('user.crypto.trade_crypto',compact('coins'));
        //   try{
        $data = [
            'price_amount' => request()->price_amount ?? 100,
            'price_currency' => request()->price_currency ?? 'usd',
            'order_id' => request()->order_id ?? uniqid(), // you can generate your order id as you wish
            'pay_currency' => request()->pay_currency ?? 'btc',
            'payout_currency' => request()->payout_currency ?? 'btc',//'USDTTRC20',
        ];

        $paymentDetails = Nowpayments::createPayment($data);
//$paymentDetails= NowPayments::getCurrencies();
        dd($paymentDetails);
        // Now you have the payment details,
        // you can then redirect or do whatever you want

        // return Redirect::back()->with(['msg'=>"Payment created successfully", 'type'=>'success'], 'data'=>$paymentDetails);
        /*  }catch(\Exception $e) {
              return Redirect::back()->withMessage(['error'=>"There's an error in the data", 'type'=>'error']);
          }*/
        //  $nowPay = new NowPaymentsAPI(env('nowPay'));

    }

    public function getEstimated($id){
        $data =
            "amount=" . 1 . "&" .
            "currency_from=usd" . "&" .
            "currency_to=" . $id;
        $rate = Nowpayments::getEstimatePrice($data);
//$paymentDetails= NowPayments::getCurrencies();
        return  response()->json(['rate'=>$rate['estimated_amount']],200);
        //dd($rate);
    }
    public function getRate($id){
        $data =
            "amount=" . 1 . "&" .
            "currency_from=usd" . "&" .
            "currency_to=" . $id;
        $rate = Nowpayments::getEstimatePrice($data);
//$paymentDetails= NowPayments::getCurrencies();
        return  response()->json(['rate'=>$rate['estimated_amount']],200);
        //dd($rate);
    }

    public function initTrade(Request $request){
        $request->validate([
            'amount'=>'required',
            'account'=>'required'
        ]);

        $coin = VirtualAccounts::where('user_id',Auth()->user()->id)->where('virtual_account_id',$request->account)->firstOrFail();//Coins::where('code',$request->coin)->first();
        //check accout balance
        $finalAmount = numFormat($request->amount);
        $coinDetails =Coins::where('code',$coin->blockchain_code)->first();
//chekc mini trade
        /*if ($coinDetails->min_payment > $finalAmount) {
            return response()->json([
                'status' => 'error',
                'message' => 'Minimum Payment Allow is '.$coinDetails->min_payment
            ], 400);
        }*/
        if ($coin->availableBalanceUSD < $finalAmount) {
            return response()->json([
                'status' => 'error',
                'message' => 'Insufficient balance please deposit to your wallet and try again!!'
            ], 400);
        }
        $transChanges=0;
        //do virtual account transfer to trading virtual account
        $tradingAcc = VirtualAccounts::where('blockchain_code',$coin->blockchain_code)->where('virtual_account_type','Trading')->firstOrFail();
        $payoutRate = $coinDetails->selling_rate;
        $payoutAmount = $payoutRate * $finalAmount;
        $refererBonusPayoutRate =  $coinDetails->refer_bonus;
        $refererBonusPayoutAmount =  $refererBonusPayoutRate*$finalAmount;
        $currentCoinRate = getExchangeRate($coin->blockchain_code, 'USD');
        $paymentId= uniqid().time() . Auth()->user()->id;
        $orderId = 'R2T-'.$paymentId;
        $description=  '$' . $request->amount . ' ' . $request->coin . ' Crypto Trading';
      if($coin->blockchain_code=='USDT_TRON'){
          $assetAmount=$finalAmount;
      }elseif($coin->blockchain_code=='BTC') {
          $deductedBTc = env('DEDUCTED_BTC');
          $assetAmount = convertUsdToAsset($currentCoinRate-$deductedBTc, $finalAmount);
      }else{
          $assetAmount = convertUsdToAsset($currentCoinRate, $finalAmount);
      }
//$payoutAmount = $finalAmount * $coi
//dd($assetAmount);
//save the transaction first
        $newTrans = new CryptoTransaction();

        //  $newTrans->price_amount = $assetAmount;
        // $newTrans->price_in_usd = $finalAmount;

        $newTrans->deducted_asset_amount = $assetAmount;
        $newTrans->deducted_asset_amount_usd = $finalAmount;

        //  $newTrans->price_currency = 'USD';
        $newTrans->send_from = $coin->attarched_address;
        $newTrans->send_to = $tradingAcc->attarched_address;
        $newTrans->transfer_type = 'Internal';
        $newTrans->order_id = $orderId;
        $newTrans->payment_id = $paymentId;
        $newTrans->blockchain_code = $coin->blockchain_code;
        $newTrans->deducted_account = $coin->virtual_account_id;
        $newTrans->coin = $coin->blockchain_code;
        $newTrans->pay_currency = $coin->blockchain_code;
        $newTrans->user_id = Auth()->user()->id;
        $newTrans->payout_currency = 'NGN'; //env('PAYOUT','btc');
        $newTrans->payout_amount = $payoutAmount;
        $newTrans->payout_rate = $payoutRate;
        $newTrans->type = 'Sell';
        $newTrans->virtual_wallet_id = $coin->id;
        // $newTrans->pay_address = $payaddress;
        $newTrans->rate = $payoutRate;
        // $newTrans->pay_amount = $pay_amount;
        $newTrans->converted_amount =0;
        $newTrans->order_description = '$' . $request->amount . ' ' . $request->coin . ' Crypto Trading';
        $newTrans->payment_creation_status = 'Initialized';
        $newTrans->referred_by = Auth()->user()->refer_by;
        $newTrans->refer_bonus_rate = $refererBonusPayoutRate;
        $newTrans->refer_bonus_payout_amount = $refererBonusPayoutAmount;
        if ($newTrans->save()) {
            // $payStatus = NowPayments::getPaymentStatus('4703776273');
            //\  dd($payStatus);
// Set your API Keys 👇 here
            // $sdk = new \Tatum\Sdk('',env('TTAPIKEYTEST'));
            $sdk = initiateTatum();
// 🐛 Enable debugging on the MainNet
            // $sdk->testnet()->config()->setDebug(true);

            $arg_create_transaction = (new \Tatum\Model\CreateTransaction())

                // Internal sender account ID within Tatum platform
                ->setSenderAccountId($coin->virtual_account_id)

                // Internal recipient account ID within Tatum platform
                ->setRecipientAccountId($tradingAcc->virtual_account_id)

                // Amount to be sent.
                ->setAmount($assetAmount)

                // (optional) Anonymous transaction does not show sender account to recipient, default is false
                ->setAnonymous(false)

                // (optional) Enable compliant checks. Transaction will not be processed, if compliant check fails.
                ->setCompliant(false)

                // (optional) For bookkeeping to distinct transaction purpose.
                ->setTransactionCode($orderId)

                // (optional) Payment ID, External identifier of the payment, which can be used to pair transactions within Tat...
                ->setPaymentId($paymentId)

                // (optional) Note visible to both, sender and recipient
                ->setRecipientNote($description)

                // (optional) Exchange rate of the base pair. Only applicable for Tatum's Virtual currencies Ledger transaction...
                //  ->setBaseRate(1)

                // (optional) Note visible to sender
                ->setSenderNote($description);

            try {

                /**
                 * POST /v3/ledger/transaction
                 *
                 * @var \Tatum\Model\TransactionResult $response
                 */
                $response = $sdk
                    ->api()
                    ->transaction()
                    ->sendTransaction($arg_create_transaction);
                $transaction_reference = $response->getReference();
//dd($transaction_reference);
                if(!empty($transaction_reference)){
                    // dd($transaction_reference);
                    $newTrans->transaction_reference = $transaction_reference;
                    $newTrans->payment_creation_status='Payment Received';
                    $newTrans->amount_received = $assetAmount;//confirmBalance($address)['amount'];//$trans->vout_amount_usd * $trans->rate;
                    $newTrans->price_in_usd = $finalAmount;
                    $newTrans->coin_rate = $currentCoinRate;
                    $newTrans->converted_amount = $newTrans->payout_amount;
                    //save amount to wallet
                    $newTrans->payment_status = 'Payment Received';

                    // $trans->recieved_converted_amount = $trans->price_in_usd * $trans->amount_received;

                    //  $trans->converted_amount = $trans->rate * $trans->recieved_converted_amount;

                   // if ($newTrans->fund_wallet_status != 'Pending' || $newTrans->fund_wallet_status != 'Balance') {
                    $newTrans->fund_wallet_status = 'Balance';
                    $newTrans->fund_wallet_status_at= now()->toDateTimeString();
                    $newTrans->approved_wallet_funding_method = 'Automatic';
                    $newTrans->approved_wallet_funding_at = now()->toDateTimeString();
                    $newTrans->approved_wallet_funding_by = Auth()->user()->id;
                    if($newTrans->save()){
                        Auth()->user()->saveToClientWallet($newTrans->converted_amount,$newTrans->user_id,'Balance', 'Crypto','');
                    };
                    if(!empty($newTrans->referred_by)){
                        Auth()->user()->saveToClientWallet($newTrans->refer_bonus,$newTrans->referred_by,'Refer', 'Crypto', $newTrans->user_id);
                    }


                    $newTrans->coin_confirm_status = 'Confirmed';


                    // }
                    if ($newTrans->save()) {
                        updateAccountBalance($coin);
                        $this->saveTradingTransaction($newTrans,$assetAmount,$coin,$tradingAcc);
                        return response()->json(['status' => 'success',  'confirmed' => true, 'vout' => $assetAmount. ' ($'.$finalAmount.')', 'orderId'=>$newTrans->order_id], 200);
                    }
                    //  $newTrans->save();

                    //  return response()->json(['data' => $newTrans->order_id, 'message' => 'Payment Initiated Successfuly'], 200);

                }

            } catch (\Tatum\Sdk\ApiException $apiExc) {
                /*
                echo sprintf(
                    "API Exception when calling api()->transaction()->sendTransaction(): %s\n",
                    var_export($apiExc->getResponseObject(), true)
                );*/
                $errorCode = $apiExc->getResponseObject()['errorCode'];
                if($errorCode=='balance.insufficient') {
                    return response()->json([
                        'status' => 'error',
                        'message' => 'Insufficient balance please deposit to your wallet and try again!!'
                    ], 400);
                }else{
                    return response()->json([
                        'status' => 'error',
                        'message' =>  var_export($apiExc->getResponseObject(), true)
                    ], 400);
                }

            } catch (\Exception $exc) {
                echo sprintf(
                    "Exception when calling api()->transaction()->sendTransaction(): %s\n",
                    $exc->getMessage()
                );
            }


        }



    }



    public function initTradeBk(Request $request){
        $request->validate([
            'coin'=>'required',
            'amount'=>'required'
        ]);

        $coin = Coins::where('code',$request->coin)->first();
        $transChanges=0;
        if($request->coin=='usdt'){
            $rate=1;
            $pay_amount = $request->amount;

            $address = newUSDTDepositAddress();
            $payaddress = $address;

        }else{
            $rate= getEstimated($request->amount, $request->coin);
            if($rate['type']=='error'){
                return response()->json(['message' => $rate['message']], 406);
            }
            // return response()->json(['message' => $rate], 406);

            $pay_amount= $rate['price'];
            $transChanges = $pay_amount * 0.005;

            //$key = 'master-E12zWEcmRhXOiQw0n7Uk';
            // $secret = '4DehYVbN9wQWrLYU2w6pz6PQ216K';
            $gemini = new Gemini(env('GEMINI_API'), env('GEMINI_SK'));
            // $gemini = new Gemini();
            $address = $gemini->newDepositAddress($request->coin);
            if(isset($address['address'])) {
                $payaddress = $address['address'];
            } else{
                return response()->json(['message' => 'Error Initiating Payment, Please try again'], 406);

            }
        }



        $newTrans = new CryptoTransaction();
        $orderId = 'R2T-' . uniqid().time() . Auth()->user()->id;
        $newTrans->price_amount = $request->amount;
        $newTrans->price_in_usd = $request->amount;
        $newTrans->price_currency = 'usd';
        $newTrans->order_id = $orderId;
        $newTrans->coin = $request->coin;
        $newTrans->pay_currency = $request->coin;
        $newTrans->user_id = Auth()->user()->id;
        $newTrans->payout_currency = 'usdttrc20'; //env('PAYOUT','btc');
        $newTrans->pay_address = $payaddress;
        $newTrans->rate = $coin->rate;
        $newTrans->pay_amount = $pay_amount + $transChanges;
        $newTrans->converted_amount =0;
        $newTrans->order_description = '$' . $request->amount . ' ' . $request->coin . ' Crypto Trading';
        $newTrans->payment_creation_status = 'Initialized';
        $newTrans->referred_by = Auth()->user()->refer_by;
        $newTrans->refer_bonus_rate = $coin->refer_bonus;
        if ($newTrans->save()) {
            // $payStatus = NowPayments::getPaymentStatus('4703776273');
            //\  dd($payStatus);

            return response()->json(['data' => $newTrans->order_id, 'message' => 'Payment Initiated Successfuly'], 200);

        }

    }

    public function trackPayment($id){
        $getPayment = CryptoTransaction::where('order_id',$id)->first();
        $getPayment->payment_status = 'Expecting Payment';

        $getPayment->save();

        return view('user.crypto.track_payment', compact('getPayment'));

    }


    public function ipnCallback(Request $request){
        $checkValid = Nowpayments::verifyIPN();
        Log::info('receive form now payment');
        Log::info($request);
        if($checkValid){ //receive from good source
            $paymentId = $request['payment_id'];
            $getTransaction = CryptoTransaction::where('payment_id',$paymentId)->first();
            $getTransaction->payment_status=$request['payment_status'];
            $getTransaction->outcome_amount=$request['payment_status'];
            Log::info("now payment request start here");
            Log::alert($request);
        }

    }

    function getBalance($address) {
        return file_get_contents('https://blockchain.info/q/addressbalance/'. $address);
    }
    function get_address_transactions($address) {
        $url = "https://mempool.space/api/address/{$address}/txs";
        $response = file_get_contents($url);
        if ($response !== false) {
            return json_decode($response, true);
        } else {
            return null;
        }
    }

    function filter_transactions_by_amount($transactions, $amount) {
        $filtered_transactions = [];
        foreach ($transactions as $tx) {
            //if(isset($tx['value'])) {
            if ($tx['value'] >=0) {
                $filtered_transactions[] = $tx;
            }
            //}
        }
        return $filtered_transactions;
    }



    public function testConfirm(){
//btctousd


// your api credentials
        $key = 'cmBq5tyrK68Dj+2VbZMM2qY1k0dgFw8nuiEzIayWCMC/pj+U3x+mWmlg';
        $secret = 'ZOexz6LpYp6q5WNf3KVk8wJ1ffb7n+EAGkNI89/5/iFuvGfyO6tsen7HgncGK8A9yUjvjKYypLI3fUqPlvw/Yw==';

        // API endpoint
        $endpoint = 'https://api.kraken.com/0/private/DepositAddresses';

// set which platform to use (beta or standard)
        $beta = false;
        $url = $beta ? 'https://api.beta.kraken.com' : 'https://api.kraken.com';
        $sslverify = $beta ? false : true;
        $version = 0;

        $kraken = new KrakenAPI($key, $secret, $url, $version, $sslverify);

// Query a public list of active assets and their properties:
        //  $res = $kraken->QueryPublic('Assets');
        $res= $kraken->getDepositAddresses('XBT', 'Bitcoin');
        dd($res);
        die();
        $apiKey = '65f76a0208d04c0001d720de';
        $apiSecret = 'cd5640c3-bdc0-4f13-97be-d1b088aade63';
        $apiPassphrase = 'qKh5gedVKxnfAX9i2d94EBh7grsfcMq1';
        $timestamp =  round(microtime(true) * 1000);

        $endpoint = '/api/v1/deposit-addresses';
        $httpMethod = 'POST';
        $nonce = uniqid();
        $requestBody = json_encode([
            'currency' => 'btc',
        ]);

        $signString = $timestamp . $httpMethod . $endpoint . $requestBody . $nonce;
        $signature = base64_encode(hash_hmac('sha256', $apiPassphrase, $apiSecret, true));

        $headers = [
            'Content-Type' => 'application/json',
            'KC-API-KEY' => $apiKey,
            'KC-API-SIGN' => $signature,
            'KC-API-TIMESTAMP' => $timestamp,
            'KC-API-PASSPHRASE' => $apiPassphrase,
            'KC-API-NONCE' => $nonce,
        ];

        $client = new \GuzzleHttp\Client([
            'base_uri' => 'https://api.kucoin.com',
        ]);

        try {
            $response = $client->post($endpoint, [
                'headers' => $headers,
                'json' => [
                    'currency' => 'YOUR_CURRENCY',
                ],
            ]);

            $body = $response->getBody();
            $data = json_decode($body);

            // Access the generated deposit address
            $depositAddress = $data->data->address;

            // Use the deposit address as needed
            echo 'New deposit address: ' . $depositAddress;
        } catch (\GuzzleHttp\Exception\RequestException $e) {
            // Handle request error
            echo 'Error: ' . $e->getMessage();
        }
        die();



        $apiEndpoint = 'https://pro-api.coinmarketcap.com/v1/tools/price-conversion';
        $apiKey = 'f2e9c0b7-7edd-4889-b97c-83c2e19b7b9e'; // Replace with your actual API key

        $parameters = [
            'amount' => '1',
            'symbol' => 'BTC',
            'convert' => 'USD'
        ];

        $url = $apiEndpoint . '?' . http_build_query($parameters);

        $curl = curl_init($url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_HTTPHEADER, [
            'X-CMC_PRO_API_KEY: ' . $apiKey
        ]);

        $response = curl_exec($curl);

        if ($response === false) {
            echo 'Error accessing CoinMarketCap API: ' . curl_error($curl);
            exit();
        }

        $data = json_decode($response, true);
//dd($data);
        if (isset($data['data']['quote']['USD']['price'])) {
            $usdPrice = $data['data']['quote']['USD']['price'];
            // $convertedAmount = $parameters['amount'] * $usdPrice;

            echo "0.00038 BTC is approximately $usdPrice USD\n";
        } else {
            echo 'Failed to convert BTC to USD using CoinMarketCap API.';
        }

        curl_close($curl);

        $apiEndpoint = 'https://api.gemini.com/v2/ticker/btcusdt';

        $curl = curl_init($apiEndpoint);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

        $response = curl_exec($curl);

        if ($response === false) {
            echo 'Error accessing Gemini API: ' . curl_error($curl);
            exit();
        }

        $data = json_decode($response, true);
        dd($data);
        if (isset($data['last'])) {
            $btcPrice = $data['last'];

            echo "BTC Price: $btcPrice USD\n";
        } else {
            echo 'Failed to retrieve BTC price from Gemini API.';
        }

        curl_close($curl);


        //mempool
// Address to query
        $address = "1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1";


// Build the API endpoint URL
        $url = 'https://mempool.space/api/address/' . $address . '/txs/chain';

// Make the API request
        $response = file_get_contents($url);

        if ($response === false) {
            echo 'Error accessing mempool.space API';
            exit();
        }

        $data = json_decode($response, true);

// Check if there are any transactions for the address
        if (empty($data)) {
            echo 'No transactions found for the address.';
            exit();
        }

// Get the last received transaction
        $lastTransaction = $data[0]; // Assuming the transactions are sorted in descending order (most recent first)

        $totalReceivedAmount = 0;
        $totalConfirmations = 0;
        $receiveDate =  null;
        $transId = null;


        foreach ($data as $transaction) {
            if (isset($transaction['status']['confirmed'])) {
                $totalConfirmations += $transaction['status']['confirmed'];
                $receiveDate = $transaction['status']['block_time'];
            }
            foreach ($transaction['vout'] as $output) {
                if ($output['scriptpubkey_address'] === $address) {
                    $transId =$transaction['txid'];
                    $totalReceivedAmount += $output['value'];
                    echo $output['scriptpubkey_address'];
                }
            }
        }

        $totalReceivedAmount = $totalReceivedAmount / 100000000; // Convert satoshis to BTC

        echo "Total Received Amount: " . $totalReceivedAmount . " BTC\n";
        echo "Total Confirmations: " . $totalConfirmations . " confirmations\n";
        echo "Recived Id: " .$transId;

        dd($data);

        $address = '1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1'; // Replace with the address you want to query

// Build the API endpoint URL
        $url = 'https://mempool.space/api/address/' . $address . '/txs';

// Make the API request
        $response = file_get_contents($url);

        if ($response === false) {
            echo 'Error accessing mempool.space API';
            exit();
        }

        $data = json_decode($response, true);
// Check if there are any transactions for the address
        if (empty($data)) {
            echo 'No transactions found for the address.';
            exit();
        }

// Get the last received transaction
        $lastTransaction = $data[0]; // Assuming the transactions are sorted in descending order (most recent first)

        $transactionId = $lastTransaction['txid'];
        $confirmations = $lastTransaction['status']['block_height'];
        $receivedAmount = $lastTransaction['vout'][0]['value'];
        $senderAddress = $lastTransaction['vin'][0]['prevout']['scriptpubkey_address'];
        $networkFees = $lastTransaction['fee'];
        // $timestamp = $lastTransaction['time'];
        // $date = date('Y-m-d H:i:s', $timestamp);

        echo "Last Transaction ID: " . $transactionId . "\n";
        echo "Confirmation Status: " . $confirmations . " confirmations\n";
        echo "Received Amount: " . $receivedAmount . " BTC\n";
        echo "Sender Address: " . $senderAddress . "\n";
        echo "Network Fees: " . $networkFees . " satoshis\n";
        //  echo "Date: " . $date . "\n";
        dd($data);


        $url = "https://blockchain.info/rawaddr/" . '1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1';
        $addr = '1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1';
        $response = file_get_contents($url);

        if ($response === false) {
            echo 'Error accessing API';
            exit();
        }

        $data = json_decode($response, true);

        $totalReceived = $data['total_received'];
        $balance = $totalReceived / 100000000; // Convert from satoshis to BTC

        echo "Total Received: " . $totalReceived . " satoshis\n";
        echo "Total Balance: " . $balance . " BTC\n";

        $lastTx = $data['txs'][0]; // Retrieve the first transaction (most recent)
        $lastReceivedDate = $lastTx['time'];
        $lastReceivedAddress = $lastTx['out'][0]['addr'];
        $transactionId = $lastTx['hash'];

        $inputValue = 0;
        $outputValue = 0;
        $senderAddress = '';

        foreach ($lastTx['inputs'] as $input) {
            if (isset($input['prev_out']['addr']) && $input['prev_out']['addr'] == $addr) {
                $inputValue += $input['prev_out']['value'];
                $senderAddress = $input['prev_out']['addr'];
            }
        }

        foreach ($lastTx['out'] as $output) {
            if ($output['addr'] == $addr) {
                $outputValue += $output['value'];
            }
        }

        $networkCharges = $inputValue - $outputValue;
        $sentAmount = $outputValue - $networkCharges;

        echo "Last Received Date: " . date('Y-m-d H:i:s', $lastReceivedDate) . "\n";
        echo "Last Received Address: " . $lastReceivedAddress . "\n";
        echo "Transaction ID: " . $transactionId . "\n";
        echo "Network Charges: " . $networkCharges . " satoshis\n";
        echo "Sent Amount: " . $sentAmount . " satoshis\n";
        echo "Sender Address: " . $senderAddress . "\n";

        if (isset($lastTx['confirmations'])) {
            $confirmations = $lastTx['confirmations'];
            if ($confirmations > 0) {
                echo "Transaction is confirmed. Confirmations: " . $confirmations . "\n";
            } else {
                echo "Transaction is unconfirmed. Confirmations: " . $confirmations . "\n";
            }
        } else {
            echo "Confirmations field not present in the transaction data.\n";
        }

        dd($data);



        $r = file_get_contents('https://blockchain.info/q/addressbalance/1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1');
        $addr='1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1';
        if ($r === false) {
            echo 'Error accessing API';
            exit();
        }
        dd($r);
        $b = (int)$r;

        echo $addr . '\t' . $r . ' sat\t' . ($b / 100000) . ' mBTC\t' . ($b / 100000000) . ' BTC';
        confirmBalance('1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1');
        // $address = "1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp";
        // $transactions = $this->get_address_transactions($address);
//dd($transactions);
//die();
        /* if ($transactions !== null) {
             // Assuming amount is in Satoshis (1 BTC = 100,000,000 Satoshis)
             $amount_to_check = 100000000; // For example, 1 BTC
             $filtered_transactions = $this->filter_transactions_by_amount($transactions, $amount_to_check);
            // dd($filtered_transactions);
             if (!empty($filtered_transactions)) {
                 echo "Transactions found with the specified amount:<br>";
                 foreach ($filtered_transactions as $tx) {
                     print_r($tx);
                     echo "<br>";
                 }
             } else {
                 echo "No transactions found with the specified amount.";
             }
         } else {
             echo "Error retrieving transaction information.";
         }
         die();
        */
//blokocnomy

        //$balance = $this->getBalance('1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp');
//dd(satToBtc($balance));
        //  echo 'Address Balance: ' . getBalance('1EzwoHtiXB4iFwedPr49iywjZn2nnekhoj');

        //   echo json_encode($response);
        /*  $address = "1dice8EMZmqKvrGE4Qc9bUFf9PX3xaYDp"; // Replace with your actual Bitcoin address
          $apiKey = "hihv7pldoxmdsrTN84JESyrnCPe7k8SALKRqEc4o2Ho"; // Replace with your Blockonomics API key

          $addresses ="1LjFSQYBCMipDXGh7doSTFWW3Zsr6fx31k"; // Replace with your actual Bitcoin addresses (whitespace separated)
         // $apiKey = "YOUR_API_KEY_HERE"; // Replace with your Blockonomics API key

      // Initialize a cURL handle
          $ch = curl_init("https://www.blockonomics.co/api/balance");

      // Set cURL options
          curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Capture response instead of printing it
          curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Skip SSL certificate verification (not recommended for production)
          curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Skip SSL hostname verification (not recommended for production)

      // Set request method to POST
          curl_setopt($ch, CURLOPT_POST, true);

      // Prepare the request body
          $requestBody = json_encode(['addr' =>  $addresses]); // Implode to create the whitespace-separated list

      // Set the request body with proper content type
          curl_setopt($ch, CURLOPT_POSTFIELDS, $requestBody);
          curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));

      // Set the Authorization header
          $headers = array('Authorization: Bearer ' . $apiKey);
          curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

      // Execute the cURL request
          $response = curl_exec($ch);
      //dd($response);
      // Check for errors
          if (curl_errno($ch)) {
              echo 'Error: ' . curl_error($ch);
              exit;
          }

      // Close the cURL handle
          curl_close($ch);

      // Decode the JSON response
          $data = json_decode($response, true);

      // Process the response data (refer to Blockonomics API documentation)
          if (isset($data['balances'])) {
              foreach ($data['balances'] as $address => $balance) {
                  echo "Address: " . $address . ", Balance: " . $balance . " Satoshi<br>";
              }
          } else {
              echo "Failed to retrieve balances.";
          }
      */
        $url = 'https://mempool.space/api/address/1DyDvLSenrGC2ZfiLWknBMQA5xMare1ST1/txs/chain';

// Initialize cURL
        $ch = curl_init($url);

// Set cURL options
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Capture response instead of printing it
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Skip SSL certificate verification (not recommended for production)
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Skip SSL hostname verification (not recommended for production)

// Execute the cURL request
        $response = curl_exec($ch);
//dd($response);
// Check for errors
        if (curl_errno($ch)) {
            echo 'Error: ' . curl_error($ch);
            exit;
        }

// Close the cURL resource
        curl_close($ch);

// Decode the JSON response
        $data = json_decode($response, true);


        $total_in = 0;
        $total_out = 0;
        dd($data[0]);
        $transaction= $data[0];
// Calculate total amount received (in)
        foreach ($transaction['vout'] as $output) {
            $total_in += $output['value'];
        }

// Calculate total amount sent (out)
        foreach ($transaction['vin'] as $input) {
            $total_out += $input['prevout']['value'];
        }

        echo "Total amount received (in): " . $total_in . " Satoshi\n";
        echo "Total amount sent (out): " . $total_out . " Satoshi\n";
// Process the data
        if (isset($data['txs'])) {
            foreach ($data['txs'] as $tx) {
                echo "Transaction ID: " . $tx['txid'] . "<br>";
                // Access other transaction details as needed (refer to API documentation)
            }
        } else {
            echo "No transactions found for the address.";
        }

    }
    public function confirmPayment(Request $request){


        $request->validate([
            'coin'=>'required',
            'address'=>'required',
            'order_id'=>'required'
        ]);
        $services = [
            'btc' => [['https://mempool.space/api/', 'address/{R}', 'address/{R}/txs', 'tx/{R}', 'blocks/tip/height', 'mempool'], ['https://blockstream.info/api/', 'address/{R}', 'address/{R}/txs', 'tx/{R}', 'blocks/tip/height', 'blockstream'], ['https://blockchain.info/', 'q/addressbalance/{R}', 'rawaddr/{R}?limit=30', 'rawtx/{R}', 'q/getblockcount', 'blockchain'], 'blockdaemon'],
            'eth' => [['https://api.etherscan.io/api?', 'module=account&action=balance&address={R}', 'module=account&action=txlist&address={R}&startblock=0&endblock=99999999&offset=99&sort=asc', 'module=account&action=txlist&address={R}&startblock=0&endblock=99999999&offset=99&sort=asc', false, 'etherscan'], ['https://api.ethplorer.io/', 'getAddressInfo/{R}', 'getAddressTransactions/{R}?limit=99&showZeroValues=false', 'getTxInfo/{R}', 'getLastBlock', 'ethplorer'], ['https://blockscout.com/eth/mainnet/api?', 'module=account&action=balance&address={R}', 'module=account&action=txlist&address={R}', 'module=transaction&action=gettxinfo&txhash={R}', false, 'blockscout'], 'blockdaemon'],
            'xrp' => [['https://data.ripple.com/v2/', 'accounts/{R}/balances', 'accounts/{R}/transactions', 'transactions/{R}', false, 'ripple'], 'blockdaemon'],
            'doge' => ['blockcypher', 'blockdaemon'],
            'algo' => [['https://algoindexer.algoexplorerapi.io/v2/', 'accounts/{R}', 'accounts/{R}/transactions?limit=99', 'transactions/{R}', 'accounts/{R}', 'algoexplorerapi'], 'blockdaemon'],
            'bnb' => [['https://api.bscscan.com/api?', 'module=account&action=balance&address={R}', 'module=account&action=txlist&address={R}&startblock=0&endblock=99999999&offset=99&sort=asc', 'module=account&action=txlist&address={R}&startblock=0&endblock=99999999&offset=99&sort=asc', false, 'bscscan']],
            'ltc' => ['tatum', 'blockdaemon', 'blockcypher'],
            'bch' => [['https://rest1.biggestfan.net/v2/address/', 'details/{R}', 'transactions/{R}', 'transactions/{R}', false, 'biggestfan'], 'blockdaemon'],
            'trx' => [['https://apilist.tronscan.org/api/', 'account?address={R}', 'transaction?sort=-timestamp&count=true&limit=99&start=0&address={R}', 'transaction-info?hash={R}', false, 'tronscan'], 'tatum']
        ];
        $coin = $request->coin;
        $address= $request->address;
        $orderId= $request->order_id;
        $trans = CryptoTransaction::where('order_id',$orderId)->where('user_id',Auth()->user()->id)->firstOrFail();
        if(!($trans->coin_confirm_status)) {
            if ($coin == 'btc') {//check transaction mempool.space

                $data = confirmBtcPayment($request->address);
                if ($data['amount'] > 0) {
                    //update transaction
                    $trans->txid = $data['txid'];
                    // $trans->vin_crypto = $data['vin'];
                    //  $trans->vout_crypto = $data['vout'];
                    //  $trans->txt_fees = $data['fee'];
                    // $trans->vin_amount_usd = btcToUsd($data['vin']);
                    //$trans->vout_amount_usd = btcToUsd($data['vout']);

                    //   if($data['confirmed']){//that mnean the money is successufl
                    // dd(confirmBalance($address)['amount']);
                    $trans->amount_received = $data['amount'];//confirmBalance($address)['amount'];//$trans->vout_amount_usd * $trans->rate;
                    $trans->price_in_usd = btctoUsd($trans->coint);
                    $trans->coin_rate = $trans->price_in_usd;
                    //save amount to wallet
                    $trans->payment_status = 'Payment Received';

                    $trans->recieved_converted_amount = $trans->price_in_usd * $trans->amount_received;

                    $trans->converted_amount = $trans->rate * $trans->recieved_converted_amount;

                    if ($trans->fund_wallet_status != 'Pending' || $trans->fund_wallet_status != 'Balance') {
                        $trans->fund_wallet_status='Pending';
                        //load wallet
                        Auth()->user()->saveToClientWallet($trans->converted_amount, $trans->user_id, 'Pending');
                        if (!empty($trans->referred_by)) {
                            $bonus = $trans->recieved_converted_amount * $trans->refer_bonus_rate;
                            $trans->refer_bonus= $bonus;
                            Auth()->user()->saveToClientWallet($bonus, $trans->referred_by, 'ReferPending');
                        }
                    }


                    $trans->coin_confirm_status = $data['confirmed'];


                    // }
                    if ($trans->save()) {
                        return response()->json(['status' => $trans->coin_confirm_status, 'confirmed' => true, 'vout' => $trans->amount_received. ' ($'.$trans->recieved_converted_amount.')', 'orderId'=>$trans->order_id], 200);
                    }

                } else {

                    // dd($data);
                    return response()->json(['confirmed' => false, 'message' => 'Payment not confirm, Bitcoin blocks only arrive at an average of 10 minutes'], 406);
                }

            } else if ($coin == 'eth') { //which etherrium etherscan.io

            } else if ($coin == 'usdt') {//explorer.bnbchain.org
                $trans->payment_status = 'Reviewing Payment';
                $trans->price_in_usd=1;
                $trans->coin_rate = $trans->price_in_usd;

                $trans->coin_confirm_status = '0';
                $trans->save();
                // dd(address)
                updateUsdtAddressUsed($trans->pay_address, $trans->created_at, $trans->user_id);

                return response()->json(['status' => $trans->coin_confirm_status, 'confirmed' => true, 'vout' => $trans->amount_received. ' ($'.$trans->recieved_converted_amount.')', 'orderId'=>$trans->order_id], 200);
            }
        }else{
            return response()->json(['status' => $trans->coin_confirm_status, 'confirmed' => true, 'vout' => $trans->amount_received. ' ($'.$trans->recieved_converted_amount.')', 'orderId'=>$trans->order_id], 200);
        }


    }

    public function viewTrade($id){
        $getPayment = CryptoTransaction::where('order_id',$id)->first();


        return view('user.crypto.view_crypto_trade', compact('getPayment'));

    }


    public function buyCrypto(){
        $coins = Coins::where('status', '1')->get();
        $assets = VirtualAccounts::where('user_id',Auth()->user()->id)->get();

        return view('user.crypto.buy',  compact('coins','assets'));
    }

    public function confirmPreview(Request $request){
        $request->validate([
            'amount'    => 'required|numeric|gt:0',
            //'address' => 'required',
            'payment_method'=>'required',
            'coin'=>'required'

        ]);
        $asset = VirtualAccounts::where('virtual_account_id',$request->coin)->firstorFail();

        // $coin =  Coins::where('code', $request->coin)->first();
        $coin = $asset->coin;
        if(empty($coin)){
            return response()->json([
                'status' => 'error',
                'message' => 'Coin not available'
            ], 400);
        }
        //check allow buying
        if($coin->min_selling>$request->amount){

                return response()->json([
                    'status' => 'error',
                    'message' => 'Minimum allow buying amount is '.toMOney($coin->min_selling)
                ], 400);

        }
        $buyCrypto = Session::get('buyCrypto');
        if(!empty($buyCrypto)
            &&
            ($buyCrypto->price_amount==$request->amount) && ($buyCrypto->pay_address==$request->address) && ($buyCrypto->coin==$request->coin) && ($buyCrypto->payment_method==$request->payment_method)){
//this is good do nothing
            // dd($buyCrypto);
        }else{
            $coinCode = $coin->code;
if($coin->code=='USDT_TRON'){
   $coinCode='USDT(TRC-20)';
    $coinRate=1;
}else{
    $coinRate=  btctoUsd($coinCode);
}

            $buyCrypto = new CryptoTransaction();
            $buyCrypto->price_amount = $request->amount;
            $buyCrypto->pay_currency = 'NGN';
            $buyCrypto->price_currency = 'NGN';
            $buyCrypto->virtual_wallet_id = $asset->id;
            $buyCrypto->coin = $coin->code;
            $buyCrypto->blockchain_code = $coin->code;
            $buyCrypto->rate = $coin->selling_rate;
            $buyCrypto->refer_bonus_rate = $coin->selling_refer_bonus;
            $buyCrypto->referred_by = Auth()->user()->refer_by;
            $buyCrypto->transaction_type = 1;
            $buyCrypto->transfer_type = "Internal";
            $buyCrypto->payment_status = 'Pending';
            $buyCrypto->coin_rate =$coinRate;
            $buyCrypto->payment_method = $request->payment_method;
            $buyCrypto->price_in_usd = numFormat(($request->amount / $coin->selling_rate), 2);
            $buyCrypto->amount_received = numFormat($buyCrypto->price_in_usd / $buyCrypto->coin_rate, 6);

            $buyCrypto->order_id = 'R2T-BY' . uniqid() . Auth()->user()->id;;

            $buyCrypto->user_id = Auth()->user()->id;
            $buyCrypto->payout_currency = $request->coin; //env('PAYOUT','btc');

            $buyCrypto->pay_amount = $request->amount;
            $buyCrypto->converted_amount = $buyCrypto->price_in_usd;

            $buyCrypto->order_description = 'Buying of ' . toMoney($request->amount) . ' ' . $coin->name;
            //$buyCrypto->save();
            Session::put('buyCrypto', $buyCrypto);
        }

        return view('user.crypto._inner_confirm', [
            'model'=>$buyCrypto

        ])->render();


    }
    public function confirmOrder(Request $request){
        $request->validate([
            'orderId'    => 'required',


        ]);

        $coin =  Coins::where('code', $request->coin)->first();
        if(empty($coin)){
            return response()->json([
                'status' => 'error',
                'message' => 'Coin not available'
            ], 400);
        }

        $buyCrypto = Session::get('buyCrypto');
        if(!empty($buyCrypto)){
            $model = $buyCrypto->save();
            if($model->payment_method=='Wallet'){

            }
        }



        return 'uscess';


    }
    public function confirmOrderByWallet(Request $request){

        $buyCrypto = Session::get('buyCrypto');
        if(empty($buyCrypto)){
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid Trade please try again'
            ], 400);
        }
        $request->validate([
            'password'=>'required',


        ]);

        if (!(Hash::check( $request->password, Auth()->user()->getAuthPassword()))) {
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid Password Please Retry'
            ], 400);
        }

        $wallet = Auth()->user()->getMyWallet();
        if(!$wallet){
            return response()->json([
                'status' => 'error',
                'message' => 'Wallet Not Found'
            ], 400);
            // return back()->with('error','Wallet not found');
        }

        //if($request->amount < $method->min_amount || $request->amount > $method->max_amount){
        /* if($request->amount < $wallet->amount > $method->max_amount){
             return back()->with('error','Please follow the limit');
         }
 */
//dd($buyCrypto);
        // $charge = chargeCalc($method,$request->amount);
        $finalAmount = numFormat($buyCrypto->pay_amount);

        // $transferAmount =  numFormat($request->amount);

        if ($wallet->balance < $finalAmount ) {
            return response()->json([
                'status' => 'error',
                'message' => 'Insufficient balance please fund you wallet and try again'
            ], 400);
        }
        $wallet->balance -=  $finalAmount;

        // $coin =  Coins::where('code', $request->coin)->first();
        $buyCrypto->payment_status='Confirmed';
        $buyCrypto->save();
        $wallet->save();

        TransactionHistory::create([
            'descriptions' =>$buyCrypto->order_description,
            'trade_id' => null,
            'request_id' => $buyCrypto->id,
            'tradedcard_details_id' => null,
            'transaction_ref' =>$buyCrypto->order_id,
            'user_id' => $buyCrypto->user_id,
            'amount' =>$buyCrypto->price_amount,
            'exchange_rate'=>$buyCrypto->rate,
            'transaction_amount_in_usd'=>0,
            'transaction_type' => 'Debit',
            'created_by' => $buyCrypto->user_id,
            'source' => 'Crypto',
            'status' => 'success',
            'status_at' => now(),
            'status_by' => $buyCrypto->user_id,
            'status_reason' => "Successful",
           // 'refer_bonus' => $buyCrypto->refer_bonus,
            'referer_user_id' => auth()->user()->refer_by,
            'rate' => null,
            'currency' => "NGN",
        ]);
        $this->transferCryptoBuy($buyCrypto);
        Session::remove('buyCrypto');


        return response()->json([
            'status' => 'success',
            'orderId' => $buyCrypto->order_id,
            'message' => 'Payment Successful',
        ], 200);

        // return 'uscess';


    }

    public function paymentConfirmed(Request $request){
        $model = CryptoTransaction::where('order_id',$request->id)->first();
        return view('user.crypto.payment_confirmed',compact('model'));
    }

    public function confirmOrderByCard(Request $request){

        $buyCrypto = Session::get('buyCrypto');
        if(empty($buyCrypto)){
            return response()->json([
                'status' => 'error',
                'message' => 'Invalid Trade please try again'
            ], 400);
        }
        /*  $request->validate([
              'orderId'=>'required',


          ]);*/



        //if($request->amount < $method->min_amount || $request->amount > $method->max_amount){
        /* if($request->amount < $wallet->amount > $method->max_amount){
             return back()->with('error','Please follow the limit');
         }
 */
        // $charge = chargeCalc($method,$request->amount);
        // $finalAmount = numFormat($buyCrypto->amount);
        // $transferAmount =  numFormat($request->amount);

        //This generates a payment reference
        $reference = Flutterwave::generateReference();

        // Enter the details of the payment
        $data = [
            'payment_options' => 'banktransfer',
            'amount' => $buyCrypto->pay_amount,
            'email' => Auth()->user()->email,
            'tx_ref' => $buyCrypto->order_id,
            'currency' => "NGN",
            'redirect_url' => route('user.crypto.card-callback'),
            'customer' => [
                'email' => Auth()->user()->email,
                "phone_number" => Auth()->user()->phone,
                "name" => Auth()->user()->name,
            ],

            "customizations" => [
                "title" => 'Payment for Purchasing of Coin',
                "description" => $buyCrypto->description
            ]
        ];

        $payment = Flutterwave::initializePayment($data);


        if ($payment['status'] !== 'success') {
            // notify something went wrong
           // dd($payment);
            return response()->json([
                'status' => 'error',
                'message' => 'Payment Gate Error Please Try again'
            ], 400);
        }

        // return redirect($payment['data']['link']);
        // $coin =  Coins::where('code', $request->coin)->first();
        $buyCrypto->payment_status='Initiated';
        $buyCrypto->save();
        //initiate Internal Transfer


        Session::remove('buyCrypto');


        return response()->json([
            'status' => 'success',
            'orderId' => $buyCrypto->order_id,
            'url' => $payment['data']['link'],
            'message' => 'Payment Successful',
        ], 200);

        // return 'uscess';


    }


    public function cardPaymentcallback()
    {

        $status = request()->status;
        $transactionID = request()->tx_ref;
        $buyCrypto = CryptoTransaction::where('order_id',$transactionID)->first();



        //if payment is successful
        if ($status ==  'success') {
            $transactionID = Flutterwave::getTransactionIDFromCallback();
            $data = Flutterwave::verifyTransaction($transactionID);

Log::debug("successCharge: ",$data);
          //  dd($data);

            if($data['status']=='successful') {
                $this->transferCryptoBuy($buyCrypto);
            }else{
                $buyCrypto->payment_status = 'Failed';
                $buyCrypto->save();
            }
        }
        elseif ($status ==  'cancelled'){
            //Put desired action/code after transaction has been cancelled here
            $buyCrypto->payment_status = 'Cancelled';
           $buyCrypto->save();

        }
        else{
            //Put desired action/code after transaction has failed here
            dd(request());
        }
        // Get the transaction from your DB using the transaction reference (txref)
        // Check if you have previously given value for the transaction. If you have, redirect to your successpage else, continue
        // Confirm that the currency on your db transaction is equal to the returned currency
        // Confirm that the db transaction amount is equal to the returned amount
        // Update the db transaction record (including parameters that didn't exist before the transaction is completed. for audit purpose)
        // Give value for the transaction
        // Update the transaction to note that you have given value for the transaction
        // You can also redirect to your success page from here

    }




    public function blockchainwallet()
    {
        $basic = GeneralSettings::first();
        if ($basic->blockallow == 0) {
            return back()->with('alert', 'Blockchain feature has been disabled'); }
        $auth = Auth::user();
        $data['page_title'] = "Blockchain Wallet";
        $data['id'] = $id;
        $data['coin'] = Coin::whereId($id)->first();
        $data['wallet'] = Coinwallet::whereCoin_id($id)->whereUser_id($auth->id)->get();
        return view('user.blockhain.index', $data);
    }


    public function createWallet(Request $request){
        $request->validate([
            'asset'=>'required',
        ]);
        $asset = $request->asset;
        $user_id = Auth()->user()->id;

        $cryptoWallet = BlockchainWallet::where('blockchain_code',$asset)->firstOrFail();
        //check if created
        $checkifExits = VirtualAccounts::where('user_id',$user_id)->where('wallet_id',$cryptoWallet->id)->exists();

        if($checkifExits){
            return  back()->with('error',"You already have this asset");
        }

        //dd($cryptoWallet);
//check if virtual account exist

        //dd(Auth()->user()->crypto_account_number);
        //if not crated before check if their is still pending address
        //create addresss using xpub

//echo $apiKey; die();
        // $tSdk->testnet()->config()->setDebug(true);
        $response = initiateTatum();
        $customer = new \Tatum\Model\CustomerRegistration(['external_id'=>Auth()->user()->crypto_customer_id,'accounting_currency'=>'USD']);
        try {
        if($asset=='USDT_TRON'){
//just create account
            $arg_create_account = (new \Tatum\Model\CreateAccount())

                // <p>The currency for the virtual account</p> <ul> <li><b>Native blockchain assets:</b> ALGO, BCH, ...
                ->setCurrency('USDT_TRON')

                // Extended public key to generate addresses from.
              //  ->setXpub($cryptoWallet->xpub)

                // (optional) \Tatum\Model\CustomerRegistration
                ->setCustomer($customer)

                // (optional) Enable compliant checks. If this is enabled, it is impossible to create account if compliant chec...
                ->setCompliant(false)

                // (optional) For bookkeeping to distinct account purpose.
                ->setAccountCode(Auth()->user()->crypto_account_code)

                // (optional) All transaction will be accounted in this currency for all accounts. Currency can be overridden p...
                ->setAccountingCurrency('USD')

                // (optional) Account number from external system.
                ->setAccountNumber(Auth()->user()->crypto_account_number);
//dd($arg_create_account);
            $addressGenerated = getUSDTAddress();
           // try {
                $responseData = $response->api()->account()
                    ->createAccount($arg_create_account);
               // dd($responseData->getId());
          /*  } catch (\Tatum\Sdk\ApiException $apiExc) {
                echo sprintf(
                    "API Exception when calling api()->account()->getAccounts(): %s\n",
                    var_export($apiExc->getResponseObject(), true)
                );
            } catch (\Exception $exc) {
                echo sprintf(
                    "Exception when calling api()->account()->getAccounts(): %s\n",
                    $exc->getMessage()
                );
            }*/
           // $addressGenerated = generateAddressByAccountId($responseData->id);
            //check if created already
           // $accountCheck = checkAccount('USDT_TRON',Auth()->user()->crypto_account_number);
//dd($responseData->getId());

            $assignedStatus = assignAddressToVA($responseData->getId(),$addressGenerated->address);
            if($assignedStatus) {
                $acct = new VirtualAccounts();
                $acct->virtual_account_id = $responseData->getId();
                $acct->customer_id = $responseData->getCustomerId();
                $acct->currency = $responseData->getCurrency();
                $acct->account_number = $responseData->getAccountNumber();
                $acct->account_code = $responseData->getAccountCode();
                $acct->accounting_currency = $responseData->getAccountingCurrency();
               // $acct->xpub = $responseData->xpub;
                $acct->wallet_id = $cryptoWallet->id;
                $acct->virtual_account_type = 'SlaveGas';
                $acct->user_id = $user_id;
                $acct->blockchain_code = $cryptoWallet->blockchain_code;
                $acct->blockchain_name = $cryptoWallet->blockchain_name;
                $acct->attarched_address = $addressGenerated->address;
                $acct->is_attarched = 1;
                $acct->derivation_key = $addressGenerated->derivative_index;
                $acct->master_address = $addressGenerated->master_address;
                $acct->master_derivative = $addressGenerated->master_derivative;
                $acct->token_address = $addressGenerated->token_address;
                if ($acct->save()) {
                    //attarched address to an account
$addressGenerated->assigned_to=$user_id;
$addressGenerated->assigned_wallet_id=$acct->id;
$addressGenerated->save();
                    return back()->with('success', "Asset Created Successfully! Make you first deposit");
                };
            }

        }else {
//just generate it using xpub
            $arg_create_account = (new \Tatum\Model\CreateAccountXpub())
                // <p>The currency for the virtual account</p> <ul> <li><b>Native blockchain assets:</b> ALGO, BCH, ...
                ->setCurrency($cryptoWallet->blockchain_code)

                // Extended public key to generate addresses from.
                ->setXpub($cryptoWallet->xpub)

                // (optional) \Tatum\Model\CustomerRegistration
                ->setCustomer($customer)

                // (optional) Enable compliant checks. If this is enabled, it is impossible to create account if compliant chec...
                ->setCompliant(false)

                // (optional) For bookkeeping to distinct account purpose.
                ->setAccountCode(Auth()->user()->crypto_account_code)

                // (optional) All transaction will be accounted in this currency for all accounts. Currency can be overridden p...
                ->setAccountingCurrency('USD')

                // (optional) Account number from external system.
                ->setAccountNumber(Auth()->user()->crypto_account_number);
            $responseData= $response->api()->account()
                ->createAccount($arg_create_account);
            $addressGenerated = generateAddressByAccountId($responseData->getId());


            $acct = new VirtualAccounts();
            $acct->virtual_account_id=$responseData->getId();
            $acct->customer_id =$responseData->getCustomerId();
            $acct->currency = $responseData->getCurrency();
            $acct->account_number = $responseData->getAccountNumber();
            $acct->account_code = $responseData->getAccountCode();
            $acct->accounting_currency = $responseData->getAccountingCurrency();
            $acct->xpub = $responseData->getXpub();
            $acct->wallet_id = $cryptoWallet->id;
            $acct->virtual_account_type ='Normal';
            $acct->user_id = $user_id;
            $acct->blockchain_code=$cryptoWallet->blockchain_code;
            $acct->blockchain_name=$cryptoWallet->blockchain_name;
            $acct->attarched_address= $addressGenerated->getGeneratedAddress();
            $acct->derivation_key=$addressGenerated->getDerivationKey();
            if($acct->save()){
                return  back()->with('success',"Asset Created Successfully! Make you first deposit");
            };

        }





                //  $responseData = json_decode($response);
                // dd($responseData);
                //save virtual account
                // $argb = (new \Tatum\Model\GenerateAccountAddress())


                //once is save generate address





            } catch (\Tatum\Sdk\ApiException $apiExc) {
                echo sprintf(
                    "API Exception when calling api()->account()->createAccount(): %s\n",
                    var_export($apiExc->getResponseObject(), true)
                );
            } catch (\Exception $exc) {
                echo sprintf(
                    "Exception when calling api()->account()->createAccount(): %s\n",
                    $exc->getMessage()
                );
            }

    }


    public function withdrawAsset(Request $request){

        $asset = $request->asset;
        $user = Auth()->user();
        //recheck the balance
        $accountOld = VirtualAccounts::where('virtual_account_id', $asset)->where('user_id',$user->id)->firstOrFail();
        $account= getAssetAccountBalanceReal($accountOld);
        if($request->post()){
            $requestType = $request->type;
            $request->validate([
                'amount' => 'required',
                'withdraw_type'=>'required',
                'address' => 'required_if:withdraw_type,2',
                'email_address' => 'required_if:withdraw_type,1',

            ]);
            $withdrawType = $request->withdraw_type;
            $emailAddress = $request->email_address;
            $amount = $request->amount;
            $getConvertedAssetAmount = convertUsdToAsset($account->last_check_rate, $amount);


            //first check if the balance is enough
            //check minimum withdraw allow
            if ($request->amount < $account->coin->minimum_withdraw) {
                return response()->json(['message' => $account->coin->minimum_withdraw.' USD is the minimum withdraw allow for '.$account->coin->name, 'status'=>'error'], 403);

            }
            if ($request->amount < $account->coin->minimum_withdraw) {
                return response()->json(['message' => $account->coin->minimum_withdraw.' USD is the minimum withdraw allow for '.$account->coin->name, 'status'=>'error'], 403);

            }
            $mainNetworkFees = env($account->blockchain_code.'_GAS');
            $profitOnNetworkFees =$account->coin->transaction_charges- $mainNetworkFees;

            // $networkFees = convertAssetToUSD($account->last_check_rate, $mainNetworkFees);
            $finalWithdraw = $amount + $account->coin->transaction_charges;

            //check if the available balance is same
            if ($finalWithdraw > $account->availableBalanceUSD) {
                return response()->json(['message' => 'Insufficient Asset Balance Please try again', 'status'=>'error'], 403);

            }


            if ($requestType == 'g') {
                if($withdrawType=='2') {
                    return response()->json(['status' => 'success', 'value' => $getConvertedAssetAmount, 'recipient'=>$request->address], 200);


                }
                if($withdrawType==1){//phone
                    $check = User::where('email',  $emailAddress)->where('email', '!=', Auth()->user()->email)
                        ->first();

                    if(empty($check)){
                        return response()->json(['message' => 'UnIdentify Refer2Trade Users, please make sure you input the correct phone number of the users', 'status'=>'error'], 403);


                    }else{
                        $recipientAccount= VirtualAccounts::where('user_id',$check->id)->where('blockchain_code',$account->blockchain_code)->first();
                        if(empty($account)){
                            return response()->json(['message' => $account->blockchain_name.' Wallet cannot be found for user: '.$check->name.'- '.$check->email.' please inform user to create '.$account->blockchain_name .' Wallet' , 'status'=>'error'], 403);


                        }else {
                            return response()->json(['status' => 'success', 'value' => $getConvertedAssetAmount, 'recipient'=> $check->name . " (Phone Number: " . $check->phone . "), WalletAddress: ".$recipientAccount->attarched_address], 200);
                        }
                    }

                }
            }


            if($requestType=='a') {
                //check the password once it has sufficient balance
                if (!(Hash::check($request->password, Auth()->user()->getAuthPassword()))) {
                    return response()->json([
                        'status' => 'error',
                        'message' => 'Invalid Password Please Retry'
                    ], 400);
                }
                $convetedNetworkFees = convertUsdToAsset($account->last_check_rate, $mainNetworkFees);

                //when the password is corrent initiate withdraw
                if ($withdrawType == '2') {
                    if ($account->blockchain_code == 'BTC') {
                        if ($withdrawType == 2) { //external Address
                            $getConvertedProfitAssetAmount = convertUsdToAsset($account->last_check_rate, $profitOnNetworkFees);

                            $response = $this->withdrawBTC($account, $request->address, $getConvertedAssetAmount, $convetedNetworkFees, $request->amount, $getConvertedProfitAssetAmount);
                            //update withdraw status
                            if($response['status']=='error'){
                                return response()->json($response, 403);

                            }else{
                                return response()->json($response, 200);
                            }
                        } elseif ($withdrawType == '1') {
                            //internal withdraw
                        }

                    }elseif($account->blockchain_code=='USDT_TRON'){
                    $response=  $this->withdrawUSDT($account, $request->address, $amount, $convetedNetworkFees, $request->amount, $profitOnNetworkFees);
                    if($response['status']=='error'){
                        return response()->json($response, 403);

                    }else{
                        return response()->json($response, 200);
                    }
                    //return $response;
                }
                }
            }elseif($withdrawType=="1"){
                //this is account to account
            }
        }

        return view('user.crypto.withdraw-crypto', compact('asset', 'account'));
    }

    //withdraw asset test
    public function withdrawBTC($account, $address, $amount, $gas, $amountInUsd, $profitOnNetworkFees){
        $sdk = initiateTatum();// \Tatum\Sdk();
        $paymentId = 'R2T'.time().Auth()->user()->id;
        $senderNote= 'Withdrawing $'.$amount.' BTC from  '.$account->attarched_address.' on '.date('Y-m-d h:i').' to '.$address;
        $withdrawCrypto = new CryptoTransaction();
        $withdrawCrypto->price_amount = $amount;
        $withdrawCrypto->price_in_usd = $amountInUsd;
        $withdrawCrypto->coin_amount = $amount;
        $withdrawCrypto->pay_currency = $account->blockchain_code;
        $withdrawCrypto->price_currency = $account->blockchain_code;
        $withdrawCrypto->recipient_address = $address;
        $withdrawCrypto->coin = $account->blockchain_code;
        $withdrawCrypto->master_address = $account->master_address;
        $withdrawCrypto->token_address = $account->token_address;
        $withdrawCrypto->sender_address = $account->attarched_address;
        $withdrawCrypto->gas_fees = $gas;
        $withdrawCrypto->virtual_wallet_id = $account->id;
        $withdrawCrypto->profit_on_gas = 2;
        $withdrawCrypto->send_from = $account->attarched_address;
        $withdrawCrypto->send_to = $address;
        $withdrawCrypto->transfer_type = 'External';
        $withdrawCrypto->type = 'Withdraw';

        $withdrawCrypto->network = $account->blockchain_code;

        $withdrawCrypto->transaction_type = 2;

        $withdrawCrypto->payment_status = 'Pending';


        $withdrawCrypto->order_id = $paymentId;


        $withdrawCrypto->user_id = Auth()->user()->id;


        $withdrawCrypto->order_description = $senderNote;
        $withdrawCrypto->save();
// 🐛 Enable debugging on the MainNet
        // $sdk->mainnet()->config()->setDebug(true);

        $arg_transfer_btc_mnemonic = (new \Tatum\Model\TransferBtcMnemonic())

            // Sender account ID
            ->setSenderAccountId($account->virtual_account_id)

            // Blockchain address to send assets to. For BTC, LTC, DOGE and BCH, it is possible to enter list of...
            ->setAddress($address)

            // Amount to be withdrawn to blockchain.
            ->setAmount($amount)

            // (optional) Compliance check, if withdrawal is not compliant, it will not be processed.
            ->setCompliant(false)

            // (optional) Fee to be submitted as a transaction fee to blockchain. If none is set, default value of 0.0005 B...
            ->setFee($gas)

            // (optional) For BTC, LTC, DOGE and BCH, it is possible to enter list of multiple recipient blockchain amounts...
            ->setMultipleAmounts(null)

            // (optional) Used to parametrize withdrawal as a change address for left coins from transaction. XPub or attr ...
            ->setAttr('null')

            // Mnemonic seed - usually 12-24 words with access to whole wallet. Either mnemonic, keyPair or sign...
            ->setMnemonic($account->blockchain->menonic)

            // Extended public key (xpub) of the wallet associated with the accounts. Should be present, when mn...
            ->setXpub($account->xpub)

            // (optional) Identifier of the payment, shown for created Transaction within Tatum sender account.
            ->setPaymentId($paymentId)

            // (optional) Note visible to owner of withdrawing account
            ->setSenderNote($senderNote);

        try {

            /**
             * POST /v3/offchain/bitcoin/transfer
             *
             * @var \Tatum\Model\TransferBtcMnemonic200Response $response
             */
            $response = $sdk//->mainnet()
            ->api()
                ->blockchainOperations()
                ->transferBtcMnemonic($arg_transfer_btc_mnemonic);

if(!empty($response->getTxId())) {
    $withdrawCrypto->payment_id = $response->getId();
    $withdrawCrypto->payment_reference = $response->getSignatureId();
    $withdrawCrypto->txid = $response->getTxId();
    $withdrawCrypto->payment_status = 'Completed';
    $withdrawCrypto->save();
    //convert $profitOnNetworkFees to asset

$this->saveTradingTransaction($withdrawCrypto,$profitOnNetworkFees,$account);
    return ['status'=>'success','message'=>'Withdraw Successful','id'=>$response->getTxId()];
}else{
    return ['status'=>'error','message'=>'Unable to complete withdraw','id'=>''];
}
          //  dd($response->getCompleted());

        } catch (\Tatum\Sdk\ApiException $apiExc) {
           /* echo sprintf(
                "API Exception when calling api()->blockchainOperations()->transferBtcMnemonic(): %s\n",
                var_export($apiExc->getResponseObject(), true)
            );*/
            return ['status'=>'error','message'=>sprintf(
                "API Exception when calling api()->blockchainOperations()->transferBtcMnemonic(): %s\n",
                var_export($apiExc->getResponseObject(), true)
            ),'id'=>''];
        } catch (\Exception $exc) {
          /*  echo sprintf(
                "Exception when calling api()->blockchainOperations()->transferBtcMnemonic(): %s\n",
                $exc->getMessage()
            );*/
            return ['status'=>'error','message'=>sprintf(
                "Exception when calling api()->blockchainOperations()->transferBtcMnemonic(): %s\n",
                $exc->getMessage()
            ),'id'=>''];
        }
    }
    public function withdrawUSDT($account, $address, $amount, $gas, $amountInUsd, $profitOnNetworkFees) {
        $client = new Client();

        try {
          $tatumKey=  getTatumKey('live');
          $paymentId ='R2T' . time() . Auth()->user()->id;
          $senderNote ='Withdrawing of $'.$amount.' USDT  from ' . $account->attarched_address . ' on ' . date('Y-m-d h:i') . ' to ' . $address;
            // Generate the Private Key
            $pKey = generateTronPrivateKey($account);
          //check if address is activated
            if($account->activate_address_status==0){//it measn is not activated activte first
                $valid = checkifActivate($account);
                if(!$valid) {
                    $activateId = activateTronGasPumpAddress($account, $pKey);

                    if (!empty($activateId)) {
                        //validate
                        $valid = checkifActivate($account);
                        if ($valid) {
                            $account->activate_address_status = 1;
                            $account->activate_txId = $activateId;
                            $account->save();
                        } else {
                            return ['status' => 'error', 'message' => 'Unable to activate address', 'id' => ''];
                        }
                    } else {
                        return ['status' => 'error', 'message' => 'Unable to activate address', 'id' => ''];
                    }
                }  else {
                    $account->activate_address_status = 1;
                    //$account->activate_txId = $activateId;
                    $account->save();
            }

            }
            // Prepare the body for the withdrawal request
            $body = json_encode([
                'senderAccountId' => $account->virtual_account_id,
                'address' => $address,
                'amount' => $amount,
                'fee' => "40",
                'paymentId' => $paymentId,
                'senderNote' => $senderNote
            ]);
//dd($body);
            // Make the withdrawal request
            $curl = curl_init();



            curl_setopt_array($curl, [
                CURLOPT_URL => 'https://api.tatum.io/v3/offchain/withdrawal',
                CURLOPT_RETURNTRANSFER => true,
                CURLOPT_ENCODING => "",
                CURLOPT_MAXREDIRS => 10,
                CURLOPT_TIMEOUT => 30,
                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                CURLOPT_CUSTOMREQUEST => "POST",
                CURLOPT_POSTFIELDS => $body,
                CURLOPT_HTTPHEADER => [
                    "accept: application/json",
                    "content-type: application/json",
                    "x-api-key: $tatumKey",
                ],
            ]);

            $response = curl_exec($curl);
            $err = curl_error($curl);
            curl_close($curl);

            if ($err) {
                echo "cURL Error #:" . $err;
            } else {
                // Decode the JSON response
                $withdrawResponse = json_decode($response, true);
              //  dd($withdrawResponse); // Use dd() to inspect the successful response
            }
            // Check if the response status code is 200
            if (isset($withdrawResponse['id'])) {
                // Decode the response body
               // $withdrawResponse = json_decode($response->, true);

                // Check if the response contains the expected data
                if (isset($withdrawResponse['id']) && isset($withdrawResponse['reference'])) {
                    //crease system withdraw
                    $withdrawCrypto = new CryptoTransaction();
                    $withdrawCrypto->price_amount = $amount;
                    $withdrawCrypto->price_in_usd = $amountInUsd;
                    $withdrawCrypto->coin_amount = $amount;
                    $withdrawCrypto->pay_currency = 'USDT_TRON';
                    $withdrawCrypto->price_currency = 'USDT_TRON';
                    $withdrawCrypto->recipient_address = $address;
                    $withdrawCrypto->coin = "USDT_TRON";
                    $withdrawCrypto->master_address = $account->master_address;
                    $withdrawCrypto->token_address = $account->token_address;
                    $withdrawCrypto->sender_address = $account->attarched_address;
                    $withdrawCrypto->gas_fees = $gas;
                    $withdrawCrypto->send_from = $account->attarched_address;
                    $withdrawCrypto->send_to = $address;
                    $withdrawCrypto->transfer_type = 'External';
                    $withdrawCrypto->type = 'Withdraw';
                    $withdrawCrypto->profit_on_gas = 2;
                    $withdrawCrypto->network = 'TRON';

                    $withdrawCrypto->transaction_type = 2;
                    $withdrawCrypto->payment_status = 'Pending';


                    $withdrawCrypto->order_id = $paymentId;
                    $withdrawCrypto->payment_id = $withdrawResponse['id'];
                    $withdrawCrypto->payment_reference = $withdrawResponse['reference'];

                    $withdrawCrypto->user_id = Auth()->user()->id;


                    $withdrawCrypto->order_description = $senderNote;
                    $withdrawCrypto->save();

                    if (!empty($pKey)) {
                        //check if asset has enough balance
                       $assetBalance= getUsdtAddressBalance($account->attarched_address, $account->token_address);
                        if ($amount > $assetBalance) {
                            //it mean tradding account has low account balance alert the admin send email to admin
                            @email([
                                'email'   => env('ADMIN_EMAIL'),
                                'name'    => "ADMIN",
                                'subject' => 'Low Asset Balance in User Account When Withdrawing',
                                'message' =>'Hello, System Detect low asset balance but enough VA Balance while customer is withdrawing, this withdraw has been place under pending withdrawer, please transfer some fund then retry',
                            ]);
                            return ['status' => 'success', 'id' => "Pending TRX ID", 'message' => 'Withdraw Initiated'];

                        }else {
                            // Prepare the body for the blockchain transfer request
                            $curl = curl_init();

                            $transferBody = json_encode([
                                'chain' => 'TRON',
                                'contractType' => 0,
                                'custodialAddress' => $account->attarched_address,
                                'recipient' => $address,
                                'tokenAddress' => $account->token_address,
                                'amount' => $amount,
                                'fromPrivateKey' => $pKey,
                                'feeLimit' => 40,
                            ]);

                            curl_setopt_array($curl, [
                                CURLOPT_URL => 'https://api.tatum.io/v3/blockchain/sc/custodial/transfer',
                                CURLOPT_RETURNTRANSFER => true,
                                CURLOPT_ENCODING => "",
                                CURLOPT_MAXREDIRS => 10,
                                CURLOPT_TIMEOUT => 30,
                                CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                                CURLOPT_CUSTOMREQUEST => "POST",
                                CURLOPT_POSTFIELDS => $transferBody,
                                CURLOPT_HTTPHEADER => [
                                    "accept: application/json",
                                    "content-type: application/json",
                                    "x-api-key: $tatumKey",
                                ],
                            ]);

                            $response = curl_exec($curl);
                            $err = curl_error($curl);
                            curl_close($curl);

                            if ($err) {
                                echo "cURL Error #:" . $err;
                            } else {
                                // Decode the JSON response
                                $transferResponse = json_decode($response, true);

                                // Check if the response was successful
                                /*  if (isset($transferResponse['txId'])) {
                                      echo "Transfer successful. Transaction ID: " . $transferResponse['txId'];
                                  } else {
                                      echo "Error: " . json_encode($transferResponse);
                                  }*/
                            }

                            // Check if the transfer response status code is 200
                            if (isset($transferResponse['txId'])) {
                                // Decode the transfer response body
                                //  $transferResponseData = json_decode($transferResponse->getBody(), true);

                                // Check if the response contains the txId
                                if (isset($transferResponse['txId'])) {
                                    // Prepare the URL for completing the withdrawal
                                    $withdrawId = $withdrawResponse['id'];
                                    $txId = $transferResponse['txId'];
                                    $url = "https://api.tatum.io/v3/offchain/withdrawal/$withdrawId/$txId";

                                    $curl = curl_init();

                                    curl_setopt_array($curl, [
                                        CURLOPT_URL => $url,
                                        CURLOPT_RETURNTRANSFER => true,
                                        CURLOPT_ENCODING => "",
                                        CURLOPT_MAXREDIRS => 10,
                                        CURLOPT_TIMEOUT => 30,
                                        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
                                        CURLOPT_CUSTOMREQUEST => "PUT",
                                        CURLOPT_HTTPHEADER => [
                                            "accept: application/json",
                                            "x-api-key: $tatumKey", // Ensure you're using the right key
                                        ],
                                    ]);

                                    $completeWithdraw = curl_exec($curl);
                                    $err = curl_error($curl);
                                    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
                                    curl_close($curl);

                                    if ($err) {
                                        $withdrawCrypto->payment_status = "failed";
                                        $withdrawCrypto->save();

                                        return ['status' => 'error', 'message' => "cURL Error: " . $err, 'id' => ""];
                                    } else {
                                        // Check if the complete withdrawal status code is 204
                                        //if ($httpCode === 204) {
                                        // Withdrawal successful
                                        $withdrawCrypto->txid = $txId;
                                        $withdrawCrypto->payment_status = "Completed";
                                        $withdrawCrypto->save();

                                        $this->transferWithdrawProfit($withdrawCrypto, $profitOnNetworkFees, $account);
                                        return ['status' => 'success', 'id' => $txId, 'message' => 'Withdraw Successful'];
                                        // } else {
                                        //   return ['status' => 'error', 'message' => "Failed to complete withdrawal. HTTP Status Code: " . $httpCode, 'id' => ""];
                                        // }
                                    }
                                }
                            } else {
                                $withdrawCrypto->payment_status = "failed";
                                $withdrawCrypto->save();
                                return ['status' => 'error', 'message' => "Failed to retrieve transaction ID from transfer response.", 'id' => ''];
                            }
                        }
                        } else {
                            //dd($transferResponse);
                            return ['status'=>'error','message'=>"Failed to process blockchain transfer. HTTP Status Code: ", 'id'=>''];
                        }

                    }
                }


        } catch (RequestException $e) {
            // Handle exceptions (for example, log the error message)
            return ['status'=>'error','message'=>"Request failed: " . $e->getMessage(), 'id'=>''];
        }
    }

    private function saveTradingTransaction($withdrawCrypto, $amount,$virtual, $recipient){
$tran =new CryptoTradingProfitTransaction();
$tran->user_id = $withdrawCrypto->user_id;
$tran ->wallet_address = $withdrawCrypto->send_from;
$tran->virtual_account_id = $virtual->virtual_account_id;
$tran->blockchain_code = $withdrawCrypto->blockchain_code;
        $tran->sender_va = $virtual->virtual_account_id;
        $tran->receiver_va = $recipient->virtual_account_id;
$tran->amount = $amount;
$tran->trading_ref = $withdrawCrypto->transaction_ref;
$tran->transaction_reference = $withdrawCrypto->transaction_reference;
$tran->descriptions =$withdrawCrypto->description;
$tran->account_type= "Trading";
$tran->transaction_type= "Credit";
$tran->save();



    }
    private function transferWithdrawProfit($withdrawCrypto, $amount, $virtual){
        $paymentId= uniqid().time() . Auth()->user()->id;
        $orderId = 'R2T-'.$paymentId;
        $description="Profit on ".$withdrawCrypto->description;

        $recipientAccount  = VirtualAccounts::where('blockchain_code',$virtual->blockchain_code)->where('virtual_account_type','Profit')->firstOrFail();

        $sdk = initiateTatum();
// 🐛 Enable debugging on the MainNet
        // $sdk->testnet()->config()->setDebug(true);

        $arg_create_transaction = (new \Tatum\Model\CreateTransaction())

            // Internal sender account ID within Tatum platform
            ->setSenderAccountId($virtual->virtual_account_id)

            // Internal recipient account ID within Tatum platform
            ->setRecipientAccountId($recipientAccount->virtual_account_id)

            // Amount to be sent.
            ->setAmount($amount)

            // (optional) Anonymous transaction does not show sender account to recipient, default is false
            ->setAnonymous(false)

            // (optional) Enable compliant checks. Transaction will not be processed, if compliant check fails.
            ->setCompliant(false)

            // (optional) For bookkeeping to distinct transaction purpose.
            ->setTransactionCode($orderId)

            // (optional) Payment ID, External identifier of the payment, which can be used to pair transactions within Tat...
            ->setPaymentId($paymentId)

            // (optional) Note visible to both, sender and recipient
            ->setRecipientNote($description)

            // (optional) Exchange rate of the base pair. Only applicable for Tatum's Virtual currencies Ledger transaction...
            //  ->setBaseRate(1)

            // (optional) Note visible to sender
            ->setSenderNote($description);

        try {

            /**
             * POST /v3/ledger/transaction
             *
             * @var \Tatum\Model\TransactionResult $response
             */
            $response = $sdk
                ->api()
                ->transaction()
                ->sendTransaction($arg_create_transaction);
            $transaction_reference = $response->getReference();
//dd($transaction_reference);
            if(!empty($transaction_reference)){
                //save transaction

                $tran =new CryptoTradingProfitTransaction();
                $tran->user_id = $withdrawCrypto->user_id;
                $tran ->wallet_address = $withdrawCrypto->send_from;
                $tran->virtual_account_id = $virtual->virtual_account_id;
                $tran->blockchain_code = $withdrawCrypto->blockchain_code;
                $tran->sender_va = $virtual->virtual_account_id;
                $tran->receiver_va = $recipientAccount->virtual_account_id;
                $tran->amount = $amount;
                $tran->trading_ref = $withdrawCrypto->transaction_ref;
                $tran->descriptions ="Profit on ".$withdrawCrypto->description;
                $tran->transaction_type= "Credit";
                $tran->transaction_reference = $transaction_reference;
                $tran->account_type = "Profit";
                $tran->save();

            }
        } catch (\Tatum\Sdk\ApiException $apiExc) {
            /*
            echo sprintf(
                "API Exception when calling api()->transaction()->sendTransaction(): %s\n",
                var_export($apiExc->getResponseObject(), true)
            );*/
            $errorCode = $apiExc->getResponseObject()['errorCode'];
            if($errorCode=='balance.insufficient') {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Insufficient balance please deposit to your wallet and try again!!'
                ], 400);
            }else{
                return response()->json([
                    'status' => 'error',
                    'message' =>  var_export($apiExc->getResponseObject(), true)
                ], 400);
            }

        } catch (\Exception $exc) {
            echo sprintf(
                "Exception when calling api()->transaction()->sendTransaction(): %s\n",
                $exc->getMessage()
            );
        }


    }

    private function transferCryptoBuy($buyModel){
        $paymentId= uniqid().time() . Auth()->user()->id;
        $orderId = 'R2T-BY'.$paymentId;
        $description= $buyModel->order_description;
        $amount = $buyModel->amount_received;

        $recipientAccount  = VirtualAccounts::where('blockchain_code',$buyModel->blockchain_code)->where('user_id',$buyModel->user_id)->where('virtual_account_type','SlaveGas')->firstOrFail();
        $tradingWallet  = VirtualAccounts::where('blockchain_code',$buyModel->blockchain_code)->where('user_id',$buyModel->user_id)->where('virtual_account_type','Trading')->firstOrFail();
//check asset balance
        getAssetAccountBalanceReal($tradingWallet);
        if ($buyModel->amount_received > $tradingWallet->availableBalanceUSD) {
            //it mean tradding account has low account balance alert the admin send email to admin
            @email([
                'email'   => env('ADMIN_EMAIL'),
                'name'    => "ADMIN",
                'subject' => 'Low Virtual Account Balance in Your Trading Wallet',
                'message' =>'Hello, Customer buying transaction is on pending due to low in VA Account Balance in your trading wallet, please transfer some fund then retry',
            ]);


        }else {
            $sdk = initiateTatum();
// 🐛 Enable debugging on the MainNet
            // $sdk->testnet()->config()->setDebug(true);

            $arg_create_transaction = (new \Tatum\Model\CreateTransaction())

                // Internal sender account ID within Tatum platform
                ->setSenderAccountId($tradingWallet->virtual_account_id)

                // Internal recipient account ID within Tatum platform
                ->setRecipientAccountId($recipientAccount->virtual_account_id)

                // Amount to be sent.
                ->setAmount($amount)

                // (optional) Anonymous transaction does not show sender account to recipient, default is false
                ->setAnonymous(false)

                // (optional) Enable compliant checks. Transaction will not be processed, if compliant check fails.
                ->setCompliant(false)

                // (optional) For bookkeeping to distinct transaction purpose.
                ->setTransactionCode($orderId)

                // (optional) Payment ID, External identifier of the payment, which can be used to pair transactions within Tat...
                ->setPaymentId($paymentId)

                // (optional) Note visible to both, sender and recipient
                ->setRecipientNote($description)

                // (optional) Exchange rate of the base pair. Only applicable for Tatum's Virtual currencies Ledger transaction...
                //  ->setBaseRate(1)

                // (optional) Note visible to sender
                ->setSenderNote($description);

            try {

                /**
                 * POST /v3/ledger/transaction
                 *
                 * @var \Tatum\Model\TransactionResult $response
                 */
                $response = $sdk
                    ->api()
                    ->transaction()
                    ->sendTransaction($arg_create_transaction);
                $transaction_reference = $response->getReference();
//dd($transaction_reference);
                if (!empty($transaction_reference)) {
                    //save transaction

                    $tran = new CryptoTradingProfitTransaction();
                    $tran->user_id = $buyModel->user_id;
                    $tran->wallet_address = $tradingWallet->attarched_address;
                    $tran->virtual_account_id = $tradingWallet->virtual_account_id;
                    $tran->blockchain_code = $buyModel->blockchain_code;

                    $tran->amount = $amount;
                    $tran->trading_ref = $buyModel->order_id;
                    $tran->transaction_reference = $transaction_reference;
                    $tran->descriptions = $buyModel->order_description;
                    $tran->transaction_type = "Debit";
                    $tran->account_type = "Trading";
                    $tran->sender_va = $tradingWallet->virtual_account_id;
                    $tran->receiver_va = $recipientAccount->virtual_account_id;
                    $tran->save();
                    $buyModel->payment_status = 'Completed';
                    $buyModel->transaction_reference = $transaction_reference;

                    $buyModel->save();

                }
            } catch (\Tatum\Sdk\ApiException $apiExc) {
                /*
                echo sprintf(
                    "API Exception when calling api()->transaction()->sendTransaction(): %s\n",
                    var_export($apiExc->getResponseObject(), true)
                );*/
                $errorCode = $apiExc->getResponseObject()['errorCode'];
                if ($errorCode == 'balance.insufficient') {
                    return response()->json([
                        'status' => 'error',
                        'message' => 'Insufficient balance please deposit to your wallet and try again!!'
                    ], 400);
                } else {
                    return response()->json([
                        'status' => 'error',
                        'message' => var_export($apiExc->getResponseObject(), true)
                    ], 400);
                }

            } catch (\Exception $exc) {
                echo sprintf(
                    "Exception when calling api()->transaction()->sendTransaction(): %s\n",
                    $exc->getMessage()
                );
            }
        }


    }







}
