<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\Deposit;
use App\Models\User;
use App\Models\UserBalance;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class DepositController extends Controller
{
    public function index(Request $request): View
    {
        $query = Deposit::with('user');

        if ($request->has('status')) {
            $query->where('status', $request->get('status'));
        }

        if ($request->has('user_id')) {
            $query->where('user_id', $request->get('user_id'));
        }

        // Per page - default 10, allow 10, 20, 50, 100
        $perPage = $request->get('per_page', 10);
        if (!in_array($perPage, [10, 20, 50, 100])) {
            $perPage = 10;
        }

        $deposits = $query->latest()->paginate($perPage)->withQueryString();

        return view('admin.deposits.index', [
            'deposits' => $deposits,
            'pageTitle' => __('admin.deposits.title'),
            'title' => __('admin.deposits.title')
        ]);
    }

    public function update(Request $request, $id): RedirectResponse
    {
        try {
            $deposit = Deposit::with('user')->findOrFail($id);
            $oldStatus = $deposit->status;

            // Check if deposit is already processed and prevent double processing
            if ($oldStatus !== 'pending' && $request->status !== $oldStatus) {
                return redirect()->back()->with('error', 'This deposit has already been processed.');
            }

            // Make reason optional for confirmed, required for rejected
            $rules = [
                'status' => 'required|in:pending,confirmed,rejected',
            ];

            if ($request->status === 'rejected') {
                $rules['reason'] = 'required|string|max:500';
            } else {
                $rules['reason'] = 'nullable|string|max:500';
            }

            $validated = $request->validate($rules);

            $adminUserId = session('admin.user_id');
            if (!$adminUserId) {
                return redirect()->back()->with('error', 'Admin session expired. Please log in again.');
            }

            DB::transaction(function () use ($deposit, $validated, $oldStatus, $adminUserId) {
                // Store reason in admin_note field for user to see
                $updateData = ['status' => $validated['status']];
                if (!empty($validated['reason'])) {
                    $updateData['admin_note'] = $validated['reason'];
                }
                if ($validated['status'] !== 'pending') {
                    $updateData['processed_by'] = $adminUserId;
                    $updateData['processed_at'] = now();
                }
                
                $deposit->update($updateData);

                // If confirmed, credit user balance
                if ($validated['status'] === 'confirmed' && $oldStatus !== 'confirmed') {
                    $user = $deposit->user;
                    
                    // Check if user exists
                    if (!$user) {
                        throw new \Exception('User not found for this deposit. Cannot process deposit confirmation.');
                    }

                    // Get coin_name from wallet's coin_name or extract from network
                    $wallet = \App\Models\Wallet::where('address', $deposit->address)->first();
                    $coinName = $wallet ? ($wallet->coin_name ?? 'USDT') : 'USDT';
                    
                    // If network contains coin info, extract it (e.g., "btc", "eth", "usdt-trc20" -> "BTC", "ETH", "USDT")
                    if (stripos($deposit->network, 'btc') !== false) {
                        $coinName = 'BTC';
                    } elseif (stripos($deposit->network, 'eth') !== false && stripos($deposit->network, 'usdt') === false) {
                        $coinName = 'ETH';
                    } elseif (stripos($deposit->network, 'usdt') !== false) {
                        $coinName = 'USDT';
                    }
                    
                    $coinName = strtoupper($coinName);
                    
                    // Credit user's coin-specific balance
                    $userBalance = UserBalance::firstOrNew([
                        'user_id' => $user->id,
                        'coin_name' => $coinName
                    ]);
                    
                    if ($userBalance->exists) {
                        $userBalance->increment('balance', $deposit->amount);
                    } else {
                        $userBalance->balance = $deposit->amount;
                        $userBalance->locked_balance = 0;
                        $userBalance->save();
                    }
                    
                    // Also update legacy balance field for backward compatibility
                    $user->increment('balance', $deposit->amount);

                    \App\Services\NotificationService::createDepositApproved($user, (float) $deposit->amount, $deposit->network);
                }

                // Log audit
                \App\Models\AuditLog::create([
                    'admin_user_id' => $adminUserId,
                    'action' => 'deposit_update',
                    'model_type' => Deposit::class,
                    'model_id' => $deposit->id,
                    'changes' => json_encode(['status' => $oldStatus . ' -> ' . $validated['status']]),
                    'reason' => $validated['reason'] ?? 'Deposit confirmed',
                ]);
            });

            return redirect()->back()->with('success', 'Deposit updated successfully.');
        } catch (\Illuminate\Database\Eloquent\ModelNotFoundException $e) {
            return redirect()->back()->with('error', 'Deposit not found.');
        } catch (\Illuminate\Validation\ValidationException $e) {
            return redirect()->back()->withErrors($e->errors())->withInput();
        } catch (\Exception $e) {
            \Log::error('Deposit update failed: ' . $e->getMessage(), [
                'deposit_id' => $id,
                'admin_user_id' => session('admin.user_id'),
                'trace' => $e->getTraceAsString()
            ]);
            
            return redirect()->back()->with('error', 'Failed to update deposit: ' . $e->getMessage());
        }
    }
}
