<?php

namespace App\Http\Controllers\Api\User;

use App\Http\Controllers\Controller;
use App\Http\Controllers\User\DepositController;
use App\Models\Deposit;
use App\Models\User;
use App\Models\DepositCoin;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use App\Models\Notification;
use Illuminate\Support\Facades\File;
use Carbon\Carbon;

class DepositApiController extends Controller
{
    protected $depositController;

    public function __construct()
    {
        $this->depositController = new DepositController();
    }
    
    // flutterwave callback
    public function flutterwaveCallback(Request $request)
    {
        // Get raw JSON body
        $callbackResponse = $request->getContent();
    
        // Persist raw payload for auditing
        File::append(
            storage_path('app/flutterwave_callback.json'),
            $callbackResponse . PHP_EOL
        );
    
        $payload = json_decode($callbackResponse, true);
    
        Log::info('Flutterwave Callback Received', $payload);
    
        // Validate event
        if (
            ($payload['event'] ?? null) !== 'charge.completed' ||
            ($payload['data']['status'] ?? null) !== 'successful'
        ) {
            Log::warning('Ignored Flutterwave callback', $payload);
            return response()->json(['status' => 'ignored'], 200);
        }
    
        // Extract payment details
        $data = $payload['data'];
        $meta = $payload['meta_data'] ?? [];
    
        $trxID     = $data['id'];
        $txRef     = $data['tx_ref'];
        $flwRef    = $data['flw_ref'];
        $amount    = (float) $data['amount'];
        $currency  = strtoupper($data['currency'] ?? '');
    
        // Customer details
        $customer = $data['customer'] ?? [];
        $email    = $customer['email'] ?? null;
    
        if (!$email || $amount <= 0 || !$currency) {
            Log::error('Invalid Flutterwave payload', $payload);
            return response()->json(['status' => 'invalid'], 422);
        }
    
        // Find user
        $user = User::where('email', $email)->first();
    
        if (!$user) {
            Log::error('User not found for Flutterwave payment', [
                'email' => $email,
                'tx_ref' => $txRef
            ]);
            return response()->json(['status' => 'user_not_found'], 404);
        }
    
        // Prevent duplicate processing
        if (Deposit::where('payment_id', $flwRef)->exists()) {
            Log::info('Duplicate Flutterwave callback ignored', [
                'flw_ref' => $flwRef
            ]);
            return response()->json(['status' => 'duplicate'], 200);
        }
    
        /**
         * REGISTRATION FEE LOGIC
         */
        if (str_contains($txRef, 'REGFEE')) {
    
            creditSignupBonus($user);
    
            // Upline bonus
            if ($user->referred_by) {
                $upline = User::where('username', $user->referred_by)->first();
                if ($upline) {
                    $upline->ngn_balance += 7200;
                    $upline->save();
                }
            }
    
            $depositType = 'ngn';
    
        } else {
    
            /**
             * NORMAL DEPOSIT LOGIC (MULTI-CURRENCY)
             */
             
            switch ($currency) {
                case 'USD':
                    $user->balance += $amount;
                    $depositType = 'usd';
                    break;
    
                case 'KES':
                    $user->kes_balance += $amount;
                    $depositType = 'kes';
                    break;
    
                case 'NGN':
                default:
                    $user->ngn_balance += $amount;
                    $depositType = 'ngn';
                    break;
            }
            
            if (!str_contains($txRef, 'CBC-FLW')) {
                $user->save();
            }
        }
        
        
        
        if (str_contains($txRef, 'CBC-FLW')) {
    
            $user->cbc_balance += $amount/1550;
            $user->save();
    
            $depositType = 'ngn';
    
        }
    
        /**
         * RECORD DEPOSIT
         */
        $deposit = new Deposit();
        $deposit->user_id = $user->id;
        $deposit->amount = $amount;
        $deposit->payment_type = 'deposit';
        $deposit->fee = $data['app_fee'] ?? 0;
        $deposit->currency = $currency;
        $deposit->type = $depositType;
        $deposit->converted_amount = match ($currency) {
            'USD' => $amount,
            'KES' => $amount / 150,
            default => $amount / 1550, // NGN
        };
        $deposit->ref = $txRef;
        $deposit->network = 'flutterwave';
        $deposit->payment_id = $flwRef;
        $deposit->payment_wallet = $trxID ?? mt_rand(10000,9999999999999);
        $deposit->status = 'finished';
        $deposit->deposit_coin_id = 219;
        $deposit->valid_until = Carbon::now()->addYears(5);
        $deposit->save();
    
        sendDepositConfirmedMail($deposit);

        // 30-day first-deposit bonus promo ($200) - only on normal deposits
        if (!str_contains($txRef, 'REGFEE')) {
            giveFirstDepositBonus($user->fresh(), (float) $deposit->converted_amount);
        }

        // 25% deposit bonus on every Flutterwave deposit > $100 (USD-equivalent)
        // Excludes registration fee and CBC token purchases.
        if (
            !str_contains($txRef, 'REGFEE') &&
            !str_contains($txRef, 'CBC-FLW') &&
            (float) $deposit->converted_amount > 100
        ) {
            giveDepositBonus(
                $user->fresh(),
                (float) $deposit->converted_amount,
                $depositType,    // 'usd' | 'ngn' | 'kes'
                (float) $amount, // bonus credited in the original currency
                'Flutterwave'
            );
        }        Log::info('Flutterwave deposit processed successfully', [
            'user_id' => $user->id,
            'currency' => $currency,
            'amount' => $amount,
            'tx_ref' => $txRef
        ]);
    
        return response()->json(['status' => 'success'], 200);
    }

    
    
    
    

    /**
     * Get user deposits with search and filter options
     * @param Request $request
     * @return JsonResponse
     */
    public function index(Request $request): JsonResponse
    {
        try {
            $user = auth()->user();
            $query = $user->deposits()->with('depositCoin');

            // Search by transaction reference
            if ($request->has('search') && !empty($request->search)) {
                $query->where('ref', 'LIKE', '%' . $request->search . '%');
            }

            // Filter by status
            if ($request->has('status') && !empty($request->status)) {
                $query->where('status', $request->status);
            }

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

            // Filter by date range
            if ($request->has('from_date') && !empty($request->from_date)) {
                $query->whereDate('created_at', '>=', $request->from_date);
            }

            if ($request->has('to_date') && !empty($request->to_date)) {
                $query->whereDate('created_at', '<=', $request->to_date);
            }

            $deposits = $query->orderBy('id', 'DESC')->get();

            return response()->json([
                'status' => 'success',
                'data' => [
                    'deposits' => $deposits,
                    'summary' => [
                        'total_deposits' => $user->deposits()->count(),
                        'total_amount' => $user->deposits()->where('status', 'finished')->sum('amount'),
                        'pending_deposits' => $user->deposits()->whereIn('status', ['waiting', 'confirming'])->count(),
                        'completed_deposits' => $user->deposits()->where('status', 'finished')->count(),
                    ]
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch deposits',
                'error' => $e->getMessage()
            ], 500);
        }
    }

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

            return response()->json([
                'status' => 'success',
                'data' => [
                    'deposit_methods' => $coins,
                    'limits' => [
                        'min_deposit' => (float) site('min_deposit'),
                        'max_deposit' => (float) site('max_deposit'),
                        'deposit_fee' => (float) site('deposit_fee'),
                        'currency' => site('currency')
                    ]
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch deposit methods',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get deposit statistics
     * @return JsonResponse
     */
    public function getStatistics(): JsonResponse
    {
        try {
            $user = auth()->user();
            
            $stats = [
                'total_deposits' => $user->deposits()->count(),
                'total_amount' => $user->deposits()->where('status', 'finished')->sum('amount'),
                'pending_amount' => $user->deposits()->whereIn('status', ['waiting', 'confirming'])->sum('amount'),
                'completed_deposits' => $user->deposits()->where('status', 'finished')->count(),
                'pending_deposits' => $user->deposits()->whereIn('status', ['waiting', 'confirming'])->count(),
                'failed_deposits' => $user->deposits()->whereIn('status', ['expired', 'rejected'])->count(),
                'this_month_deposits' => $user->deposits()
                    ->where('status', 'finished')
                    ->whereMonth('created_at', now()->month)
                    ->whereYear('created_at', now()->year)
                    ->sum('amount'),
                'last_deposit' => $user->deposits()
                    ->with('depositCoin')
                    ->latest()
                    ->first(),
                'currency_breakdown' => $user->deposits()
                    ->where('status', 'finished')
                    ->select('currency', DB::raw('SUM(amount) as total_amount'), DB::raw('COUNT(*) as count'))
                    ->groupBy('currency')
                    ->get()
            ];

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

    /**
     * Check deposit status by reference
     * @param string $ref
     * @return JsonResponse
     */
    public function checkStatus($ref): JsonResponse
    {
        try {
            $user = auth()->user();

            $deposit = $user->deposits()
                ->with('depositCoin')
                ->where('ref', $ref)
                ->first();

            if (!$deposit) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Deposit not found'
                ], 404);
            }

            return response()->json([
                'status' => 'success',
                'data' => [
                    'deposit' => $deposit,
                    'is_expired' => now()->gt($deposit->valid_until),
                    'time_remaining' => now()->lt($deposit->valid_until) ? 
                        now()->diffInSeconds($deposit->valid_until) : 0
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to check deposit status',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Create new deposit
     * @param Request $request
     * @return JsonResponse
     */
    public function store(Request $request): JsonResponse
    {
        try {
            // Validate request
            $request->validate([
                'amount' => 'required|numeric|min:0.01',
                'currency_code' => 'required|string',
                'payment_type' => 'nullable',
                'type' => 'nullable',
                'origin' => 'nullable',
            ]);

            // Get authenticated user
            $user = auth()->user();
            if (!$user) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'User not authenticated'
                ], 401);
            }

            Log::info('API Deposit creation attempt', [
                'user_id' => $user->id,
                'amount' => $request->amount,
                'currency' => $request->currency_code,
                'type' => $request->type,
                'origin' => $request->origin,
            ]);

            $result = $this->depositController->newDeposit($request, $user);
            
            Log::info('API Deposit creation result', [
                'user_id' => $user->id,
                'result_type' => gettype($result),
                'result_status' => $result->status ?? 'unknown'
            ]);
            
            $notification = new Notification();
            $notification->user_id = auth()->user()->id;
            $notification->title = "Deposit";
            $notification->message = "Deposit created successfully!";
            $notification->status = 0;
            $notification->save();
            
            // Return the result directly as it already has the correct format
            return $result;
        } catch (\Exception $e) {
            Log::error('API Deposit creation failed', [
                'error' => $e->getMessage(),
                'trace' => $e->getTraceAsString()
            ]);
            
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to create deposit',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Process SafeHaven deposit
     * @param Request $request
     * @return JsonResponse
     */
    public function processSafeHaven(Request $request): JsonResponse
    {
        try {
            $request->validate([
                'amount' => 'required|numeric|min:100',
            ]);

            // SafeHaven uses NGN currency with rate of 1550 NGN = 1 USD
            $ngnAmount = $request->amount;
            $usdAmount = $ngnAmount / 1550;

            return response()->json([
                'status' => 'success',
                'data' => [
                    'ngn_amount' => $ngnAmount,
                    'usd_equivalent' => round($usdAmount, 2),
                    'exchange_rate' => 1550,
                    'min_amount' => 1550,
                    'currency' => 'NGN'
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to process SafeHaven deposit',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get deposit fees and limits
     * @return JsonResponse
     */
    public function getLimits(): JsonResponse
    {
        try {
            return response()->json([
                'status' => 'success',
                'data' => [
                    'min_deposit' => (float) site('min_deposit'),
                    'max_deposit' => (float) site('max_deposit'),
                    'deposit_fee_percentage' => (float) site('deposit_fee'),
                    'currency' => site('currency'),
                    'payment_processor' => site('payment_processor'),
                    'safehaven_rate' => 1550, // NGN to USD
                    'safehaven_min' => 1550 // Minimum NGN amount
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch deposit limits',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Process deposit (legacy support)
     * @param Request $request
     * @return JsonResponse
     */
    public function deposit(Request $request): JsonResponse
    {
        try {
            $result = $this->depositController->deposit($request);
            
            // Return the result directly as it already has the correct format
            return $result;
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to process deposit',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get deposit details
     * @param string $ref
     * @return JsonResponse
     */
    public function show($ref): JsonResponse
    {
        try {
            $user = auth()->user();

            $deposit = $user->deposits()
                ->with('depositCoin')
                ->where('ref', $ref)
                ->first();

            if (!$deposit) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Deposit not found'
                ], 404);
            }

            // Calculate time remaining if deposit is still valid
            $timeRemaining = 0;
            $isExpired = true;
            
            if ($deposit->valid_until && now()->lt($deposit->valid_until)) {
                $timeRemaining = now()->diffInSeconds($deposit->valid_until);
                $isExpired = false;
            }

            return response()->json([
                'status' => 'success',
                'data' => [
                    'deposit' => $deposit,
                    'time_remaining' => $timeRemaining,
                    'is_expired' => $isExpired,
                    'qr_data' => $deposit->payment_wallet, // For QR code generation
                    'status_info' => $this->getStatusInfo($deposit->status)
                ]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to fetch deposit details',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Get status information helper
     * @param string $status
     * @return array
     */
    private function getStatusInfo($status): array
    {
        $statusMap = [
            'waiting' => [
                'label' => 'Waiting for Payment',
                'description' => 'Please send the specified amount to the provided wallet address',
                'color' => 'warning',
                'icon' => 'clock'
            ],
            'confirming' => [
                'label' => 'Confirming Payment',
                'description' => 'Payment received, awaiting blockchain confirmation',
                'color' => 'info',
                'icon' => 'refresh'
            ],
            'finished' => [
                'label' => 'Payment Completed',
                'description' => 'Payment successfully confirmed and balance credited',
                'color' => 'success',
                'icon' => 'check'
            ],
            'expired' => [
                'label' => 'Payment Expired',
                'description' => 'Payment window has expired, please create a new deposit',
                'color' => 'danger',
                'icon' => 'x'
            ],
            'rejected' => [
                'label' => 'Payment Rejected',
                'description' => 'Payment was rejected or failed',
                'color' => 'danger',
                'icon' => 'x'
            ]
        ];

        return $statusMap[$status] ?? [
            'label' => 'Unknown Status',
            'description' => 'Contact support for assistance',
            'color' => 'secondary',
            'icon' => 'question'
        ];
    }

    /**
     * Cancel pending deposit
     * @param string $ref
     * @return JsonResponse
     */
    public function cancel($ref): JsonResponse
    {
        try {
            $user = auth()->user();

            $deposit = $user->deposits()
                ->where('ref', $ref)
                ->whereIn('status', ['waiting', 'confirming'])
                ->first();

            if (!$deposit) {
                return response()->json([
                    'status' => 'error',
                    'message' => 'Deposit not found or cannot be cancelled'
                ], 404);
            }

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

            return response()->json([
                'status' => 'success',
                'message' => 'Deposit cancelled successfully',
                'data' => ['deposit' => $deposit]
            ]);
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to cancel deposit',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Handle deposit callback
     * @param Request $request
     * @return JsonResponse
     */
    public function callback(Request $request): JsonResponse
    {
        try {
            $result = $this->depositController->callback($request);
            return $result;
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to process callback',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Handle deposit callback
     * @param Request $request
     * @return JsonResponse
     */
    public function depositCallback(Request $request): JsonResponse
    {
        try {
            $result = $this->depositController->depositCallback($request);
            return $result;
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to process deposit callback',
                'error' => $e->getMessage()
            ], 500);
        }
    }

    /**
     * Handle coinpayment callback
     * @param Request $request
     * @return JsonResponse
     */
    public function depositCallbackCoinpayment(Request $request): JsonResponse
    {
        try {
            $result = $this->depositController->depositCallbackCoinpayment($request);
            return $result;
        } catch (\Exception $e) {
            return response()->json([
                'status' => 'error',
                'message' => 'Failed to process coinpayment callback',
                'error' => $e->getMessage()
            ], 500);
        }
    }
}
