<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Models\AiTradeBot;
use App\Models\UserBalance;
use App\Services\OrderService;
use Illuminate\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

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

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

        // 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;
        }

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

        // Live P/L only for ACTIVE bots (closed/stopped show final DB values)
        foreach ($bots as $bot) {
            $bot->live_pl = ($bot->status === 'active') ? $this->calculateGradualPL($bot) : null;
        }

        return view('admin.ai-trade.index', [
            'bots' => $bots,
            'pageTitle' => __('admin.nav.ai_trade'),
            'title' => __('admin.ai_trade.bots_title')
        ]);
    }

    public function show($id): View
    {
        $bot = AiTradeBot::with(['user', 'orders'])->findOrFail($id);
        $livePl = ($bot->status === 'active') ? $this->calculateGradualPL($bot) : null;

        return view('admin.ai-trade.show', [
            'bot' => $bot,
            'livePl' => $livePl,
            'pageTitle' => __('admin.nav.ai_trade'),
            'title' => __('admin.ai_trade.bots_title') . ' #' . $bot->id
        ]);
    }

    /**
     * Live (gradual) P/L for active bot - same logic as user side and EarningsController.
     */
    private function calculateGradualPL(AiTradeBot $bot): ?array
    {
        if (!$bot->admin_activated_at) {
            return null;
        }
        $elapsedMinutes = (int) abs($bot->admin_activated_at->diffInMinutes(now()));
        $totalTime = (int) ($bot->admin_set_trading_time_minutes ?? 1440); // Default 24 hours
        $amount = (float) $bot->amount;
        $maxProfitPercent = (float) ($bot->max_profit_percent ?? 0);
        $maxLossPercent = (float) ($bot->max_loss_percent ?? 0);
        if ($totalTime <= 0 || $amount <= 0) {
            return null;
        }
        $progress = min(1, max(0, $elapsedMinutes / $totalTime));
        $netPercent = $maxProfitPercent - $maxLossPercent;
        $finalNetPL = ($netPercent / 100) * $amount;
        $seed = ($bot->id ?? 0) + (int) floor($elapsedMinutes);
        mt_srand($seed);
        $random = mt_rand() / (mt_getrandmax() ?: 1);
        $variation = 0.9 + ($random * 0.2);
        $currentNetPL = $finalNetPL * $progress * $variation;
        $totalProfit = $currentNetPL > 0 ? $currentNetPL : 0;
        $totalLoss = $currentNetPL < 0 ? abs($currentNetPL) : 0;
        return [
            'totalProfit' => max(0, $totalProfit),
            'totalLoss' => max(0, $totalLoss)
        ];
    }

    public function update(Request $request, $id): RedirectResponse
    {
        $bot = AiTradeBot::findOrFail($id);

        $validated = $request->validate([
            'status' => 'sometimes|in:active,paused,stopped,closed',
            'max_profit_percent' => 'sometimes|numeric|min:0|max:100',
            'max_loss_percent' => 'sometimes|numeric|min:0|max:100',
            'total_profit' => 'sometimes|numeric',
            'total_loss' => 'sometimes|numeric',
            'admin_set_trading_time_minutes' => 'sometimes|nullable|integer|min:1|max:1440',
        ]);

        $changes = [];
        $updateData = [];

        // Handle basic fields
        if (isset($validated['status'])) {
            $updateData['status'] = $validated['status'];
            if ($validated['status'] != $bot->status) {
                $changes['status'] = ['old' => $bot->status, 'new' => $validated['status']];
            }
        }
        if (isset($validated['max_profit_percent'])) {
            $updateData['max_profit_percent'] = $validated['max_profit_percent'];
        }
        if (isset($validated['max_loss_percent'])) {
            $updateData['max_loss_percent'] = $validated['max_loss_percent'];
        }
        if (isset($validated['total_profit'])) {
            $updateData['total_profit'] = $validated['total_profit'];
            if ($validated['total_profit'] != $bot->total_profit) {
                $changes['total_profit'] = ['old' => $bot->total_profit, 'new' => $validated['total_profit']];
            }
        }
        if (isset($validated['total_loss'])) {
            $updateData['total_loss'] = $validated['total_loss'];
            if ($validated['total_loss'] != $bot->total_loss) {
                $changes['total_loss'] = ['old' => $bot->total_loss, 'new' => $validated['total_loss']];
            }
        }

        // Handle trading time setting
        if (isset($validated['admin_set_trading_time_minutes'])) {
            $updateData['admin_set_trading_time_minutes'] = $validated['admin_set_trading_time_minutes'];
            if ($validated['admin_set_trading_time_minutes'] != $bot->admin_set_trading_time_minutes) {
                $changes['admin_set_trading_time_minutes'] = [
                    'old' => $bot->admin_set_trading_time_minutes,
                    'new' => $validated['admin_set_trading_time_minutes']
                ];
            }
        }

        // When status is set to 'active': default trade time 24hr if not set, then mark as started
        if (isset($validated['status']) && $validated['status'] === 'active') {
            if (!$bot->admin_set_trading_time_minutes && !isset($validated['admin_set_trading_time_minutes'])) {
                $updateData['admin_set_trading_time_minutes'] = 1440; // Default 24 hours
                $changes['admin_set_trading_time_minutes'] = ['new' => 1440];
            }
            if (!$bot->admin_activated_at) {
                $updateData['admin_activated_at'] = now();
                $changes['admin_activated_at'] = ['new' => now()->toDateTimeString()];
            }
        }

        $oldStatus = $bot->status;

        // Update bot
        if (!empty($updateData)) {
            $bot->update($updateData);
            $bot->refresh();
        }

        \App\Models\AuditLog::create([
            'admin_user_id' => session('admin.user_id'),
            'action' => 'ai_trade_update',
            'model_type' => AiTradeBot::class,
            'model_id' => $bot->id,
            'changes' => json_encode($changes),
            'reason' => 'Bot updated via Control Bot form',
        ]);

        $statusChangedToActive = isset($validated['status']) && $validated['status'] === 'active' && $oldStatus !== 'active';
        if ($statusChangedToActive) {
            return redirect()->back()->with('success', 'Bot started. Status is now Active. User will see it as running. Max Profit % / Max Loss % will apply when the bot is closed.');
        }
        return redirect()->back()->with('success', 'Bot updated. Max Profit % and Max Loss % will apply when the bot is closed.');
    }

    public function adjustProfitLoss(Request $request, $id): RedirectResponse
    {
        $bot = AiTradeBot::findOrFail($id);

        $validated = $request->validate([
            'profit_adjustment' => 'required|numeric',
            'loss_adjustment' => 'required|numeric',
            'reason' => 'required|string|max:500',
        ]);

        $oldProfit = $bot->total_profit;
        $oldLoss = $bot->total_loss;

        $bot->update([
            'total_profit' => $oldProfit + $validated['profit_adjustment'],
            'total_loss' => $oldLoss + $validated['loss_adjustment'],
        ]);

        \App\Models\AuditLog::create([
            'admin_user_id' => session('admin.user_id'),
            'action' => 'ai_trade_adjust_profit_loss',
            'model_type' => AiTradeBot::class,
            'model_id' => $bot->id,
            'changes' => json_encode([
                'profit' => ['old' => $oldProfit, 'new' => $bot->total_profit, 'adjustment' => $validated['profit_adjustment']],
                'loss' => ['old' => $oldLoss, 'new' => $bot->total_loss, 'adjustment' => $validated['loss_adjustment']],
            ]),
            'reason' => $validated['reason'],
        ]);

        return redirect()->back()->with('success', 'Profit/Loss adjusted');
    }

    public function setTimeBasedRules(Request $request, $id): RedirectResponse
    {
        $bot = AiTradeBot::findOrFail($id);

        $validated = $request->validate([
            'trading_time_minutes' => 'required|integer|min:1|max:1440', // Max 24 hours
            'time_based_rules' => 'required|string|json',
            'reason' => 'required|string|max:500',
        ]);

        // Parse and validate JSON rules
        $rules = json_decode($validated['time_based_rules'], true);
        
        if (json_last_error() !== JSON_ERROR_NONE) {
            return redirect()->back()->withErrors(['time_based_rules' => 'Invalid JSON format'])->withInput();
        }

        // Validate rules structure
        foreach ($rules as $rule) {
            if (isset($rule['after_complete']) && $rule['after_complete']) {
                if (!isset($rule['type']) || !isset($rule['percent'])) {
                    return redirect()->back()->withErrors(['time_based_rules' => 'Rule with after_complete must have type and percent'])->withInput();
                }
            } else {
                if (!isset($rule['start_minutes']) || !isset($rule['end_minutes']) || !isset($rule['type']) || !isset($rule['percent'])) {
                    return redirect()->back()->withErrors(['time_based_rules' => 'Rule must have start_minutes, end_minutes, type, and percent'])->withInput();
                }
            }
        }

        $bot->update([
            'admin_set_trading_time_minutes' => $validated['trading_time_minutes'],
            'time_based_profit_loss_rules' => $rules,
        ]);

        \App\Models\AuditLog::create([
            'admin_user_id' => session('admin.user_id'),
            'action' => 'ai_trade_set_time_based_rules',
            'model_type' => AiTradeBot::class,
            'model_id' => $bot->id,
            'changes' => json_encode([
                'trading_time_minutes' => $validated['trading_time_minutes'],
                'rules' => $rules,
            ]),
            'reason' => $validated['reason'],
        ]);

        return redirect()->back()->with('success', 'Time-based rules saved. Activate bot to start applying rules.');
    }

    public function control(Request $request, $id): RedirectResponse
    {
        $bot = AiTradeBot::findOrFail($id);

        $validated = $request->validate([
            'action' => 'required|in:start,stop,pause,resume',
            'reason' => 'required|string|max:500',
        ]);

        $statusMap = [
            'start' => 'active',
            'stop' => 'stopped',
            'pause' => 'paused',
            'resume' => 'active',
        ];

        $updateData = ['status' => $statusMap[$validated['action']]];
        
        // If starting/resuming: set default trade time 24hr if not set, then activate
        if (in_array($validated['action'], ['start', 'resume'])) {
            if (!$bot->admin_set_trading_time_minutes) {
                $updateData['admin_set_trading_time_minutes'] = 1440; // Default 24 hours
            }
            if (!$bot->admin_activated_at) {
                $updateData['admin_activated_at'] = now();
            }
        }

        $bot->update($updateData);

        \App\Models\AuditLog::create([
            'admin_user_id' => session('admin.user_id'),
            'action' => 'ai_trade_control',
            'model_type' => AiTradeBot::class,
            'model_id' => $bot->id,
            'changes' => json_encode(['action' => $validated['action']]),
            'reason' => $validated['reason'],
        ]);

        return redirect()->back()->with('success', 'Bot ' . $validated['action'] . 'ed');
    }

    /**
     * Manually process a single bot (create orders immediately)
     */
    public function processNow($id): RedirectResponse
    {
        $bot = AiTradeBot::findOrFail($id);

        if ($bot->status !== 'active') {
            return redirect()->back()->withErrors(['error' => 'Bot must be active to process orders']);
        }

        try {
            $orderService = app(\App\Services\OrderService::class);
            // Force process (bypass interval check) when admin manually triggers
            $result = $orderService->processBot($bot, true);

            $message = "Bot processed successfully. ";
            if ($result['orders_created'] > 0) {
                $message .= "Created {$result['orders_created']} order(s).";
            } else {
                $message .= "No orders created (may be waiting for interval or other conditions).";
            }

            \App\Models\AuditLog::create([
                'admin_user_id' => session('admin.user_id'),
                'action' => 'ai_trade_manual_process',
                'model_type' => AiTradeBot::class,
                'model_id' => $bot->id,
                'changes' => json_encode(['orders_created' => $result['orders_created'] ?? 0]),
                'reason' => 'Admin manually triggered bot processing',
            ]);

            return redirect()->back()->with('success', $message);
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\Log::error("Manual bot processing error: " . $e->getMessage());
            return redirect()->back()->withErrors(['error' => 'Error processing bot: ' . $e->getMessage()]);
        }
    }

    /**
     * Close bot (admin). Uses admin-set win/loss % for final P/L and creates order record.
     */
    public function close(OrderService $orderService, $id): RedirectResponse
    {
        $bot = AiTradeBot::with('user')->findOrFail($id);

        if ($bot->status === 'closed') {
            return redirect()->back()->with('warning', 'Bot is already closed');
        }

        $user = $bot->user;
        if (!$user) {
            return redirect()->back()->withErrors(['error' => 'Bot has no user']);
        }

        try {
            DB::transaction(function () use ($user, $bot, $orderService) {
                $user = $user->fresh();
                $usdtBalance = UserBalance::where('user_id', $user->id)->where('coin_name', 'USDT')->first();

                if ($usdtBalance) {
                    $currentLocked = max(0, (float) $usdtBalance->locked_balance);
                    $unlockAmount = min($currentLocked, (float) $bot->amount);
                    if ($unlockAmount > 0) {
                        $usdtBalance->decrement('locked_balance', $unlockAmount);
                    }
                }

                $currentLocked = max(0, (float) $user->locked_balance);
                $unlockAmount = min($currentLocked, (float) $bot->amount);
                if ($unlockAmount > 0) {
                    $user->decrement('locked_balance', $unlockAmount);
                }

                $finalPL = $orderService->calculateFinalPLFromWinLossPercent($bot);
                if ($finalPL !== null) {
                    $finalNetPL = $finalPL['totalProfit'] - $finalPL['totalLoss'];
                    $currentNetPL = (float) $bot->total_profit - (float) $bot->total_loss;
                    $adjustmentNeeded = $finalNetPL - $currentNetPL;

                    $bot->update([
                        'total_profit' => $finalPL['totalProfit'],
                        'total_loss' => $finalPL['totalLoss'],
                    ]);

                    if ($adjustmentNeeded != 0) {
                        if (!$usdtBalance) {
                            $currentBalance = max(0, (float) $user->balance);
                            $currentLocked = max(0, (float) $user->locked_balance);
                            $usdtBalance = UserBalance::create([
                                'user_id' => $user->id,
                                'coin_name' => 'USDT',
                                'balance' => $currentBalance,
                                'locked_balance' => $currentLocked,
                            ]);
                        }
                        if ($adjustmentNeeded > 0) {
                            $usdtBalance->increment('balance', $adjustmentNeeded);
                            $user->increment('balance', $adjustmentNeeded);
                        } else {
                            $newBalance = max(0, (float) $usdtBalance->balance + $adjustmentNeeded);
                            $usdtBalance->update(['balance' => $newBalance]);
                            $newLegacyBalance = max(0, (float) $user->balance + $adjustmentNeeded);
                            $user->update(['balance' => $newLegacyBalance]);
                        }
                    }
                    $orderService->normalizeOrdersToMatchFinalPL($bot, $finalNetPL);
                    $orderService->createSummaryOrdersForClosedBot($bot, $finalNetPL);
                }

                $bot->update([
                    'status' => 'closed',
                    'closed_at' => now(),
                    'close_reason' => 'Closed by admin',
                ]);

                if ($user && ($bot->total_profit - $bot->total_loss) > 0) {
                    \App\Services\NotificationService::createBotProfit($user->fresh(), $bot->name ?? ('Bot #' . $bot->id), (float) $bot->total_profit - (float) $bot->total_loss);
                }
            });

            \App\Models\AuditLog::create([
                'admin_user_id' => session('admin.user_id'),
                'action' => 'ai_trade_close_bot',
                'model_type' => AiTradeBot::class,
                'model_id' => $bot->id,
                'changes' => json_encode(['closed_by' => 'admin']),
                'reason' => 'Closed by admin',
            ]);

            return redirect()->back()->with('success', 'Bot closed. Final P/L applied from win/loss %.');
        } catch (\Exception $e) {
            Log::error('Admin close bot error: ' . $e->getMessage(), ['bot_id' => $bot->id]);
            return redirect()->back()->withErrors(['error' => 'Error closing bot: ' . $e->getMessage()]);
        }
    }
}
