<?php

namespace App\Http\Controllers\Dashboard\Admin;

use App\Enum\TradePerformanceDirection;
use App\Enum\TraderStatus;
use App\Http\Controllers\Controller;
use App\Models\Trader;
use App\Models\TraderPerformance;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;


class TraderPerformanceController extends Controller
{
    /**
     * Display a listing of the resource.
     */
    public function index(string $traderUUID)
    {
        $breadcrumbs = [
            ['label' => config('app.name'), 'url' => '/'],
            ['label' => 'Dashboard', 'url' => route('admin.dashboard')],
            ['label' => 'Trader Performances', 'active' => true]
        ];

        $trader = Trader::where('uuid', $traderUUID)->firstOrFail();
        $traderPerformances = $trader->performances()->with(['trader'])->latest()->get();

        $data = [
            'title' => 'Trader Performances',
            'breadcrumbs' => $breadcrumbs,
            'trader' => $trader,
            'traderPerformances' => $traderPerformances
        ];

        return view('dashboard.admin.trader_performance.index', $data);
    }

    /**
     * Show the form for creating a new resource.
     */
    public function create($traderUUID)
    {
        $breadcrumbs = [
            ['label' => config('app.name'), 'url' => '/'],
            ['label' => 'Dashboard', 'url' => route('admin.dashboard')],
            ['label' => 'Trader Performances', 'url' => route('admin.trader.performance.index', $traderUUID)],
            ['label' => 'Create Trader Performance', 'active' => true]
        ];

        $trader = Trader::with(['user'])->where('uuid', $traderUUID)->firstOrFail();
        $traders = Trader::with(['user'])->where('status', TraderStatus::ACTIVE)->get();
        $traderPerformanceDirections = TradePerformanceDirection::cases();

        $data = [
            'title' => 'Create Trader Performance',
            'breadcrumbs' => $breadcrumbs,
            'trader' => $trader,
            'traders' => $traders,
            'traderPerformanceDirections' => $traderPerformanceDirections
        ];

        return view('dashboard.admin.trader_performance.create', $data);
    }

    /**
     * Store a newly created resource in storage.
     */
    public function store(Request $request, string $traderUUID)
    {
        $request->validate([
            'trader_id' => 'required|numeric',
            'direction' => 'required|in:up,down',
            'roi_percentage' => 'required|numeric',
            'recorded_at' => 'required|date'
        ]);

        try {
            $trader = Trader::with(['user'])->where('uuid', $traderUUID)->firstOrFail();

            DB::transaction(function () use ($request, $trader) {

                TraderPerformance::create(
                    [
                        'trader_id' => $trader->id,
                        'direction' => $request->direction,
                        'roi_percentage' => $request->roi_percentage,
                        'recorded_at' => $request->recorded_at,
                    ]
                );

                // Update trader balance if requested
                if ($request->has('update_balance')) {
                    $roi = (float) $request->roi_percentage;
                    $balanceChange = $request->direction === 'up'
                        ? $trader->balance * ($roi / 100)
                        : -($trader->balance * ($roi / 100));

                    $trader->update([
                        'balance' => max(0, $trader->balance + $balanceChange),
                    ]);
                }
            });

            return redirect()->route('admin.trader.performance.index', $traderUUID)->with('success', 'Trader performance added successfully');
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return redirect()->route('admin.trader.performance.create', $traderUUID)->with('error', 'Unable to create trader performance');
        }
    }

    /**
     * Display the specified resource.
     */
    public function show(string $traderUUID, string $traderPerformanceUUID)
    {
        $breadcrumbs = [
            ['label' => config('app.name'), 'url' => '/'],
            ['label' => 'Dashboard', 'url' => route('admin.dashboard')],
            ['label' => 'Trader Performances', 'url' => route('admin.trader.performance.index', $traderUUID)],
            ['label' => 'Trader Performance Details', 'active' => true]
        ];

        $trader = Trader::with(['user'])->where('uuid', $traderUUID)->firstOrFail();
        $traderPerformance = $trader->performances()->where('uuid', $traderPerformanceUUID)->firstOrFail();

        $data = [
            'title' => 'Trader Performance Details',
            'breadcrumbs' => $breadcrumbs,
            'trader' => $trader,
            'traderPerformance' => $traderPerformance
        ];

        return view('dashboard.admin.trader_performance.show', $data);
    }

    /**
     * Show the form for editing the specified resource.
     */
    public function edit(string $traderUUID, string $traderPerformanceUUID)
    {
        $breadcrumbs = [
            ['label' => config('app.name'), 'url' => '/'],
            ['label' => 'Dashboard', 'url' => route('admin.dashboard')],
            ['label' => 'Trader Performances', 'url' => route('admin.trader.performance.index', $traderUUID)],
            ['label' => 'Edit Trader Performance', 'active' => true]
        ];

        $traders = Trader::with(['user'])->where('status', TraderStatus::ACTIVE)->get();
        $trader = Trader::with(['user'])->where('uuid', $traderUUID)->firstOrFail();
        $traderPerformance = $trader->performances()->where('uuid', $traderPerformanceUUID)->firstOrFail();
        $traderPerformanceDirections = TradePerformanceDirection::cases();

        $data = [
            'title' => 'Edit Trader Performance',
            'breadcrumbs' => $breadcrumbs,
            'traders' => $traders,
            'trader' => $trader,
            'traderPerformance' => $traderPerformance,
            'traderPerformanceDirections' => $traderPerformanceDirections
        ];

        return view('dashboard.admin.trader_performance.edit', $data);
    }

    /**
     * Update the specified resource in storage.
     */
    public function update(Request $request, string $traderUUID, string $traderPerformanceUUID)
    {
        $request->validate([
            'trader_id' => 'required|numeric',
            'direction' => 'required|in:up,down',
            'roi_percentage' => 'required|numeric',
            'recorded_at' => 'required|date'
        ]);

        try {
            $trader = Trader::with(['user'])->where('uuid', $traderUUID)->firstOrFail();
            $requestTrader = Trader::with(['user'])->where('id', $request->trader_id)->firstOrFail();
            $traderPerformance = $trader->performances()->where('uuid', $traderPerformanceUUID)->firstOrFail();

            DB::transaction(function () use ($request, $traderPerformance) {
                $traderPerformance->update(
                    [
                        'trader_id' => $request->trader_id,
                        'direction' => $request->direction,
                        'roi_percentage' => $request->roi_percentage,
                        'recorded_at' => $request->recorded_at,
                    ]
                );
            });

            return redirect()->route('admin.trader.performance.index', $requestTrader->uuid)->with('success', 'Trader performance updated successfully');
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return redirect()->route('admin.trader.performance.edit', [$traderUUID, $traderPerformanceUUID])->with('error', 'Unable to update trader performance');
        }
    }

    /**
     * Remove the specified resource from storage.
     */
    public function delete(string $traderUUID, string $traderPerformanceUUID)
    {
        try {
            $trader = Trader::with(['user'])->where('uuid', $traderUUID)->firstOrFail();
            $traderPerformance = $trader->performances()->where('uuid', $traderPerformanceUUID)->firstOrFail();

            DB::transaction(function () use ($traderPerformance) {
                $traderPerformance->delete();
            });

            return redirect()->route('admin.trader.performance.index', $traderUUID)->with('success', 'Trader performance deleted successfully');
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return redirect()->route('admin.trader.performance.index', $traderUUID)->with('error', 'Unable to delete trader performance');
        }
    }

    /**
     * Auto-generate performance data.
     * Smart fill: only creates records for missing days in the last 7 days,
     * unless 'override' is checked — then it replaces all last 7 days.
     */
    public function autoGenerate(Request $request, string $traderUUID)
    {
        $request->validate([
            'trend' => 'required|in:profitable,unprofitable',
        ]);

        try {
            $trader = Trader::where('uuid', $traderUUID)->firstOrFail();
            $trend = $request->trend;
            $override = $request->has('override');
            $updateBalance = $request->has('update_balance');

            DB::transaction(function () use ($trader, $trend, $override, $updateBalance) {
                // Get dates for the last 7 days
                $datesToFill = [];
                for ($i = 6; $i >= 0; $i--) {
                    $datesToFill[] = now()->subDays($i)->toDateString();
                }

                if ($override) {
                    // Delete existing performances for last 7 days
                    $trader->performances()
                        ->whereIn('recorded_at', $datesToFill)
                        ->delete();
                    $missingDates = $datesToFill;
                } else {
                    // Find which dates already have records
                    $existingDates = $trader->performances()
                        ->whereIn('recorded_at', $datesToFill)
                        ->pluck('recorded_at')
                        ->map(fn($d) => $d->toDateString())
                        ->toArray();

                    $missingDates = array_diff($datesToFill, $existingDates);
                }

                if (empty($missingDates)) {
                    return; // Nothing to generate
                }

                $count = count($missingDates);

                // Determine how many up/down days proportional to days being filled
                if ($trend === 'profitable') {
                    $upDays = (int) ceil($count * rand(70, 85) / 100);
                } else {
                    $upDays = (int) floor($count * rand(15, 30) / 100);
                }
                $downDays = $count - $upDays;

                // Build array of directions
                $directions = array_merge(
                    array_fill(0, $upDays, 'up'),
                    array_fill(0, $downDays, 'down')
                );
                shuffle($directions);

                $totalPnl = 0;
                $idx = 0;

                foreach ($missingDates as $date) {
                    $direction = $directions[$idx];

                    if ($trend === 'profitable') {
                        $roi = $direction === 'up'
                            ? round(rand(300, 1500) / 100, 2)  // 3% - 15%
                            : round(rand(100, 400) / 100, 2);  // 1% - 4%
                    } else {
                        $roi = $direction === 'down'
                            ? round(rand(300, 1500) / 100, 2)  // 3% - 15%
                            : round(rand(100, 400) / 100, 2);  // 1% - 4%
                    }

                    TraderPerformance::create([
                        'trader_id' => $trader->id,
                        'direction' => $direction,
                        'roi_percentage' => $roi,
                        'recorded_at' => $date,
                    ]);

                    // Track total signed PnL
                    $totalPnl += $direction === 'up' ? $roi : -$roi;
                    $idx++;
                }

                // Update trader balance if requested
                if ($updateBalance && $totalPnl != 0) {
                    $balanceChange = $trader->balance * ($totalPnl / 100);
                    $trader->update([
                        'balance' => max(0, round($trader->balance + $balanceChange, 2)),
                    ]);
                }
            });

            return redirect()
                ->route('admin.trader.performance.index', $traderUUID)
                ->with('success', 'Performance data auto-generated successfully (' . $request->trend . ' trend).');
        } catch (\Exception $e) {
            Log::error($e->getMessage());
            return redirect()
                ->route('admin.trader.performance.index', $traderUUID)
                ->with('error', 'Unable to auto-generate performance data.');
        }
    }
}
