<?php

namespace App\Http\Controllers\Api\Admin;

use App\Http\Controllers\Controller;
use App\Models\AutoWallet;
use App\Models\User;
use App\Models\Withdrawal;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;

class WithdrawalApiController extends Controller
{
    // SafeHaven API Configuration
    private $baseUrlSafe = 'https://api.safehavenmfb.com';
    private $clientId = '523d581921dd49665d3aae522b8baa02';
    private $clientAssertion = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2FwaS5jYnJpbGxpYW5jZS5pbyIsInN1YiI6IjUyM2Q1ODE5MjFkZDQ5NjY1ZDNhYWU1MjJiOGJhYTAyIiwiYXVkIjoiaHR0cHM6Ly9hcGkuc2FmZWhhdmVubWZiLmNvbSIsImlhdCI6MTc2MDU3NDA1OSwiZXhwIjoxODYwNTczOTQ2fQ.qWoBQ4kv7hpOqnH9fkop-AE3Sbjg3PO8CQKBmvITvxMGa-ULRK8ZD0vGMIpbUFd35dZgwwWsTyzuc14TIfJdZ448zqnymDOhTKTE3o9GtGpFCZ8ewB3Tp1ju9eGEnPfmBFmSxbFGb9GvzuBeAxZv08xfMatsqlyaD4dfoOr3Hyo';

    /**
     * Get all withdrawals with pagination and filtering (matching original logic)
     */
    public function index(Request $request)
    {
        try {
            $withdrawal_query = Withdrawal::get();
            $summary = [
                'approved' => $withdrawal_query->where('status', 'approved')->sum('amount'),
                'rejected' => $withdrawal_query->where('status', 'rejected')->sum('amount'),
                'pending' => $withdrawal_query->where('status', 'pending')->sum('amount')
            ];

            if ($request->s) {
                $withdrawals = Withdrawal::with(['user', 'depositCoin'])->where('ref', 'LIKE', '%' . $request->s . '%')->orderBy('id', 'DESC')->paginate(10);
            } else {
                $withdrawals = Withdrawal::with(['user', 'depositCoin'])->orderBy('id', 'DESC')->paginate(10);
            }

            $balances = [];
            $balance_error = null;

            $api_key = env('NP_API_KEY');
            $response = Http::withHeaders([
                'x-api-key' => $api_key,
            ])->get('https://api.nowpayments.io/v1/balance');

            if (!$response->successful()) {
                $response = json_decode($response->body());
                $balance_error = $response->message ?? 'Failed to retrieve balance';
            } else {
                $balances = $response->json();
            }

            if ($request->w) {
                $auto_wallets = AutoWallet::with(['user', 'depositCoin'])->where('wallet_address', 'LIKE', '%' . $request->w . '%')->orderBy('id', 'DESC')->paginate(site('pagination'));
            } else {
                $auto_wallets = AutoWallet::with(['user', 'depositCoin'])->orderBy('id', 'DESC')->paginate(site('pagination'));
            }

            return response()->json([
                'status' => 'success',
                'data' => $withdrawals,
                'summary' => $summary,
                'balances' => $balances,
                'balance_error' => $balance_error,
                'auto_wallets' => $auto_wallets
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch withdrawals',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get specific withdrawal details (matching original viewWithdrawal)
     */
    public function show($id)
    {
        try {
            $withdrawal = Withdrawal::with('depositCoin')->where('id', $id)->first();
            if (!$withdrawal) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Withdrawal not found'
                ], 404);
            }

            $withdrawalData = [
                'amount' => $withdrawal->amount,
                'fee' => $withdrawal->fee,
                'currency' => $withdrawal->depositCoin->code,
                'converted_amount' => $withdrawal->converted_amount,
                'ref' => $withdrawal->ref,
                'network' => $withdrawal->depositCoin->network ?? $withdrawal->depositCoin->code,
                'payment_wallet' => $withdrawal->wallet_address,
                'status' => $withdrawal->status,
                'id' => $withdrawal->id
            ];

            return response()->json([
                'status' => 'success',
                'withdrawal' => $withdrawalData
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Withdrawal not found',
                'error' => $e->getMessage()
            ], 404);
        }
    }

    /**
     * Process withdrawal (approve/reject/delete - matching original logic)
     */
    public function process(Request $request, $id)
    {
        try {
            $request->validate([
                'action' => 'required'
            ]);

            $action = $request->action;
            $withdrawal = Withdrawal::find($id);
            if (!$withdrawal) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Withdrawal not found'
                ], 422);
            }

            $user = User::find($withdrawal->user->id);
            
             $totalDeposits = totalDeposits($user);
        
                if (!$totalDeposits) {
                    return response()->json([
                        'status' => 'error',
                        'message' => 'Your account is yet to reach the minimum capital of $300, kindly continue to grow your account or deposit to reach the threshold!'
                    ], 422);
                }

            if ($action == 'delete') {
                $withdrawal->delete();
                return response()->json([
                    'status' => 'success',
                    'message' => 'Withdrawal Deleted successfully'
                ]);
            } elseif ($action == 'approve') {
                // Check if this is a NGN withdrawal that requires SafeHaven transfer
                if ($withdrawal->currency == 'ngn' && $withdrawal->status == 'pending') {
                    try {
                        // Log user balance before approval
                        \Log::info('Withdrawal approval started', [
                            'withdrawal_id' => $withdrawal->id,
                            'user_id' => $user->id,
                            'withdrawal_amount' => $withdrawal->amount,
                            'user_ngn_balance_before' => $user->ngn_balance
                        ]);

                        // Process SafeHaven transfer
                        $result = $this->processSafeHavenTransfer($withdrawal);
                        
                        if (!$result['success']) {
                            return response()->json([
                                'status' => 'error',
                                'message' => $result['message']
                            ], 422);
                        }

                        // Update withdrawal with actual transfer details
                        $withdrawal->status = 'approved';
                        $withdrawal->amount_sent = $result['amount_sent'];
                        $withdrawal->net_amount = $result['net_amount'];
                        $withdrawal->fee = $result['total_fees'];
                        $withdrawal->save();

                        // Log successful approval
                        \Log::info('Withdrawal approved successfully', [
                            'withdrawal_id' => $withdrawal->id,
                            'user_id' => $user->id,
                            'amount_debited_from_user' => $withdrawal->amount,
                            'amount_sent_to_bank' => $result['amount_sent'],
                            'net_received_by_user' => $result['net_amount'],
                            'total_fees' => $result['total_fees'],
                            'user_ngn_balance_after' => $user->fresh()->ngn_balance
                        ]);

                        // Create notification for user
                        \App\Models\Notification::create([
                            'user_id' => $user->id,
                            'title' => 'Withdrawal Approved',
                            'message' => 'Your withdrawal of NGN ' . number_format($withdrawal->amount, 2) . ' has been approved. NGN ' . number_format($result['net_amount'], 2) . ' has been sent to your bank account. Fees: NGN ' . number_format($result['total_fees'], 2),
                            'status' => 0
                        ]);

                        sendWithdrawalEmail($withdrawal);
                        return response()->json([
                            'status' => 'success',
                            'message' => 'Withdrawal approved and funds transferred successfully via SafeHaven',
                            'data' => [
                                'amount_debited_from_user' => $withdrawal->amount,
                                'amount_sent_to_bank' => $result['amount_sent'],
                                'net_received_by_user' => $result['net_amount'],
                                'total_fees' => $result['total_fees'],
                                'breakdown' => [
                                    'user_paid' => $withdrawal->amount,
                                    'gateway_fee' => $result['gateway_fee'],
                                    'api_fee' => $result['api_fee'],
                                    'received_in_bank' => $result['net_amount']
                                ]
                            ]
                        ]);
                    } catch (\Exception $e) {
                        \Log::error('SafeHaven transfer failed during approval', [
                            'withdrawal_id' => $withdrawal->id,
                            'error' => $e->getMessage(),
                            'trace' => $e->getTraceAsString()
                        ]);
                        return response()->json([
                            'status' => 'error',
                            'message' => 'Failed to process SafeHaven transfer: ' . $e->getMessage()
                        ], 422);
                    }
                } else {
                    // Regular approval for non-NGN or already processed withdrawals
                    $withdrawal->status = 'approved';
                    $withdrawal->save();

                    sendWithdrawalEmail($withdrawal);
                    return response()->json([
                        'status' => 'success',
                        'message' => 'Withdrawal request was approved'
                    ]);
                }
            } elseif ($action == 'reject') {
                $withdrawal->status = 'rejected';
                $withdrawal->save();

                // Credit the user back based on currency
                if ($withdrawal->currency == 'ngn') {
                    $new_balance = $user->ngn_balance + $withdrawal->amount;
                    $user->ngn_balance = $new_balance;
                } else {
                    $new_balance = $user->balance + $withdrawal->amount;
                    $user->balance = $new_balance;
                }
                $user->save();
                
                recordNewTransaction($withdrawal->amount, $user->id, 'credit', 'Withdrawal refunded', $withdrawal->currency);
                sendWithdrawalEmail($withdrawal);
                // send email
                return response()->json([
                    'status' => 'success',
                    'message' => 'Withdrawal request was declined and funds refunded'
                ]);
            }

            return response()->json([
                'status' => 'error',
                'message' => 'Unknown action'
            ], 422);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to process withdrawal',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Update withdrawal details
     */
    public function update(Request $request, $id)
    {
        try {
            $withdrawal = Withdrawal::findOrFail($id);

            $validator = Validator::make($request->all(), [
                'amount' => 'sometimes|numeric|min:0.01',
                'wallet_address' => 'sometimes|string|max:255',
                'method' => 'sometimes|string|max:100',
                'admin_note' => 'nullable|string|max:1000'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Validation failed',
                    'errors' => $validator->errors()
                ], 422);
            }

            if ($withdrawal->status !== 'pending') {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Only pending withdrawals can be modified'
                ], 400);
            }

            $withdrawal->update($validator->validated());

            return response()->json([
                'status' => 'success',
                'message' => 'Withdrawal updated successfully',
                'data' => $withdrawal
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to update withdrawal',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Delete withdrawal
     */
    public function destroy($id)
    {
        try {
            $withdrawal = Withdrawal::findOrFail($id);
            
            if ($withdrawal->status === 'approved') {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Cannot delete approved withdrawals'
                ], 400);
            }

            // If pending, refund the amount
            if ($withdrawal->status === 'pending') {
                $walletType = $withdrawal->wallet_type ?? 'deposit_wallet';
                $withdrawal->user->increment($walletType, $withdrawal->amount);
            }

            $withdrawal->delete();

            return response()->json([
                'status' => 'success',
                'message' => 'Withdrawal deleted successfully'
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to delete withdrawal',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get withdrawal wallets
     */
    public function wallets(Request $request)
    {
        try {
            $query = WithdrawalWallet::with('user');

            // Filter by user
            if ($request->has('user_id')) {
                $query->where('user_id', $request->user_id);
            }

            // Filter by currency
            if ($request->has('currency')) {
                $query->where('currency', $request->currency);
            }

            $perPage = $request->per_page ?? 15;
            $wallets = $query->orderBy('created_at', 'desc')->paginate($perPage);

            return response()->json([
                'status' => 'success',
                'data' => $wallets
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch withdrawal wallets',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Delete auto wallets (matching original deleteWallet)
     */
    public function deleteWallet($id)
    {
        try {
            $wallet = AutoWallet::find($id);
            if ($wallet) {
                $wallet->delete();
                return response()->json([
                    'status' => 'success',
                    'message' => 'Wallet Deleted successfully'
                ]);
            } else {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Failed to delete wallet'
                ], 422);
            }
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to delete withdrawal wallet',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get withdrawal statistics
     */
    public function statistics(Request $request)
    {
        try {
            $period = $request->period ?? 'all'; // today, week, month, year, all
            
            $query = Withdrawal::query();
            
            switch ($period) {
                case 'today':
                    $query->whereDate('created_at', today());
                    break;
                case 'week':
                    $query->whereBetween('created_at', [now()->startOfWeek(), now()->endOfWeek()]);
                    break;
                case 'month':
                    $query->whereMonth('created_at', now()->month);
                    break;
                case 'year':
                    $query->whereYear('created_at', now()->year);
                    break;
            }

            $stats = [
                'total_withdrawals' => $query->count(),
                'total_amount' => $query->sum('amount'),
                'pending_withdrawals' => $query->where('status', 'pending')->count(),
                'pending_amount' => $query->where('status', 'pending')->sum('amount'),
                'approved_withdrawals' => $query->where('status', 'approved')->count(),
                'approved_amount' => $query->where('status', 'approved')->sum('amount'),
                'rejected_withdrawals' => $query->where('status', 'rejected')->count(),
                'rejected_amount' => $query->where('status', 'rejected')->sum('amount'),
                'average_withdrawal' => $query->avg('amount'),
                'methods' => Withdrawal::selectRaw('method, COUNT(*) as count, SUM(amount) as total_amount')
                                      ->groupBy('method')
                                      ->get(),
            ];

            return response()->json([
                'status' => 'success',
                'data' => $stats,
                'period' => $period
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch withdrawal statistics',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Bulk process withdrawals
     */
    public function bulkProcess(Request $request)
    {
        try {
            $validator = Validator::make($request->all(), [
                'action' => 'required|in:approve,reject',
                'withdrawal_ids' => 'required|array',
                'withdrawal_ids.*' => 'exists:withdrawals,id',
                'reason' => 'nullable|string|max:500'
            ]);

            if ($validator->fails()) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Validation failed',
                    'errors' => $validator->errors()
                ], 422);
            }

            $withdrawalIds = $request->withdrawal_ids;
            $action = $request->action;
            $processedCount = 0;

            $withdrawals = Withdrawal::whereIn('id', $withdrawalIds)
                                   ->where('status', 'pending')
                                   ->get();

            foreach ($withdrawals as $withdrawal) {
                if ($action === 'approve') {
                    $withdrawal->update([
                        'status' => 'approved',
                        'processed_at' => now(),
                        'admin_note' => 'Bulk approved'
                    ]);

                    // Create transaction record
                    \App\Models\Transaction::create([
                        'user_id' => $withdrawal->user_id,
                        'type' => 'debit',
                        'amount' => $withdrawal->amount,
                        'description' => 'Withdrawal approved - ' . $withdrawal->reference,
                        'wallet' => $withdrawal->wallet_type ?? 'deposit_wallet',
                        'balance_after' => $withdrawal->user->deposit_wallet,
                        'reference' => $withdrawal->reference,
                        'status' => 'completed'
                    ]);
                } else {
                    $walletType = $withdrawal->wallet_type ?? 'deposit_wallet';
                    $withdrawal->user->increment($walletType, $withdrawal->amount);
                    
                    $withdrawal->update([
                        'status' => 'rejected',
                        'processed_at' => now(),
                        'admin_note' => 'Bulk rejected',
                        'rejection_reason' => $request->reason
                    ]);

                    // Create refund transaction record
                    \App\Models\Transaction::create([
                        'user_id' => $withdrawal->user_id,
                        'type' => 'credit',
                        'amount' => $withdrawal->amount,
                        'description' => 'Withdrawal rejected - Refund: ' . $withdrawal->reference,
                        'wallet' => $walletType,
                        'balance_after' => $withdrawal->user->$walletType,
                        'reference' => 'REF-' . $withdrawal->reference,
                        'status' => 'completed'
                    ]);
                }
                $processedCount++;
            }

            return response()->json([
                'status' => 'success',
                'message' => "Bulk {$action} completed successfully",
                'processed_count' => $processedCount
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to perform bulk process',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Process SafeHaven transfer for approved NGN withdrawal
     */
    private function processSafeHavenTransfer(Withdrawal $withdrawal)
    {
        // Get SafeHaven token
        $token = $this->requestSafeHavenToken();
        if (!$token) {
            return [
                'success' => false,
                'message' => 'Unable to fetch SafeHaven authentication token'
            ];
        }

        $gatewayFee = 3200; // NGN
        $transferAttemptAmount = $withdrawal->amount - $gatewayFee;

        if ($transferAttemptAmount <= 0) {
            return [
                'success' => false,
                'message' => 'Amount too small to cover gateway fee'
            ];
        }

        // Prepare transfer payload
        // Send the transfer amount (after gateway fee), not the full amount debited from user
        $payload = [
            'nameEnquiryReference'     => $withdrawal->enquiry_reference,
            'debitAccountNumber'       => '0119318661',
            'beneficiaryBankCode'      => $withdrawal->bank_code,
            'beneficiaryAccountNumber' => $withdrawal->wallet_address,
            'amount'                   => (float) round($transferAttemptAmount, 2), // Transfer amount after gateway fee
            'saveBeneficiary'          => false,
            'narration'                => 'Withdrawal - ' . $withdrawal->ref,
            'paymentReference'         => $withdrawal->ref,
        ];

        // Make transfer request
        $response = $this->makeSafeHavenRequest('POST', '/transfers', $token, $payload);
        $body = $response->json();

        if (!isset($body['data']['fees'])) {
            $errMsg = $body['message'] ?? 'SafeHaven transfer failed';
            return [
                'success' => false,
                'message' => $errMsg
            ];
        }

        // SafeHaven fee
        $apiFee = (float) $body['data']['fees'];

        // Ensure the API fee doesn't consume the whole transfer amount
        if ($apiFee >= $transferAttemptAmount) {
            return [
                'success' => false,
                'message' => 'Transfer fees are greater than or equal to the transferable amount'
            ];
        }

        // Calculate net amount received by beneficiary
        $netToBeneficiary = $transferAttemptAmount - $apiFee;
        $totalFees = $apiFee + $gatewayFee;

        return [
            'success' => true,
            'amount_sent' => $transferAttemptAmount,
            'net_amount' => $netToBeneficiary,
            'total_fees' => $totalFees,
            'api_fee' => $apiFee,
            'gateway_fee' => $gatewayFee
        ];
    }

    /**
     * Request SafeHaven OAuth token
     */
    private function requestSafeHavenToken()
    {
        $payload = [
            'grant_type' => 'client_credentials',
            'client_assertion_type' => 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
            'client_id' => $this->clientId,
            'client_assertion' => $this->clientAssertion
        ];
    
        $response = $this->makeSafeHavenRequest('POST', '/oauth2/token', null, $payload);
    
        return $response->successful()
            ? $response->json('access_token')
            : null;
    }

    /**
     * Make SafeHaven API request
     */
    private function makeSafeHavenRequest(string $method, string $endpoint, ?string $token = null, array $data = [])
    {
        $url = $this->baseUrlSafe . $endpoint;

        $headers = [
            'Accept' => 'application/json',
            'Content-Type' => 'application/json',
            'ClientID' => $this->clientId,
        ];

        if ($token) {
            $headers['Authorization'] = 'Bearer ' . $token;
        }

        $http = Http::withHeaders($headers)
            ->timeout(60)
            ->retry(3, 1000);

        // Only disable SSL verification in development
        if (config('app.env') !== 'production') {
            $http = $http->withOptions([
                'verify' => false,
                'curl' => [
                    CURLOPT_SSL_VERIFYPEER => false,
                    CURLOPT_SSL_VERIFYHOST => false,
                ]
            ]);
        }

        $method = strtoupper($method);

        try {
            switch ($method) {
                case 'POST':
                    return $http->post($url, $data);
                case 'PUT':
                    return $http->put($url, $data);
                case 'PATCH':
                    return $http->patch($url, $data);
                case 'DELETE':
                    return $http->delete($url, $data);
                default:
                    return $http->get($url, ['query' => $data]);
            }
        } catch (\Exception $e) {
            \Log::error('SafeHaven API request failed', [
                'method' => $method,
                'url' => $url,
                'error' => $e->getMessage()
            ]);
            throw $e;
        }
    }
}