<?php

namespace App\Console\Commands;

use Carbon\Carbon;
use App\Models\UserPlan;
use App\Models\Transaction;
use App\Enum\UserPlanStatus;
use App\Enum\TransactionType;
use App\Enum\TransactionMethod;
use App\Enum\TransactionStatus;
use Illuminate\Console\Command;
use App\Enum\TransactionDirection;
use Illuminate\Support\Facades\DB;

class ProcessDailyProfit extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'app:process-daily-profit';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Process daily profit for active trading plans';

    /**
     * Execute the console command.
     */
    public function handle()
    {
        $today = Carbon::today();

        UserPlan::where('status', UserPlanStatus::ACTIVE)
            ->whereDate('starts_at', '<=', $today)
            ->whereColumn('days_processed', '<', 'duration')
            ->chunkById(100, function ($userPlans) use ($today) {

                foreach ($userPlans as $plan) {

                    DB::transaction(function () use ($plan, $today) {

                        // Lock plan row to prevent race conditions
                        $userPlan = UserPlan::where('id', $plan->id)
                            ->lockForUpdate()
                            ->first();

                        // Skip if plan already completed
                        if ($userPlan->days_processed >= $userPlan->duration) {
                            $this->completePlan($userPlan);
                            return;
                        }

                        // Prevent duplicate credit for today
                        $alreadyCredited = Transaction::where('other_reference_id', $userPlan->id)
                            ->where('type', TransactionType::PROFIT)
                            ->whereDate('transaction_at', $today)
                            ->exists();

                        if ($alreadyCredited) {
                            return;
                        }

                        // Calculate profit considering daily_profit_multiplication
                        $profit = $this->calculateProfit($userPlan);

                        // Lock user row to prevent concurrent balance modifications
                        $user = $userPlan->user()->lockForUpdate()->first();

                        // Credit profit to balance
                        $user->profit_balance += $profit;
                        $user->save();

                        // Increment processed days
                        $userPlan->increment('days_processed');

                        // Log transaction
                        Transaction::create([
                            'user_id' => $user->id,
                            'type' => TransactionType::PROFIT,
                            'direction' => TransactionDirection::CREDIT,
                            'description' => 'Daily profit from plan ' . $userPlan->plan->name,
                            'amount' => $profit,
                            'method' => TransactionMethod::TRADE,
                            'transaction_at' => now(),
                            'reference_id' => generateReferenceId(),
                            'other_reference_id' => $userPlan->id,
                            'status' => TransactionStatus::COMPLETED,
                        ]);

                        // If plan finished today, complete it
                        if ($userPlan->days_processed >= $userPlan->duration) {
                            $this->completePlan($userPlan);
                        }
                    });
                }
            });

        return Command::SUCCESS;
    }

    // protected function calculateProfit(UserPlan $userPlan)
    // {
    //     $capital = $userPlan->amount;
    //     $multiplier = $userPlan->plan->daily_profit_multiplication;

    //     // Simple profit if multiplier is 0
    //     if ($multiplier <= 0) {
    //         return ($capital * $userPlan->daily_profit) / 100;
    //     }

    //     // Otherwise, compound multiple times per day
    //     for ($i = 0; $i < $multiplier; $i++) {
    //         $profitIteration = ($capital * $userPlan->daily_profit) / 100;
    //         $capital += $profitIteration;
    //     }

    //     return $capital - $userPlan->amount;
    // }

    protected function calculateProfit(UserPlan $userPlan)
    {
        $initialCapital = $userPlan->amount;
        $capital = $initialCapital;

        $dailyRate = $userPlan->daily_profit / 100;
        $multiplier = $userPlan->plan->daily_profit_multiplication;
        $tradesPerDayStatus = true;
        $trades = $userPlan->trades_per_day;

        if (!$tradesPerDayStatus) {

            if ($multiplier <= 0) {
                return round($capital * $dailyRate, 2);
            }

            for ($i = 0; $i < $multiplier; $i++) {
                $capital += $capital * $dailyRate;
            }

            return round($capital - $initialCapital, 2);
        } else {
            $ratePerTrade = $dailyRate / $trades;

            for ($t = 0; $t < $trades; $t++) {

                if ($multiplier <= 0) {
                    $capital += $capital * $ratePerTrade;
                } else {
                    for ($m = 0; $m < $multiplier; $m++) {
                        $capital += $capital * $ratePerTrade;
                    }
                }
            }

            return round($capital - $initialCapital, 2);
        }
    }


    protected function completePlan(UserPlan $userPlan)
    {
        DB::transaction(function () use ($userPlan) {

            $user = $userPlan->user()->lockForUpdate()->first();

            // Return capital to user balance
            $user->balance += $userPlan->amount;
            $user->save();

            $userPlan->update([
                'status' => UserPlanStatus::COMPLETED
            ]);

            // Log capital return
            Transaction::create([
                'user_id' => $user->id,
                'type' => TransactionType::CAPITAL_RETURN,
                'direction' => TransactionDirection::CREDIT,
                'description' => 'Capital returned from completed plan ' . $userPlan->plan->name,
                'amount' => $userPlan->amount,
                'method' => TransactionMethod::TRADE,
                'transaction_at' => now(),
                'reference_id' => generateReferenceId(),
                'other_reference_id' => $userPlan->id,
                'status' => TransactionStatus::COMPLETED,
            ]);
        });

        $this->info("Plan {$userPlan->id} completed.");
    }
}
