<?php

namespace App\Http\Controllers\User;

use App\Http\Controllers\Controller;
use App\Models\Deposit;
use App\Models\DepositCoin;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\File;

class DepositController extends Controller
{
    
    
    public function callback(Request $request)
    {
    try {
        // Get raw JSON body
        $callbackResponse = $request->getContent();

        // Save raw response to a file in storage/app/
        $logFile = storage_path('app/safehaven_callback.json');
        File::append($logFile, $callbackResponse . PHP_EOL);

        // Decode the JSON payload
        $payload = json_decode($callbackResponse, true);

        // Log decoded payload
        Log::info('SafeHaven Callback Received', ['payload' => $payload]);

        // Extract customer and payment data
        $customer = $payload['data']['customer'] ?? null;
        $status = $payload['data']['status'] ?? null;
        $amount = (float) ($payload['data']['amount'] ?? 0);
        $referenceCode = $payload['data']['referenceCode'] ?? '';

        if (!$customer || $status !== 'Paid' || $amount <= 0) {
            Log::warning('Invalid callback or unpaid status.');
            return response()->json(['status' => 'ignored'], 200);
        }

        $email = $customer['emailAddress'] ?? null;
        $phone = $customer['phoneNumber'] ?? null;

        // Find the user
        $user = User::where('email', $email)->first();

        if (!$user) {
            Log::error('User not found for SafeHaven callback', ['email' => $email, 'phone' => $phone]);
            return response()->json(['status' => 'user_not_found'], 404);
        }
        
        
        // Check if this is REGFEE
        $isRegFee = str_contains($referenceCode, 'REGFEE');
        
        $isCbcPurchase = str_contains($referenceCode, 'CBC-SAFE');
        
        // Mark registration fee as paid
        if ($isRegFee) {
            creditSignupBonus($user);

            // Upline bonus (always runs)
            if ($user->referred_by) {
                $upline = User::where('username', $user->referred_by)->first();
                if ($upline) {
                    $upline->ngn_balance += 7200;
                    $upline->save();
                }
            }
        
        } else {
            // Normal deposit increases balance
            
            if (!str_contains($referenceCode, 'CBC-SAFE')) {
                $user->ngn_balance += $amount;
                $user->save();
                
                $user->giveReferralBonusNGN($amount);

                // 30-day first-deposit bonus promo - convert NGN amount to USD
                // using the same 1550 rate used elsewhere in this file.
                $usdEquivalent = $amount / 1550;
                giveFirstDepositBonus($user->fresh(), (float) $usdEquivalent);

                // 25% bonus on SafeHaven (NGN) deposits whose USD value > $100
                if ($usdEquivalent > 100) {
                    giveDepositBonus(
                        $user->fresh(),
                        (float) $usdEquivalent,
                        'ngn',
                        (float) $amount, // credit bonus in NGN to ngn_balance
                        'SafeHaven'
                    );
                }
            }
            
            
            
            
        }
        
        
        
        if ($isCbcPurchase) {
            $user->cbc_balance += $amount/1550;
            $user->save();
        }
        
        

        // Update user balance
        // $user->ngn_balance += $amount;
        // $user->fee_paid = 1;
        // $user->save();
        
        $deposit = new Deposit();
        $deposit->user_id = $user->id;
        $deposit->amount = $amount;
        $deposit->fee = 0;
        $deposit->currency = 'USDTBSC';
        $deposit->type = 'ngn';
        $deposit->converted_amount = $amount/1550;
        $deposit->ref = mt_rand(1000,99099934);
        $deposit->network = 'trx';
        $deposit->valid_until = "2025-04-25T18:16:33.384Z";
        $deposit->payment_id = mt_rand(1000,99099934);
        $deposit->payment_wallet = "0xCe9924E4E2163e6A237276C386EC77e052ECdC21";
        $deposit->status = 'finished';
        $deposit->deposit_coin_id = 219;
        $deposit->save();
        
        
        sendDepositConfirmedMail($deposit);
        
        


        // Create transaction
        // $transaction = new Transaction();
        // $transaction->user_id = $user->id;
        // $transaction->currency_id = 2;
        // $transaction->amount = $amount;
        // $transaction->charge = 0;
        // $transaction->trx_type = "+";
        // $transaction->remarks = "Deposit via SafeHaven";
        // $transaction->trx_id = strtoupper(uniqid('SH_', true));
        // $transaction->save();

        Log::info('Deposit added to user', ['amount' => $amount, 'user' => $user->id]);

        return response()->json(['status' => 'success'], 200);
    } catch (\Exception $e) {
        Log::error('SafeHaven Callback Error', ['message' => $e->getMessage()]);
        return response()->json(['status' => 'error', 'message' => 'Callback processing failed'], 500);
    }
}




    //index of all deposits
    public function index(Request $request)
    {
        $page_title = 'My Deposits';

        if ($request->s) {
            $deposits = user()
                ->deposits()
                ->with('depositCoin')
                ->where('ref', 'LIKE', '%' . $request->s . '%')
                ->orderBy('id', 'DESC')
                ->paginate(site('pagination'));
        } else {
            $deposits = user()
                ->deposits()
                ->with('depositCoin')
                ->orderBy('id', 'DESC')
                ->paginate(site('pagination'));
        }


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

        return view(template('user.deposits.index'), compact(
            'page_title',
            'deposits',
            'coins'
        ));
    }


    //show only a single deposit
    public function deposit(Request $request)
    {
        $deposit = user()->deposits()->where('ref', $request->route('ref'))->first();
        if (!$deposit) {
            abort(404);
        }


        $depositData = [
            'amount' => $deposit->amount,
            'fee' => $deposit->fee,
            'currency' => $deposit->currency,
            'converted_amount' => $deposit->converted_amount,
            'ref' => $deposit->ref,
            'network' => $deposit->network,
            'valid_until' => $deposit->valid_until,
            'payment_id' => $deposit->payment_id,
            'payment_wallet' => $deposit->payment_wallet,
            'status' => $deposit->status,
        ];

        return response()->json(['deposit' => $depositData]);
    }


    //new deposit 
    public function newDeposit(Request $request, User $authUser = null)
    {
        $user = $authUser ?: user();
        
        if (!$user) {
            Log::error('User authentication failed in newDeposit');
            return response()->json(validationError('User not authenticated'), 401);
        }
        
        Log::info('newDeposit method called', [
            'user_id' => $user->id,
            'user_type' => get_class($user),
            'auth_user_provided' => $authUser ? true : false
        ]);

        $request->validate([
            'amount' => 'required|numeric',
            'currency_code' => 'required',
        ]);
        
       


        //check min and max
        $amount_before_fee = $request->amount;
        $currency = $request->currency_code;
        $fee = site('deposit_fee') / 100 * $amount_before_fee;
        $amount = $fee + $amount_before_fee;
        if ($amount_before_fee < site('min_deposit') || $amount_before_fee > site('max_deposit')) {
            return response()->json(validationError('Min or max deposit amount not met'), 422);
        }

        $coin = DepositCoin::where('code', $currency)->where('status', 1)->first();
        
        Log::info('Coin lookup result', [
            'currency' => $currency,
            'coin_found' => $coin ? true : false,
            'coin_id' => $coin ? $coin->id : 'null'
        ]);
        
        if (!$coin) {
            // Log the available currencies for debugging
            $availableCurrencies = DepositCoin::where('status', 1)->pluck('code')->toArray();
            Log::error('Invalid currency code provided', [
                'requested_currency' => $currency,
                'available_currencies' => $availableCurrencies
            ]);
            
            return response()->json(validationError('The Payment method you have selected is not allowed. Available methods: ' . implode(', ', $availableCurrencies)), 422);
        }

        $coin_id = $coin->id;
        
        Log::info('Coin ID assigned', ['coin_id' => $coin_id]);

        // wallet address
        $rand_wallet = null;
        $processor = site('payment_processor') ?? 'nowpayment';
        // return response()->json(validationError($processor), 422);
        if ($processor == 'manual' && !$coin->wallet_address) {
            return response()->json(validationError('Manual Wallet address not configured'), 422); 
        } 
        if ($coin->wallet_address && $processor == 'manual') {
            $wallet_address = json_decode($coin->wallet_address) ?? [];
            $wallet_address = array_filter($wallet_address, function ($value) {
                return $value !== null;
            });
            $wallet_address = array_values($wallet_address);


            $wallet_count = count($wallet_address);

            if ($wallet_count < 2) {
                $wallet_index = 0;
            } else {
                $wallet_index = rand(0, $wallet_count - 1);
            }

            shuffle($wallet_address);
            $rand_wallet = $wallet_address[$wallet_index] ?? null;
        }
        
         



        //initiate deposit


        $start = initiateDeposit($amount, $currency, $processor,  $rand_wallet, $request->origin);

        if (!$start) {
            return response()->json(validationError('Error initiating deposit'), 422);
        }
        
        // Log the raw response for debugging
        Log::info('Raw deposit response', ['response' => $start]);

        $details = json_decode($start);
        
        // return response()->json($details);

        // Check if JSON decoding was successful
        if (!$details) {
            Log::error('Failed to decode deposit response', [
                'raw_response' => $start,
                'json_error' => json_last_error_msg()
            ]);
            return response()->json(validationError('Invalid response from payment processor'), 422);
        }

        // Check if required fields exist
        $required_fields = ['payment_id', 'order_id', 'payment_status'];
        $missing_fields = [];
        
        foreach ($required_fields as $field) {
            if (!isset($details->$field)) {
                $missing_fields[] = $field;
            }
        }
        
        if (!empty($missing_fields)) {
            Log::error('Missing required fields in deposit response', [
                'missing_fields' => $missing_fields,
                'available_fields' => array_keys(get_object_vars($details)),
                'response' => $details
            ]);
            return response()->json(validationError('Invalid payment data received - missing: ' . implode(', ', $missing_fields)), 422);
        }
        
        // Check for payment amount field (can be pay_amount or price_amount)
        if (!isset($details->pay_amount) && !isset($details->price_amount)) {
            Log::error('No payment amount field found in response', [
                'available_fields' => array_keys(get_object_vars($details))
            ]);
            return response()->json(validationError('Invalid payment data - no amount field'), 422);
        }
        
        // Check for payment address field
        if (!isset($details->pay_address) && !isset($details->payment_address)) {
            Log::error('No payment address field found in response', [
                'available_fields' => array_keys(get_object_vars($details))
            ]);
            return response()->json(validationError('Invalid payment data - no payment address'), 422);
        }

        $deposit = new Deposit();
        $deposit->user_id = $user->id;
        $deposit->payment_type = $request->payment_type ?? 'deposit';
        $deposit->amount = $amount_before_fee;
        $deposit->type = $request->type;
        $deposit->fee = $fee;
        $deposit->currency = $currency;
        $deposit->converted_amount = $details->pay_amount ?? $details->price_amount ?? 0;
        $deposit->ref = $details->order_id;
        $deposit->network = $details->network ?? 'unknown';
        $deposit->valid_until = $details->valid_until ?? $details->expiration_estimate_date ?? null;
        $deposit->payment_id = $details->payment_id;
        $deposit->payment_wallet = $details->pay_address ?? $details->payment_address ?? null;
        $deposit->status = $details->payment_status ?? 'waiting';
        $deposit->deposit_coin_id = $coin_id;
        
        Log::info('About to save deposit', [
            'user_id' => $deposit->user_id,
            'amount' => $deposit->amount,
            'currency' => $deposit->currency,
            'deposit_coin_id' => $deposit->deposit_coin_id,
            'payment_id' => $deposit->payment_id
        ]);
        
        $deposit->save();
        
        Log::info('Deposit saved successfully', [
            'deposit_id' => $deposit->id ?? 'null',
            'saved' => $deposit->exists
        ]);

        $depositData = [
            'amount' => (string) $deposit->amount,
            'fee' => (string) $deposit->fee,
            'currency' => $deposit->currency,
            'converted_amount' => (string) $deposit->converted_amount,
            'ref' => $deposit->ref,
            'network' => $deposit->network,
            'valid_until' => $deposit->valid_until,
            'payment_id' => (string) $deposit->payment_id,
            'payment_wallet' => $deposit->payment_wallet,
            'status' => $deposit->status,
        ];

        return response()->json(['deposit' => $depositData]);
    }




    public function depositCallback()
    {
        return depositCallback();
    }

    public function depositCallbackCoinpayment()
    {
        return depositCallbackCoinpayment();
    }

    /**
     * Get available deposit methods
     */
    public function getAvailableMethods()
    {
        $coins = DepositCoin::where('status', 1)
            ->select('id', 'code', 'name', 'logo_url', 'network', 'precision', 'ticker')
            ->orderBy('priority', 'asc')
            ->get();

        $limits = [
            'min_deposit' => (float) site('min_deposit'),
            'max_deposit' => (float) site('max_deposit'),
            'deposit_fee' => (float) site('deposit_fee'),
            'currency' => site('currency'),
            'payment_processor' => site('payment_processor')
        ];

        return response()->json([
            'status' => 'success',
            'data' => [
                'available_methods' => $coins,
                'limits' => $limits
            ]
        ]);
    }
}
