<?php

use App\Mail\WelcomeMail;
use App\Models\Admin;
use App\Models\CronJob;
use App\Models\Deposit;
use App\Models\Setting;
use App\Models\BotActivation;
use App\Models\Transaction;
use App\Models\User;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use App\Lib\GoogleAuthenticator;


function verifyG2fa($user, $code, $secret = null) {
    $authenticator = new GoogleAuthenticator();
    if (!$secret) {
        $secret = $user->g2fa_secret;
    }
    $oneCode  = $authenticator->getCode($secret);
    $userCode = $code;
    
    // return $oneCode;
    
    if ($oneCode == $userCode) {
        // $user->tv = Status::YES;
        // $user->save();
        return true;
    } else {
        return false;
    }
}


//endpoint for api calls
if (!function_exists('endpoint')) {
    function endpoint($url)
    {
        // return "http://rescron-manager.local/api/v2/$url"; //local
        return "https://rescron.com/api/v2/$url"; //live
    }
}


if (!function_exists('currency')) {
    function currency($amount, $currency)
    {
        $currency = strtolower($currency); // make case-insensitive

        if ($currency === 'usd') {
            return '$' . $amount;
        } elseif ($currency === 'kes') {
            return 'Ksh. ' . $amount;
        } else {
            return '₦' . $amount;
        }
    }
}


if (!function_exists('totalDeposits')) {
    function totalDeposits($user): bool
    {
        return BotActivation::where('user_id', $user->id)->sum('capital') >= 300;
    }
}



//return user information
if (!function_exists('user')) {
    function user($user_id = null)
    {
        if (!$user_id) {
            $id  = session()->get('user');
        } else {
            $id  = $user_id;
        }

        if ($id) {
            $user = User::getCachedUser($id);
            return $user;
        }

        return false;
    }
}

//return admin information
if (!function_exists('admin')) {
    function admin()
    {
        $id  = session()->get('admin');
        //dd($id);

        if ($id) {
            $admin = Admin::getCachedAdmin($id);
            return $admin;
        }

        return false;
    }
}

//generate otp 
if (!function_exists('generateOTP')) {
    function generateOTP($email, $admin = false)
    {
        $otpLength = 6;
        $code = '';
        $characters = '0123456789';

        $charactersLength = strlen($characters);
        for ($i = 0; $i < $otpLength; $i++) {
            $code .= $characters[rand(0, $charactersLength - 1)];
        }
        $otp = [
            'code' => $code,
            'expires' => strtotime(now()->addMinutes(15)),
            'email' => $email
        ];

        if ($admin) {
            session()->put('admin-otp', $otp);
        } else {
            session()->put('otp', $otp);
        }
        return $otp;
    }
}

//validate otp
if (!function_exists('validateOtp')) {
    function validateOtp($code, $email,  $admin = false)
    {
        if ($admin) {
            $stored_otp = session()->get('admin-otp');
        } else {
            $stored_otp = session()->get('otp');
        }

        if (!$stored_otp) {
            return false;
        }

        if ($stored_otp['code'] !== $code || $stored_otp['expires'] < time() || $stored_otp['email'] !== $email) {
            return false;
        }

        session()->pull('otp');
        session()->pull('admin-otp');
        return true;
    }
}

//update env
if (!function_exists('updateEnvValue')) {
    function updateEnvValue($key, $newValue)
    {
        $envFile = base_path('.env');
        if (filter_var($newValue, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null) {
            $newValue = $newValue;
        } else {
            $newValue = '"' . $newValue . '"';
        }

        // Read the .env file
        $contents = file_get_contents($envFile);

        // Update the value
        $pattern = "/^($key=)(.*)$/m";
        $replacement = "$1$newValue";
        $updatedContents = preg_replace($pattern, $replacement, $contents);

        // Write the updated contents back to the .env file
        file_put_contents($envFile, $updatedContents);

        return true;
    }
}

//retrive setting
if (!function_exists('site')) {
    function site($key)
    {
        $site = app('site');
        if ($key == 'template') {
            $template = session()->get('template', $site->get($key)->value);
            // dd($template);
            return $template;
        }
        return $site->get($key)->value ?? null;
    }
}



//update setting
if (!function_exists('updateSite')) {
    function updateSite(array $settings)
    {
        Setting::updateSettings($settings);
    }
}

//domain
if (!function_exists('domain')) {
    function domain()
    {
        // Check if running from web request
        if (isset($_SERVER['HTTP_HOST'])) {
            $subdomain = $_SERVER['HTTP_HOST'];
        } else {
            // Fallback for CLI or when HTTP_HOST is not available
            $subdomain = config('app.url', 'localhost');
            // Remove protocol if present
            $subdomain = preg_replace('/^https?:\/\//', '', $subdomain);
        }
        
        // // Split the subdomain by dots
        // $parts = explode('.', $subdomain);

        // // Check if there are more than two parts (subdomains + domain) in the input
        // if (count($parts) > 2) {
        //     // Join the last two parts as the domain
        //     $domain = $parts[count($parts) - 2] . '.' . $parts[count($parts) - 1];
        //     return $domain;
        // }

        // If no subdomain was found or it is just the domain, return the original string as the domain
        // return $subdomain;
        return "rescron.com";
    }
}

//retrieve public key
if (!function_exists('getKeys')) {
    function getKeys()
    {
        $api_key = env('NP_API_KEY');
        
        if (!$api_key) {
            Log::error('NowPayments API key not configured');
            return null;
        }
        
        return $api_key;
    }
}

//update deposit information
if (!function_exists('updateDeposit')) {
    function updateDeposit($amount)
    {
        $url = endpoint('update-deposit');

        // Get the current HTTP_HOST from the request
        $httpHost = domain();

        $response = Http::withHeaders([
            'X-DOMAIN' => $httpHost, // Set X-DOMAIN header with the current HTTP_HOST value
            'X-AMOUNT' => $amount,
        ])->get($url);

        // Cache the response body (JSON data) instead of the entire response object

        return true;
    }
}

//validation error 
if (!function_exists('validationError')) {
    function validationError($message)
    {
        return [
            'message' => $message,
            'errors' => [
                'error' => [
                    $message
                ],
            ],
        ];
    }
}

//delete files and folders
if (!function_exists('deleteFilesAndFoldersRecursively')) {
    function deleteFilesAndFoldersRecursively($dir)
    {
        $iterator = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS),
            RecursiveIteratorIterator::CHILD_FIRST
        );

        foreach ($iterator as $fileInfo) {
            if ($fileInfo->isDir()) {
                rmdir($fileInfo->getRealPath());
            } else {
                unlink($fileInfo->getRealPath());
            }
        }

        rmdir($dir);
    }
}

//image uploader
if (!function_exists('uploadImage')) {
    function uploadImage($image, $path)
    {
        // $urs = recentTrades();
        $absolute_path = storage_path('app/public/' . $path);
        if (!File::isDirectory($absolute_path)) {
            File::makeDirectory($absolute_path, 0775);
        }

        $name = $image->hashName();
        $upload_image = $image->storeAs('public/' . $path . '/', $name);
        return $name;
    }
}

//protect middleware
if (!function_exists('consolidateSecurity')) {
    function consolidateSecurity()
    {
        return true;
    }
}

// initiate deposit
if (!function_exists('initiateDeposit')) {
    // function initiateDeposit($amount, $currency, $processor)
    // {
    //     $public_key = getKeys();
    //     $base_currency  = strtolower(site('currency'));
    //     $converted_amount = convertFiatToCrypto($base_currency, $currency, $amount);

    //     if ($processor == 'nowpayment') {
    //         $url = 'deposits/nowpayment';
    //         $url = endpoint($url);

    //         $data = [
    //             'api_key' => $public_key,
    //             'amount' => $amount,
    //             'base_currency' => $base_currency,
    //             'currency' => $currency,
    //             'callback' => route('payment-callback'),
    //             'converted_amount' => $converted_amount,
    //         ];
    //     } elseif ($processor == 'coinpayment') {
    //         $url = 'deposits/coinpayment';
    //         $url = endpoint($url);

    //         $data = [
    //             'public_key' => env('COINPAYMENT_PUBLIC_KEY'),
    //             'private_key' => env('COINPAYMENT_PRIVATE_KEY'),
    //             'amount' => $amount,
    //             'base_currency' => $base_currency,
    //             'currency' => $currency,
    //             'callback' => route('payment-callback-coinpayment'), //chnage for coinpayment
    //             'converted_amount' => $converted_amount,
    //             'email' => site('email')
    //         ];
    //     } else {
    //         return false;
    //     }

    //     $response = Http::post($url, $data);

    //     // dd($response->body());

    //     if (!$response->successful()) {
    //         return false;
    //     }

    //     $real_order = $response->body();

    //     return $real_order;
    // }
    
    
    
    
// function initiateDeposit($amount, $currency, $processor)
// {
//     Log::info('initiateDeposit called', [
//         'amount' => $amount,
//         'currency' => $currency,
//         'processor' => $processor
//     ]);

//     try {
//         $public_key = getKeys();
//         Log::info('Retrieved public key', ['public_key' => $public_key]);

//         $base_currency  = strtolower(site('currency'));
//         Log::info('Base currency', ['base_currency' => $base_currency]);

//         $converted_amount = convertFiatToCrypto($base_currency, $currency, $amount);
//         Log::info('Converted amount', [
//             'from' => $base_currency,
//             'to' => $currency,
//             'amount' => $amount,
//             'converted_amount' => $converted_amount
//         ]);

//         if ($processor == 'nowpayment') {
//             $url = 'deposits/nowpayment';
//             $url = endpoint($url);
//             Log::info('NowPayment endpoint', ['url' => $url]);

//             $data = [
//                 'api_key' => $public_key,
//                 'amount' => $amount,
//                 'base_currency' => $base_currency,
//                 'currency' => $currency,
//                 'callback' => route('payment-callback'),
//                 'converted_amount' => $converted_amount,
//             ];
//             Log::info('NowPayment data', $data);
//         } elseif ($processor == 'coinpayment') {
//             $url = 'deposits/coinpayment';
//             $url = endpoint($url);
//             Log::info('CoinPayment endpoint', ['url' => $url]);

//             $data = [
//                 'public_key' => env('COINPAYMENT_PUBLIC_KEY'),
//                 'private_key' => env('COINPAYMENT_PRIVATE_KEY'),
//                 'amount' => $amount,
//                 'base_currency' => $base_currency,
//                 'currency' => $currency,
//                 'callback' => route('payment-callback-coinpayment'),
//                 'converted_amount' => $converted_amount,
//                 'email' => site('email')
//             ];
//             Log::info('CoinPayment data', $data);
//         } else {
//             Log::error('Unknown processor', ['processor' => $processor]);
//             return false;
//         }

//         Log::info('Sending HTTP POST', ['url' => $url, 'data' => $data]);
//         $response = Http::post($url, $data);

//         Log::info('HTTP response', [
//             'status' => $response->status(),
//             'body' => $response->body()
//         ]);

//         if (!$response->successful()) {
//             Log::error('HTTP request failed', [
//                 'status' => $response->status(),
//                 'body' => $response->body()
//             ]);
//             return false;
//         }

//         $real_order = $response->body();
//         Log::info('Deposit initiated successfully', ['real_order' => $real_order]);

//         return $real_order;
//     } catch (\Throwable $e) {
//         Log::error('Exception in initiateDeposit', [
//             'message' => $e->getMessage(),
//             'trace' => $e->getTraceAsString()
//         ]);
//         return false;
//     }
// }
    

    function initiateDeposit($amount, $currency, $processor, $wallet_address = null, $origin = null)
    {
        $public_key = getKeys();
        
        if (!$public_key) {
            Log::error('API key not available for payment processor');
            return false;
        }
        
        $base_currency  = strtolower(site('currency'));
        $converted_amount = convertFiatToCrypto($base_currency, $currency, $amount);

        // Log conversion result
        Log::info('Currency conversion result', [
            'from' => $base_currency,
            'to' => $currency,
            'amount' => $amount,
            'converted_amount' => $converted_amount
        ]);

        if (!$converted_amount) {
            Log::error('Failed to convert currency', [
                'base_currency' => $base_currency,
                'target_currency' => $currency,
                'amount' => $amount
            ]);
            return false;
        }

        // DIRECT NOWPAYMENTS INTEGRATION - bypassing rescron.com proxy
        if ($processor == 'nowpayment') {
            return initiateDepositDirect($amount, $currency, $public_key, $converted_amount, $wallet_address, $origin);
        } elseif ($processor == 'coinpayment') {
            $url = 'deposits/coinpayment';
            $url = endpoint($url);

            $data = [
                'public_key' => env('COINPAYMENT_PUBLIC_KEY'),
                'private_key' => env('COINPAYMENT_PRIVATE_KEY'),
                'amount' => $amount,
                'base_currency' => $base_currency,
                'currency' => $currency,
                'callback' => route('payment-callback-coinpayment'),
                'converted_amount' => $converted_amount,
                'email' => site('email'),
                'wallet_address' => $wallet_address
            ];
        } elseif ($processor == 'manual') {
            // For manual, use direct NowPayments with wallet address override
            return initiateDepositDirect($amount, $currency, $public_key, $converted_amount, $wallet_address, $origin);
        } else {
            Log::error('Invalid payment processor', ['processor' => $processor]);
            return false;
        }

        // Only coinpayment uses the proxy now
        Log::info('Making deposit request', [
            'url' => $url,
            'processor' => $processor,
            'data' => array_merge($data, ['public_key' => '***hidden***', 'private_key' => '***hidden***'])
        ]);

        $response = Http::withoutVerifying()->post($url, $data);

        Log::info('Deposit API response', [
            'status' => $response->status(),
            'successful' => $response->successful(),
            'body' => $response->body()
        ]);

        if (!$response->successful()) {
            Log::error('Deposit API request failed', [
                'status' => $response->status(),
                'response_body' => $response->body(),
                'url' => $url
            ]);
            return false;
        }

        $real_order = $response->body();
        
        $test_decode = json_decode($real_order);
        if (json_last_error() !== JSON_ERROR_NONE) {
            Log::error('Invalid JSON response from deposit API', [
                'response' => $real_order,
                'json_error' => json_last_error_msg()
            ]);
            return false;
        }

        return $real_order;
    }
}

// Direct NowPayments API integration
if (!function_exists('initiateDepositDirect')) {
    function initiateDepositDirect($amount, $currency, $api_key, $converted_amount, $manual_wallet = null, $origin = null)
    {
        $order_id = null;
        
        if($origin == "cbcnet"){
            $order_id = 'DEP_CBCNET_' . uniqid() . '_' . time();
        }else{
            $order_id = 'DEP_' . uniqid() . '_' . time();
        }
        
        $callback_url = route('payment-callback');
        
        // Map currency codes to NowPayments format
        $currency_map = [
            'USDTTRC20' => 'usdttrc20',
            'USDTBSC' => 'usdtbsc', 
            'USDTERC20' => 'usdterc20',
            'USDT' => 'usdttrc20',
            'BTC' => 'btc',
            'ETH' => 'eth',
            'LTC' => 'ltc',
            'DOGE' => 'doge',
            'BNB' => 'bnbbsc',
            'BNBBSC' => 'bnbbsc',
            'TRX' => 'trx',
            'XRP' => 'xrp',
            'SOL' => 'sol',
            'MATIC' => 'maticpolygon',
            'AVAX' => 'avaxc',
            'ADA' => 'ada',
            'DOT' => 'dot',
            'SHIB' => 'shiberc20',
        ];
        
        $pay_currency = $currency_map[strtoupper($currency)] ?? strtolower($currency);
        
        $fields = [
            "price_amount" => (float) $amount,
            "price_currency" => "usd",
            "pay_currency" => $pay_currency,
            "ipn_callback_url" => $callback_url,
            "order_id" => $order_id,
            "order_description" => "Deposit to CBrilliance",
            "is_fixed_rate" => false,
            "is_fee_paid_by_user" => false
        ];

        Log::info('Making direct NowPayments API request', [
            'url' => 'https://api.nowpayments.io/v1/payment',
            'pay_currency' => $pay_currency,
            'amount' => $amount,
            'order_id' => $order_id
        ]);

        try {
            $response = Http::withHeaders([
                'x-api-key' => $api_key,
                'Content-Type' => 'application/json',
            ])->post('https://api.nowpayments.io/v1/payment', $fields);

            Log::info('Direct NowPayments API response', [
                'status' => $response->status(),
                'successful' => $response->successful(),
                'body' => $response->body()
            ]);

            if (!$response->successful()) {
                $errorBody = json_decode($response->body());
                $errorMessage = $errorBody->message ?? $response->body();
                
                Log::error('Direct NowPayments API request failed', [
                    'status' => $response->status(),
                    'response_body' => $response->body(),
                    'error_message' => $errorMessage
                ]);
                return false;
            }

            $result = json_decode($response->body());
            
            if (!$result) {
                Log::error('Failed to decode NowPayments response', [
                    'response' => $response->body()
                ]);
                return false;
            }
            
            if (isset($result->error) || isset($result->message)) {
                Log::error('NowPayments API returned error', [
                    'error' => $result->error ?? null,
                    'message' => $result->message ?? null
                ]);
                return false;
            }
            
            if (!isset($result->payment_id)) {
                Log::error('No payment_id in NowPayments response', [
                    'response' => $response->body()
                ]);
                return false;
            }
            
            // Build response in expected format
            $transformed = [
                'payment_id' => $result->payment_id,
                'order_id' => $result->order_id ?? $order_id,
                'payment_status' => $result->payment_status ?? 'waiting',
                'pay_amount' => $result->pay_amount ?? $converted_amount,
                'pay_address' => $manual_wallet ?? $result->pay_address ?? null,
                'network' => $result->network ?? $pay_currency,
                'valid_until' => $result->expiration_estimate_date ?? $result->valid_until ?? null,
                'price_amount' => $result->price_amount ?? $amount,
                'price_currency' => $result->price_currency ?? 'usd',
                'pay_currency' => $result->pay_currency ?? $pay_currency,
                'purchase_id' => $result->purchase_id ?? null,
                'created_at' => $result->created_at ?? now()->toIso8601String()
            ];
            
            Log::info('Direct NowPayments deposit created successfully', [
                'payment_id' => $transformed['payment_id'],
                'pay_address' => $transformed['pay_address'],
                'pay_amount' => $transformed['pay_amount'],
                'order_id' => $transformed['order_id']
            ]);
            
            return json_encode((object) $transformed);

        } catch (\Exception $e) {
            Log::error('Exception in direct NowPayments API call', [
                'message' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            return false;
        }
    }
}


if (!function_exists('depositCallback')) {
    function depositCallback()
    {
        Log::info('NowPayments deposit callback started', ['headers' => request()->headers->all()]);
        
        $ipn_secret = env('NP_SECRET_KEY');
        Log::info('IPN secret loaded', ['secret_exists' => !empty($ipn_secret)]);

        $error_msg = "Unknown error";
        $auth_ok = false;
        $request_data = null;

        if (request()->header('x-nowpayments-sig')) {
            Log::info('HMAC signature header found');
            
            $received_hmac = request()->header('x-nowpayments-sig');
            $request_json = request()->getContent();
            
            Log::info('Request data retrieved', [
                'content_length' => strlen($request_json),
                'received_hmac' => substr($received_hmac, 0, 10) . '...'
            ]);
            
            $request_data = json_decode($request_json, true);
            
            if ($request_data === null) {
                Log::error('Failed to decode JSON', ['json_error' => json_last_error_msg()]);
                $error_msg = 'Invalid JSON data';
            } else {
                Log::info('JSON decoded successfully', ['data_keys' => array_keys($request_data)]);
                
                ksort($request_data);
                $sorted_request_json = json_encode($request_data);
                
                Log::info('Request data sorted for HMAC verification');

                if ($request_json !== false && !empty($request_json)) {
                    $hmac = hash_hmac("sha512", $sorted_request_json, $ipn_secret);
                    
                    if (hash_equals($hmac, $received_hmac)) {
                        $auth_ok = true;
                        Log::info('HMAC verification successful');
                    } else {
                        Log::error('HMAC verification failed', [
                            'calculated_hmac' => substr($hmac, 0, 10) . '...',
                            'received_hmac' => substr($received_hmac, 0, 10) . '...'
                        ]);
                        $error_msg = 'HMAC verification failed';
                    }
                } else {
                    Log::error('Empty or invalid request content');
                    $error_msg = 'Error reading POST data';
                }
            }
        } else {
            Log::error('No HMAC signature header found', ['all_headers' => request()->headers->all()]);
            $error_msg = 'No HMAC signature sent.';
        }

        if ($auth_ok && $request_data != null) {
            Log::info('Authentication successful, processing payment data');
            
            $resp = json_decode($request_json);
            
            if (!$resp) {
                Log::error('Failed to decode response JSON for processing');
                return false;
            }
            
            $ref = $resp->order_id ?? null;
            $payment_id = $resp->payment_id ?? null;
            $status = $resp->payment_status ?? null;

            Log::info('Payment details extracted', [
                'order_id' => $ref,
                'payment_id' => $payment_id,
                'payment_status' => $status
            ]);

            if (!$payment_id) {
                Log::error('Payment ID missing from callback');
                return false;
            }

            //get the deposit
            // $deposit = Deposit::where('ref', $ref)->first();
            
            //get the deposit
            $deposit = Deposit::where('payment_id', (string)$payment_id)->first();
            
            // If not found, try alternative search methods
            if (!$deposit) {
                Log::info('Deposit not found with exact match, trying alternatives', ['payment_id' => $payment_id]);
                
                // Try case-insensitive search
                $deposit = Deposit::whereRaw('LOWER(payment_id) = ?', [strtolower($payment_id)])->first();
                
                // If still not found, try with order_id as fallback
                if (!$deposit && isset($resp->order_id)) {
                    $deposit = Deposit::where('ref', (string)$resp->order_id)->first();
                }
                
                // If still not found, try with ref as final fallback
                if (!$deposit && $ref) {
                    $deposit = Deposit::where('ref', (string)$ref)->first();
                }
            }
            
            if ($deposit) {
                Log::info('Deposit found', [
                    'deposit_id' => $deposit->id,
                    'current_status' => $deposit->status,
                    'amount' => $deposit->amount,
                    'user_id' => $deposit->user_id
                ]);
                
                // if ($status == 'finished') {
                //     Log::info('Processing finished payment');
                    
                //     //log new deposit request
                //     updateDeposit($deposit->amount);
                //     Log::info('Deposit amount updated');

                //     $result = processDeposit($deposit->id, 'approve');
                //     Log::info('Deposit processed', ['result' => $result]);
                    
                    
                //     // activate user and add referral bonus
                //     if ($deposit->payment_type === 'reg_fee') {
                //         $user = User::where('user_id', $deposit->user_id)->first();
                //         $user->fee_paid = 1;
                //         $user->balance += 100;
                //         $user->save();
                        
                        
                //         // referral
                //         $referral = User::where('username', $user->referred_by)->first();
                //         $referral->balance += 5;
                //         $referral->save();
                        
                //     }

                //     return true;
                // } 
                
                
                if ($status === 'finished') {

                    Log::info('Payment marked as finished', [
                        'deposit_id' => $deposit->id ?? null,
                        'user_id'    => $deposit->user_id ?? null,
                        'amount'     => $deposit->amount ?? null,
                        'type'       => $deposit->payment_type ?? null,
                    ]);
                
                    // 1. Validate deposit data
                    if (empty($deposit->id) || empty($deposit->user_id)) {
                        Log::error('Invalid deposit object received', [
                            'deposit' => $deposit
                        ]);
                        return false;
                    }
                
                    // 2. Update global deposit stats
                    updateDeposit($deposit->amount);
                    Log::info('Deposit totals updated', [
                        'amount' => $deposit->amount
                    ]);
                
                    // 3. Process deposit approval
                    $result = processDeposit($deposit->id, 'approve');
                
                    Log::info('Deposit approval executed', [
                        'deposit_id' => $deposit->id,
                        'result'     => $result
                    ]);
                
                    if ($result !== true) {
                        Log::warning('Deposit processing returned non-success', [
                            'deposit_id' => $deposit->id,
                            'result'     => $result
                        ]);
                    }
                    
                    
                    // CBCNET deposit
                    if (str_contains($deposit->ref, 'DEP_CBCNET_')) {
                        
                        $user = User::where('user_id', $deposit->user_id)->first();
                
                        if (!$user) {
                            Log::error('Crypto: User not found for crypto deposit payment', [
                                'user_id'    => $deposit->user_id,
                                'deposit_id' => $deposit->id
                            ]);
                            return false;
                        }
                
                        $user->cbc_balance += $deposit->amount;
                        $user->save();
                    }
                    
                
                    // 4. Handle registration fee logic
                    if ($deposit->payment_type === 'reg_fee') {
                
                        $user = User::where('user_id', $deposit->user_id)->first();
                
                        if (!$user) {
                            Log::error('Crypto: User not found for reg_fee payment', [
                                'user_id'    => $deposit->user_id,
                                'deposit_id' => $deposit->id
                            ]);
                            return false;
                        }
                
                        creditSignupBonus($user);
                
                        Log::info('Crypto: User activated and credited', [
                            'user_id' => $user->user_id,
                            'credit'  => 50
                        ]);
                
                        // 5. Referral bonus (optional)
                        if (!empty($user->referred_by)) {
                
                            $referral = User::where('username', $user->referred_by)->first();
                
                            if ($referral) {
                                $referral->balance += 5;
                                $referral->save();
                
                                Log::info('Crypto: Referral bonus applied', [
                                    'referrer' => $referral->username,
                                    'amount'   => 5,
                                    'from_user'=> $user->user_id
                                ]);
                            } else {
                                Log::warning('Crypto: Referral username not found', [
                                    'referred_by' => $user->referred_by,
                                    'user_id'     => $user->user_id
                                ]);
                            }
                        }
                    }
                
                    return true;
                } elseif ($deposit->status !== 'finished' && $deposit->status !== 'expired') {
                    Log::info('Updating deposit status', [
                        'from' => $deposit->status,
                        'to' => $status
                    ]);
                    
                    // just update the deposit status
                    $update = Deposit::find($deposit->id);
                    $update->status = $status;
                    $update->save();

                    Log::info('Deposit status updated successfully');
                    return true;
                } else {
                    Log::warning('Deposit already processed or expired', [
                        'current_status' => $deposit->status,
                        'new_status' => $status
                    ]);
                }

                return false;
            } else {
                Log::error('Deposit not found', ['payment_id' => $payment_id]);
                return false;
            }
        } else {
            Log::error('Authentication failed', [
                'auth_ok' => $auth_ok,
                'request_data_exists' => $request_data !== null,
                'error_message' => $error_msg
            ]);
            return false;
        }
    }
}



// if (!function_exists('depositCallback')) {
//     function depositCallback()
//     {
//         $ipn_secret = env('NP_SECRET_KEY');

//         $error_msg = "Unknown error";
//         $auth_ok = false;
//         $request_data = null;

//         if (request()->header('x-nowpayments-sig')) {
//             $received_hmac = request()->header('x-nowpayments-sig');
//             $request_json = request()->getContent();
//             $request_data = json_decode($request_json, true);
//             ksort($request_data);
//             $sorted_request_json = json_encode($request_data);

//             if ($request_json !== false && !empty($request_json)) {
//                 $hmac = hash_hmac("sha512", $sorted_request_json, $ipn_secret);
//                 $auth_ok = true;
//             } else {
//                 $error_msg = 'Error reading POST data';
//             }
//         } else {
//             $error_msg = 'No HMAC signature sent.';
//         }

//         if ($auth_ok && $request_data != null) {
//             $resp = json_decode($request_json);
//             $ref = $resp->order_id;
//             $payment_id = $resp->payment_id;
//             $status = $resp->payment_status;

//             //get the deposit
//             $deposit = Deposit::where('payment_id', $payment_id)->first();
//             if ($deposit) {
//                 if ($status == 'finished') {
//                     //log new deposit request
//                     updateDeposit($deposit->amount);

//                     processDeposit($deposit->id, 'approve');

//                     return true;
//                 } elseif ($deposit->status !== 'finished' && $deposit->status !== 'expired') {
//                     // just update the deposit status
//                     $update = Deposit::find($deposit->id);
//                     $update->status = $status;
//                     $update->save();

//                     return true;
//                 }

//                 return false;
//             }

//             return false;
//         } else {
//             return false;
//         }
//     }
// }

if (!function_exists('depositCallbackCoinpayment')) {
    function depositCallbackCoinpayment()
    {
        $cp_merchant_id = env('COINPAYMENT_MARCHANT_ID');
        $cp_ipn_secret = env('COINPAYMENT_IPN_SECRET');

        if (request()->input('ipn_mode') != 'hmac') {
            Log::error(json_encode(['IPN Mode is not HMAC', request()->all()]));
            return;
        }

        $hmacHeader = request()->header('HMAC') ?? request()->header('hmac') ?? request()->header('HTTP_HMAC');
        if (empty($hmacHeader)) {
            Log::error(json_encode(['No HMAC signature sent.', request()->all()]));
            return;
        }

        $requestContent = request()->getContent();
        if (empty($requestContent)) {
            Log::error(json_encode(['Error reading POST data', request()->all()]));
            return;
        }

        if (request()->input('merchant') != trim($cp_merchant_id)) {
            Log::error(json_encode(['No or incorrect Merchant ID passed', request()->all()]));
            return;
        }

        $hmac = hash_hmac("sha512", $requestContent, trim($cp_ipn_secret));
        if (!hash_equals($hmac, $hmacHeader)) {
            Log::error(json_encode(['HMAC signature does not match', request()->all()]));
            return;
        }

        $ipn_type = request()->ipn_type;
        $payment_id = request()->txn_id;

        $in_status = intval(request()->status);
        if ($in_status == -2) {
            $status = 'rejected';
        }

        switch ($in_status) {
            case -2:
                $status = 'rejected';
                break;

            case -1:
                $status = 'rejected';
                break;
            case 0:
                $status = 'waiting';
                break;
            case 1:
                $status = 'confirming';
                break;
            case 2:
                $status = 'finished';
                break;
            case 3:
                $status = 'confirming';
                break;
            case 100:
                $status = 'finished';
                break;
            default:
                $status = 'rejected';
                break;
        }

        if ($ipn_type != 'api') {
            Log::error('Invalid Ipn type '  . $ipn_type);
            return;
        }

        // Log::error(json_encode(['Everything okay', request()->headers->all(), request()->all()]));

        //get the deposit
        $deposit = Deposit::where('payment_id', $payment_id)->first();
        if ($deposit) {

            if ($deposit->status == 'finished' || $deposit->status == 'rejected') {
                return;
            }

            if ($status == 'finished') {
                //log new deposit request
                updateDeposit($deposit->amount);

                processDeposit($deposit->id, 'approve');

                return true;
            } elseif ($deposit->status !== 'finished' && $deposit->status !== 'expired') {
                // just update the deposit status
                $update = Deposit::find($deposit->id);
                $update->status = $status;
                $update->save();

                return true;
            }

            return false;
        }

        return false;
    }
}

//record new transaction
if (!function_exists('recordNewTransaction')) {
    function recordNewTransaction($amount, $user_id, $type, $description, $currency = 'usd')
    {
        $transaction = new Transaction();
        $transaction->user_id  = $user_id;
        $transaction->amount = $amount;
        $transaction->type = $type;
        $transaction->currency = $currency;
        $transaction->ref = uniqid('trx-');
        $transaction->description = $description;
        $transaction->balance = user($user_id)->balance;
        $transaction->save();

        return true;
    }
}

//countries
if (!function_exists('countries')) {
    function countries()
    {
        $path = resource_path('json/countries.json');
        $countries_json = file_get_contents($path);
        $countries = json_decode($countries_json);

        return $countries;
    }
}

// curriencies
if (!function_exists('currencies')) {
    function currencies()
    {
        $path = resource_path('json/currencies.json');
        $currencies_json = file_get_contents($path);
        $currencies = json_decode($currencies_json);

        return $currencies;
    }
}

//format amount


if (!function_exists('formatAmount')) {
    function formatAmount($amount, $currency = null, $use_sign = null, $position = null)
    {
        $currency = $currency ?? site('currency');
        $use_sign = $use_sign ?? site('use_sign');
        $position = $position ?? site('currency_position');

        $code = strtolower($currency);
        $currencies = currencies();
        $selected = null;

        foreach ($currencies as $currency) {
            if ($currency->code === $code) {
                $selected = $currency;
                break;
            }
        }

        if ($selected) {
            $formattedAmount = number_format($amount, $selected->is_fiat ? 2 : 8);

            if ($use_sign == 1) {
                $symbol = $selected->symbol ?? $selected->code;
            } else {
                $symbol = $selected->code;
            }

            return strtoupper($position === 'left' ? $symbol . $formattedAmount : $formattedAmount . $symbol);
        }

        return strtoupper($code . number_format($amount, 2));
    }
}

//check for required input field
if (!function_exists('is_required')) {
    function is_required($field, $star = true)
    {
        $required = json_decode(site('user_fields'));
        if (in_array($field, $required)) {
            if ($star) {
                return '<span class="text-red-500"> *</span>';
            } else {
                return 'required';
            }
        }
    }
}

//convert currency
// if (!function_exists('convertFiatToCrypto')) {
//     function convertFiatToCrypto($fiat, $crypto,  $amount)
//     {
//         // fetch conversion from api
//         $url = endpoint('convert');
//         $query = [
//             'base' => $fiat,
//             'currency' => $crypto,
//             'amount' => $amount
//         ];

//         $response = Http::withHeader('X-DOMAIN', domain())->withoutVerifying()->get($url, $query);
//         if (!$response->successful()) {
//             return false;
//         }

//         $data = $response->json();
//         $converted_amount = $data['converted_amount'];
//         return $converted_amount;
//     }
// }

//convert currency
if (!function_exists('convertFiatToCrypto')) {
    function convertFiatToCrypto($fiat, $crypto, $amount)
    {
        try {

            $fiat = strtolower($fiat);
            $crypto = strtoupper($crypto);

            // Map blockchain tokens to CoinGecko IDs
            $map = [
                'USDTTRC20' => 'tether',
                'USDTBSC' => 'tether',
                'USDTERC20' => 'tether',
                'USDT' => 'tether',
                'BTC' => 'bitcoin',
                'ETH' => 'ethereum',
                'LTC' => 'litecoin',
                'DOGE' => 'dogecoin',
                'BNB' => 'binancecoin',
                'TRX' => 'tron',
                'SOL' => 'solana',
                'MATIC' => 'matic-network',
                'AVAX' => 'avalanche-2',
                'ADA' => 'cardano',
                'DOT' => 'polkadot',
                'XRP' => 'ripple'
            ];

            if (!isset($map[$crypto])) {
                Log::error('Unsupported crypto for conversion', [
                    'crypto' => $crypto
                ]);
                return false;
            }

            $coin = $map[$crypto];

            $response = Http::get(
                "https://api.coingecko.com/api/v3/simple/price",
                [
                    "ids" => $coin,
                    "vs_currencies" => $fiat
                ]
            );

            if (!$response->successful()) {
                Log::error('CoinGecko API failed', [
                    'status' => $response->status(),
                    'body' => $response->body()
                ]);
                return false;
            }

            $data = $response->json();

            if (!isset($data[$coin][$fiat])) {
                Log::error('Invalid price data from CoinGecko', $data);
                return false;
            }

            $price = $data[$coin][$fiat];

            $converted = $amount / $price;

            return round($converted, 8);

        } catch (\Throwable $e) {

            Log::error('Conversion exception', [
                'message' => $e->getMessage()
            ]);

            return false;
        }
    }
}

// process deposit
if (!function_exists('processDeposit')) {
    function processDeposit($id, $action)
    {
        $deposit = Deposit::find($id);
        if (!$deposit) {
            return false;
        }

        $user = User::find($deposit->user_id); // load user once

        if (!$user) {
            return false;
        }
        
        
        
        

        if ($action === 'approve') {

            if (!in_array($deposit->status, ['finished', 'expired'])) {

                // mark deposit as completed
                $deposit->status = 'finished';
                $deposit->save();

                // if it's a normal deposit (NOT registration fee)
                if ($deposit->payment_type !== 'reg_fee') {

                    // SAFELY credit user
                    $user->increment('balance', $deposit->amount);

                    // record transaction
                    $description = "New {$deposit->currency} deposit";
                    recordNewTransaction($deposit->amount, $user->id, 'credit', $description);

                    // send confirmation email
                    sendDepositConfirmedMail($deposit);

                    // referral bonus
                    $user->giveReferralBonus($deposit->amount);

                    // 30-day first-deposit bonus promo ($200 on first
                    // deposit >= $50 within 30 days of signup, once the
                    // account has been activated via fee or coupon)
                    giveFirstDepositBonus($user->fresh(), (float) $deposit->amount);

                    // 25% bonus on every crypto deposit > $100
                    giveDepositBonus(
                        $user->fresh(),
                        (float) $deposit->amount, // crypto deposit amount is already in USD
                        'usd',
                        (float) $deposit->amount,
                        'Crypto'
                    );
                }

                // if it's a REGISTRATION FEE
                if ($deposit->payment_type === 'reg_fee') {
                    creditSignupBonus($user);
                }

                return true;
            }

        } elseif ($action === 'reject') {

            $deposit->status = 'expired';
            $deposit->save();
            return true;
        }

        return false;
    }
}


// process deposit
// if (!function_exists('processDeposit')) {
//     function processDeposit($id, $action)
//     {
//         $deposit = Deposit::find($id);
//         if (!$deposit) {
//             return false;
//         }

//         if ($action == 'approve') {
//             $user_id = $deposit->user_id;

//             if ($deposit->status !== 'finished' && $deposit->status !== 'expired') {
//                 $deposit->status = 'finished';
//                 $deposit->save();

//                 if($deposit->payment_type !== 'reg_fee'){
//                     //credit the the user
//                     $user = User::where('id', $user_id)->first();
//                     $credit = User::find($user_id);
//                     $credit->balance = $user->balance + $deposit->amount;
//                     $credit->save();
              
            
//                     //recored new transaction
//                     $description = "new $deposit->currency deposit";
//                     recordNewTransaction($deposit->amount, $user_id, 'credit', $description);
//                     //send deposit email
//                     sendDepositConfirmedMail($deposit);
    
                
//                     //credit the referrer
//                     $user->giveReferralBonus($deposit->amount);
//                 }
                
                
//                 if($deposit->payment_type === 'reg_fee'){
//                     $user->fee_paid = 1;
//                     $user->save();
//                 }

//                 return true;
//             }
//         } elseif ($action == 'reject') {
//             $deposit->status = 'expired';
//             $deposit->save();
//             return true;
//         } else {
//             return false;
//         }
//     }
// }

//check if folder is writable [0775]
if (!function_exists('checkFolderPermission')) {
    function checkFolderPermission($folder)
    {
        $perm = substr(sprintf('%o', fileperms(base_path($folder))), -4);
        if ($perm >= '0775') {
            $response = true;
        } else {
            $response = false;
        }

        $resp = [
            'folder' => $folder,
            'status' => $response,
            'perm' => $perm
        ];
        return $resp;
    }
}

//format timestamp
if (!function_exists('formatTimestamp')) {
    function formatTimestamp($timestamp)
    {
        $currentTimestamp = time();
        $timeDifference = $timestamp - $currentTimestamp;

        if ($timeDifference < 0) {
            // The timestamp is in the past
            $timeDifference = abs($timeDifference);

            if ($timeDifference < 60) {
                return $timeDifference . ' seconds ago';
            } elseif ($timeDifference < 3600) {
                $minutes = floor($timeDifference / 60);
                return $minutes . ' minute' . ($minutes > 1 ? 's' : '') . ' ago';
            } elseif ($timeDifference < 86400) {
                $hours = floor($timeDifference / 3600);
                return $hours . ' hour' . ($hours > 1 ? 's' : '') . ' ago';
            } else {
                $days = floor($timeDifference / 86400);
                return $days . ' day' . ($days > 1 ? 's' : '') . ' ago';
            }
        } else {
            // The timestamp is in the future
            if ($timeDifference < 60) {
                return 'in ' . $timeDifference . ' seconds';
            } elseif ($timeDifference < 3600) {
                $minutes = floor($timeDifference / 60);
                return 'in ' . $minutes . ' minute' . ($minutes > 1 ? 's' : '');
            } elseif ($timeDifference < 86400) {
                $hours = floor($timeDifference / 3600);
                return 'in ' . $hours . ' hour' . ($hours > 1 ? 's' : '');
            } else {
                $days = floor($timeDifference / 86400);
                return 'in ' . $days . ' day' . ($days > 1 ? 's' : '');
            }
        }
    }
}

// demo mask
if (!function_exists('demoMask')) {
    function demoMask($string)
    {
        if (env('DEMO_MODE')) {
            return  Str::mask($string, '*', 3);
        } else {
            return $string;
        }
    }
}

if (!function_exists('compareDatesDesc')) {
    function compareDatesDesc($a, $b)
    {
        $dateA = strtotime($a);
        $dateB = strtotime($b);

        if ($dateA == $dateB) {
            return 0;
        }

        return ($dateA > $dateB) ? -1 : 1;
    }
}

// check if all cronjobs are running optimally
if (!function_exists('allJobsRunning')) {
    function allJobsRunning()
    {
        $cron_job = CronJob::orderBy('last_run', 'ASC')->first();
        $one_ago = now()->addHours(-1)->timestamp;
        if ($cron_job->last_run < $one_ago) {
            return false;
        }

        return true;
    }
}


// switch template
if (!function_exists('template')) {
    function template($path_to_blade_file)
    {
        // default exception would be thrown for missing theme
        if (site('template') == 'default') {
            return $path_to_blade_file;
        } else {

            return ('templates.' . site('template') . '.' . $path_to_blade_file);
        }
    }
}


// get templates
if (!function_exists('getTemplates')) {
    function getTemplates()
    {
        $path = resource_path('views/templates');
        $templates = array_map('basename', File::directories($path));
        array_push($templates, 'default');
        $templates = array_diff($templates, ['neo']);

        return $templates;
    }
}


/*
|--------------------------------------------------------------------------
| 30-Day Signup / First-Deposit Bonus Promotion
|--------------------------------------------------------------------------
|
| When a new user activates their account (by paying the $20 registration
| fee OR redeeming a coupon) they receive a $50 signup bonus. If they then
| make their first deposit of at least $50 within 30 days of signing up,
| they receive an additional $200 bonus. Both bonuses are credited to the
| user's withdrawable balance.
|
| Amounts are configurable via site() settings with sensible defaults:
|   - signup_bonus            (default 50)
|   - first_deposit_bonus     (default 200)
|   - first_deposit_bonus_min (default 50)
|   - first_deposit_bonus_days(default 30)
|
*/

if (!function_exists('creditSignupBonus')) {
    /**
     * Credit the $50 signup bonus to a newly activated user and mark their
     * account as fee-paid. Idempotent - safe to call multiple times, the
     * bonus will only ever be granted once per user.
     */
    function creditSignupBonus(\App\Models\User $user): bool
    {
        // already received the signup bonus
        if ($user->signup_bonus_at) {
            // still make sure the activation flag is on
            if (!$user->fee_paid) {
                $user->fee_paid = 1;
                $user->save();
            }
            return false;
        }

        // Use dedicated `signup_bonus` site setting if present, otherwise
        // default to $50. We intentionally do NOT fall back to
        // `welcome_bonus` because that is a separate (often much smaller)
        // promotion and was causing new users to receive the wrong amount.
        $configured = site('signup_bonus');
        $amount     = is_numeric($configured) && (float) $configured > 0
            ? (float) $configured
            : 50.0;

        try {
            \Illuminate\Support\Facades\DB::transaction(function () use ($user, $amount) {
                $user->fee_paid        = 1;
                $user->balance         = (float) $user->balance + $amount;
                $user->signup_bonus_at = now();
                $user->save();

                if ($amount > 0) {
                    recordNewTransaction($amount, $user->id, 'credit', 'Signup Bonus (Account Activation)');
                }
            });
        } catch (\Throwable $e) {
            \Illuminate\Support\Facades\Log::error('creditSignupBonus failed', [
                'user_id' => $user->id,
                'error'   => $e->getMessage(),
            ]);
            return false;
        }

        return true;
    }
}


if (!function_exists('giveFirstDepositBonus')) {
    /**
     * Credit the $200 first-deposit bonus to a user who:
     *   - has an activated account (fee_paid = 1)
     *   - is within the promo window (30 days from signup by default)
     *   - has just made their first qualifying deposit (>= $50 by default)
     *   - has not yet received this bonus
     *
     * Returns true if the bonus was credited, false otherwise.
     */
    function giveFirstDepositBonus(\App\Models\User $user, float $depositAmount): bool
    {
        if (!$user) {
            return false;
        }

        // Must have activated the account via fee or coupon
        if (!$user->fee_paid) {
            return false;
        }

        // One-time bonus
        if ($user->first_deposit_bonus_at) {
            return false;
        }

        $minDeposit = (float) (site('first_deposit_bonus_min') ?? 50);
        if ($depositAmount < $minDeposit) {
            return false;
        }

        // Must be within promo window (default 30 days from signup)
        $promoDays = (int) (site('first_deposit_bonus_days') ?? 30);
        if ($user->created_at && $user->created_at->copy()->addDays($promoDays)->isPast()) {
            return false;
        }

        // Only award on the FIRST qualifying deposit
        $previousDeposits = \App\Models\Deposit::where('user_id', $user->id)
            ->where('status', 'finished')
            ->where('payment_type', '!=', 'reg_fee')
            ->count();
        if ($previousDeposits > 1) {
            // More than the one we're processing now => not the first deposit
            return false;
        }

        $bonus = (float) (site('first_deposit_bonus') ?? 200);
        if ($bonus <= 0) {
            return false;
        }

        try {
            \Illuminate\Support\Facades\DB::transaction(function () use ($user, $bonus) {
                $user->balance                = (float) $user->balance + $bonus;
                $user->first_deposit_bonus_at = now();
                $user->save();

                recordNewTransaction($bonus, $user->id, 'credit', 'First Deposit Bonus (30-Day Promo)');
            });
        } catch (\Throwable $e) {
            \Illuminate\Support\Facades\Log::error('giveFirstDepositBonus failed', [
                'user_id' => $user->id,
                'error'   => $e->getMessage(),
            ]);
            return false;
        }

        \Illuminate\Support\Facades\Log::info('First deposit bonus credited', [
            'user_id'        => $user->id,
            'bonus'          => $bonus,
            'deposit_amount' => $depositAmount,
        ]);

        return true;
    }
}


if (!function_exists('giveDepositBonus')) {
    /**
     * Credit a 25% bonus on any deposit whose USD-equivalent value is
     * greater than $100. Works for crypto (USD), Flutterwave (USD/NGN/KES)
     * and SafeHaven (NGN) deposits.
     *
     * The bonus is credited in the SAME balance bucket as the deposit so
     * that the user sees it in the wallet they topped up.
     *
     * @param \App\Models\User $user           Recipient
     * @param float            $usdEquivalent  Deposit value converted to USD
     * @param string           $type           One of: 'usd', 'ngn', 'kes'
     * @param float            $nativeAmount   Original deposit amount in $type currency
     * @param string           $source         Free-text source label (e.g. "Crypto", "Flutterwave", "SafeHaven")
     *
     * @return bool true when the bonus was credited
     */
    function giveDepositBonus(
        \App\Models\User $user,
        float $usdEquivalent,
        string $type,
        float $nativeAmount,
        string $source = 'Deposit'
    ): bool {
        if (!$user || $usdEquivalent <= 100) {
            return false;
        }

        $percent = 0.25; // 25% bonus
        $bonusNative = round($nativeAmount * $percent, 2);
        $bonusUsd    = round($usdEquivalent * $percent, 2);

        if ($bonusNative <= 0) {
            return false;
        }

        try {
            \Illuminate\Support\Facades\DB::transaction(function () use ($user, $type, $bonusNative, $bonusUsd, $source) {
                switch (strtolower($type)) {
                    case 'ngn':
                        $user->ngn_balance = (float) $user->ngn_balance + $bonusNative;
                        break;
                    case 'kes':
                        $user->kes_balance = (float) $user->kes_balance + $bonusNative;
                        break;
                    case 'usd':
                    default:
                        $user->balance = (float) $user->balance + $bonusNative;
                        break;
                }
                $user->save();

                // record bonus transaction (USD-normalized for reporting consistency)
                recordNewTransaction(
                    $bonusUsd,
                    $user->id,
                    'credit',
                    "25% {$source} Deposit Bonus (Deposits > \$100)"
                );
            });
        } catch (\Throwable $e) {
            \Illuminate\Support\Facades\Log::error('giveDepositBonus failed', [
                'user_id' => $user->id,
                'type'    => $type,
                'error'   => $e->getMessage(),
            ]);
            return false;
        }

        \Illuminate\Support\Facades\Log::info('25% deposit bonus credited', [
            'user_id'        => $user->id,
            'source'         => $source,
            'type'           => $type,
            'native_bonus'   => $bonusNative,
            'usd_bonus'      => $bonusUsd,
            'usd_equivalent' => $usdEquivalent,
        ]);

        return true;
    }
}
