<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\User;
use App\Models\Market;
use App\Models\Order;
use App\Models\Trade;
use App\Models\Wallet;
use App\Models\LedgerTransaction;
use Illuminate\Http\Request;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;

class AdminController extends Controller
{
    /**
     * Get admin dashboard statistics
     */
    public function getDashboardStats(): JsonResponse
    {
        try {
            $stats = [
                'total_users' => User::count(),
                'total_markets' => Market::count(),
                'active_orders' => Order::active()->count(),
                'total_trades' => Trade::count(),
                'total_trades_24h' => Trade::where('created_at', '>=', now()->subDay())->count(),
                'total_volume_24h' => Trade::where('created_at', '>=', now()->subDay())->sum('trade_value'),
                'total_wallets' => Wallet::count(),
                'total_deposits' => LedgerTransaction::where('type', 'deposit')->where('status', 'completed')->sum('amount'),
                'total_withdrawals' => LedgerTransaction::where('type', 'withdrawal')->where('status', 'completed')->sum('amount'),
            ];
            
            return response()->json([
                'success' => true,
                'data' => $stats
            ]);
        } catch (\Exception $e) {
            Log::error('Admin dashboard stats error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve dashboard statistics'
            ], 500);
        }
    }
    
    /**
     * Get recent trades for admin monitoring
     */
    public function getRecentTrades(Request $request): JsonResponse
    {
        try {
            $limit = $request->input('limit', 50);
            $marketId = $request->input('market_id');
            
            $query = Trade::with(['buyOrder.user', 'sellOrder.user', 'market'])
                         ->latest('executed_at');
                         
            if ($marketId) {
                $query->where('market_id', $marketId);
            }
            
            $trades = $query->paginate($limit);
            
            return response()->json([
                'success' => true,
                'data' => $trades
            ]);
        } catch (\Exception $e) {
            Log::error('Admin recent trades error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve recent trades'
            ], 500);
        }
    }
    
    /**
     * Get all markets with their status
     */
    public function getMarkets(): JsonResponse
    {
        try {
            $markets = Market::withCount(['orders', 'trades'])->get();
            
            return response()->json([
                'success' => true,
                'data' => $markets
            ]);
        } catch (\Exception $e) {
            Log::error('Admin markets error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve markets'
            ], 500);
        }
    }
    
    /**
     * Create a new market
     */
    public function createMarket(Request $request): JsonResponse
    {
        try {
            $validated = $request->validate([
                'name' => 'required|string|unique:markets,name',
                'base_currency' => 'required|string|max:10',
                'quote_currency' => 'required|string|max:10',
                'maker_fee_rate' => 'required|numeric|min:0|max:0.1',
                'taker_fee_rate' => 'required|numeric|min:0|max:0.1',
                'min_order_size' => 'required|numeric|min:0',
                'price_precision' => 'required|integer|min:0|max:8',
                'quantity_precision' => 'required|integer|min:0|max:8',
                'enabled' => 'boolean',
            ]);
            
            $market = Market::create(array_merge($validated, [
                'status' => 'active',
                'created_at' => now(),
                'updated_at' => now(),
            ]));
            
            Log::info('New market created', ['market_id' => $market->id, 'name' => $market->name]);
            
            return response()->json([
                'success' => true,
                'data' => $market,
                'message' => 'Market created successfully'
            ], 201);
        } catch (\Exception $e) {
            Log::error('Admin create market error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to create market: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Get all pending withdrawals
     */
    public function getPendingWithdrawals(): JsonResponse
    {
        try {
            $withdrawals = LedgerTransaction::where('type', 'withdrawal')
                                           ->where('status', 'pending')
                                           ->with('user')
                                           ->orderBy('created_at', 'desc')
                                           ->get();
            
            return response()->json([
                'success' => true,
                'data' => $withdrawals
            ]);
        } catch (\Exception $e) {
            Log::error('Admin pending withdrawals error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve pending withdrawals'
            ], 500);
        }
    }
    
    /**
     * Approve a withdrawal
     */
    public function approveWithdrawal(Request $request, string $transactionId): JsonResponse
    {
        try {
            DB::transaction(function () use ($transactionId, $request) {
                $transaction = LedgerTransaction::where('id', $transactionId)
                                               ->where('type', 'withdrawal')
                                               ->where('status', 'pending')
                                               ->firstOrFail();
                
                // Update transaction status
                $transaction->update([
                    'status' => 'processing',
                    'admin_action' => 'approved',
                    'admin_note' => $request->input('admin_note', 'Withdrawal approved by admin'),
                    'processed_at' => now(),
                ]);
                
                // Lock the funds
                $wallet = Wallet::where('user_id', $transaction->user_id)
                                ->where('currency', $transaction->currency)
                                ->first();
                
                if ($wallet) {
                    $wallet->decrement('locked_balance', $transaction->amount);
                }
                
                Log::info('Withdrawal approved', [
                    'transaction_id' => $transactionId,
                    'user_id' => $transaction->user_id,
                    'amount' => $transaction->amount
                ]);
            });
            
            return response()->json([
                'success' => true,
                'message' => 'Withdrawal approved successfully'
            ]);
        } catch (\Exception $e) {
            Log::error('Admin approve withdrawal error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to approve withdrawal: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Reject a withdrawal
     */
    public function rejectWithdrawal(Request $request, string $transactionId): JsonResponse
    {
        try {
            DB::transaction(function () use ($transactionId, $request) {
                $transaction = LedgerTransaction::where('id', $transactionId)
                                               ->where('type', 'withdrawal')
                                               ->where('status', 'pending')
                                               ->firstOrFail();
                
                // Update transaction status
                $transaction->update([
                    'status' => 'rejected',
                    'admin_action' => 'rejected',
                    'admin_note' => $request->input('admin_note', 'Withdrawal rejected by admin'),
                    'processed_at' => now(),
                ]);
                
                // Release locked funds back to available balance
                $wallet = Wallet::where('user_id', $transaction->user_id)
                                ->where('currency', $transaction->currency)
                                ->first();
                
                if ($wallet) {
                    $wallet->decrement('locked_balance', $transaction->amount);
                    $wallet->increment('available_balance', $transaction->amount);
                }
                
                Log::info('Withdrawal rejected', [
                    'transaction_id' => $transactionId,
                    'user_id' => $transaction->user_id,
                    'amount' => $transaction->amount
                ]);
            });
            
            return response()->json([
                'success' => true,
                'message' => 'Withdrawal rejected successfully'
            ]);
        } catch (\Exception $e) {
            Log::error('Admin reject withdrawal error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to reject withdrawal: ' . $e->getMessage()
            ], 500);
        }
    }
    
    /**
     * Get system health status
     */
    public function getSystemHealth(): JsonResponse
    {
        try {
            $health = [
                'database' => DB::connection()->getPdo() ? 'healthy' : 'unhealthy',
                'redis' => app('redis')->connection()->ping() ? 'healthy' : 'unhealthy',
                'queue_workers' => $this->checkQueueWorkers(),
                'api_response_time' => $this->measureApiResponseTime(),
                'last_trade_time' => Trade::latest('executed_at')->value('executed_at'),
                'active_users' => User::where('last_active_at', '>=', now()->subMinutes(15))->count(),
            ];
            
            return response()->json([
                'success' => true,
                'data' => $health
            ]);
        } catch (\Exception $e) {
            Log::error('Admin system health error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve system health'
            ], 500);
        }
    }
    
    /**
     * Check queue workers status
     */
    private function checkQueueWorkers(): string
    {
        try {
            // This is a simplified check - in production, you'd want more sophisticated monitoring
            $failedJobs = DB::table('failed_jobs')->where('failed_at', '>=', now()->subHour())->count();
            $pendingJobs = DB::table('jobs')->count();
            
            if ($failedJobs > 10) {
                return 'degraded';
            } elseif ($pendingJobs > 1000) {
                return 'degraded';
            }
            
            return 'healthy';
        } catch (\Exception $e) {
            return 'unhealthy';
        }
    }
    
    /**
     * Measure API response time
     */
    private function measureApiResponseTime(): float
    {
        $startTime = microtime(true);
        
        try {
            // Simple ping test
            DB::select('SELECT 1');
            $endTime = microtime(true);
            return ($endTime - $startTime) * 1000; // Convert to milliseconds
        } catch (\Exception $e) {
            return 9999; // Return high value if test fails
        }
    }
}