<?php

use App\Models\Investment;
use App\Models\InvestmentPackage;
use App\Models\Wallet;
use App\Jobs\Vrm\SendMail;
use App\Mail\AdminTransactionMail;
use App\Services\DefaultCurrencyService;
use App\Services\Investment\SubscriptionService;
use App\Services\Sms\SmsAfrikasTalking;
use App\Services\Vrm\InvestmentEmailService;
use App\Traits\Vrm\Livewire\WithNotifications;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Component;

return new #[Layout('layouts.trading')] class extends Component {
    use WithNotifications;

    public string $selectedPackageId = '';

    public string $amount = '';

    public string $search = '';
    public string $investStep = 'amount';
    public string $investResultStatus = '';
    public string $investResultMessage = '';
    public string $investResultPackageName = '';
    public float $investResultAmount = 0.0;

    #[Computed]
    public function wallet(): Wallet
    {
        return Wallet::query()->firstOrCreate(
            ['user_id' => auth()->id()],
            ['currency_code' => app(DefaultCurrencyService::class)->code()]
        );
    }

    /** System default currency from ATU (single currency across the app). */
    #[Computed]
    public function currencyCode(): string
    {
        return app(DefaultCurrencyService::class)->code();
    }

    #[Computed]
    public function packages()
    {
        return InvestmentPackage::query()
            ->where('is_active', true)
            ->orderBy('min_amount')
            ->get();
    }

    #[Computed]
    public function filteredPackages()
    {
        $query = strtolower(trim($this->search));

        return $this->packages
            ->filter(function (InvestmentPackage $package) use ($query): bool {
                if ($query === '') {
                    return true;
                }

                return str_contains(strtolower($package->name), $query)
                    || str_contains(strtolower((string) $package->description), $query);
            })
            ->values();
    }

    #[Computed]
    public function selectedPackage(): ?InvestmentPackage
    {
        if ($this->selectedPackageId === '') {
            return null;
        }
        $id = (int) $this->selectedPackageId;

        return $this->packages->firstWhere('id', $id);
    }

    #[Computed]
    public function expectedReturnPreview(): float
    {
        $pkg = $this->selectedPackage;
        if (! $pkg) {
            return 0;
        }
        $amount = (float) ($this->amount === '' ? 0 : $this->amount);
        if ($amount <= 0) {
            return 0;
        }

        return $pkg->calculateExpectedReturn($amount);
    }

    #[Computed]
    public function investments()
    {
        return Investment::query()
            ->where('user_id', auth()->id())
            ->with('package')
            ->latest()
            ->get();
    }

    public function invest(): void
    {
        $validated = $this->validatedInvestmentRequest();
        if ($validated === null) {
            $this->investStep = 'amount';

            return;
        }

        $package = $validated['package'];
        $amount = $validated['amount'];

        $wallet = $this->wallet;
        $user = auth()->user();
        $availableBalance = (float) $wallet->available_balance;

        if ($availableBalance >= $amount) {
            try {
                app(SubscriptionService::class)->createSubscription($user, $wallet, $package, $amount);
                app(InvestmentEmailService::class)->sendSubscriptionCreated(
                    $user->email,
                    $user->name,
                    $package->name,
                    app(DefaultCurrencyService::class)->code(),
                    $amount,
                );
                $adminEmail = config('mail.admin_address', 'admin@fxinvest.io');
                if (filled($adminEmail)) {
                    SendMail::dispatch((string) $adminEmail, mailable: new AdminTransactionMail(
                            $user->name,
                            $user->email,
                            $amount,
                            app(DefaultCurrencyService::class)->code(),
                            'investment',
                            'submitted',
                            'wallet'
                        ));
                }
                app(SmsAfrikasTalking::class)->sendShortMessage(
                    $user->phone,
                    "Investment subscription created for {$package->name}.",
                );
                $this->investStep = 'result';
                $this->investResultStatus = 'success';
                $this->investResultMessage = __('Your investment has been received successfully.');
                $this->investResultPackageName = $package->name;
                $this->investResultAmount = $amount;
                $this->notifySuccess(__('Investment created successfully.'));
            } catch (\InvalidArgumentException $e) {
                $this->investStep = 'result';
                $this->investResultStatus = 'failed';
                $this->investResultMessage = $e->getMessage();
                $this->investResultPackageName = $package->name;
                $this->investResultAmount = $amount;
                $this->notifyError($e->getMessage());
            }

            return;
        }

        $topUpAmount = max(0, $amount - $availableBalance);

        $this->redirectRoute('member.mpesa-deposit', [
            'amount' => number_format($topUpAmount, 2, '.', ''),
            'intent' => SubscriptionService::META_INTENT_SUBSCRIPTION,
            'package_id' => $package->id,
            'target_amount' => number_format($amount, 2, '.', ''),
        ], navigate: true);
    }

    public function goToInvestConfirmation(): void
    {
        if ($this->validatedInvestmentRequest() === null) {
            return;
        }

        $this->investStep = 'confirm';
    }

    public function backToInvestAmount(): void
    {
        $this->investStep = 'amount';
    }

    public function confirmInvestment(): void
    {
        $this->invest();
    }

    public function finishInvestmentFlow(): void
    {
        $this->investStep = 'amount';
        $this->investResultStatus = '';
        $this->investResultMessage = '';
        $this->investResultPackageName = '';
        $this->investResultAmount = 0.0;
        $this->amount = '';
        $this->selectedPackageId = '';
    }

    protected function validatedInvestmentRequest(): ?array
    {
        $this->validate([
            'selectedPackageId' => 'required|integer|exists:investment_packages,id',
            'amount' => 'required|numeric|min:0.01',
        ]);

        $package = InvestmentPackage::query()->where('is_active', true)->find((int) $this->selectedPackageId);
        if (! $package) {
            $this->notifyError(__('Package not found or inactive.'));

            return null;
        }

        $amount = (float) $this->amount;
        $min = (float) $package->min_amount;
        $max = (float) $package->max_amount;

        if ($amount < $min || $amount > $max) {
            $this->notifyError(__('Amount must be between :min and :max.', ['min' => number_format($min, 2), 'max' => number_format($max, 2)]));

            return null;
        }

        return [
            'package' => $package,
            'amount' => $amount,
        ];
    }

    public function choosePackage(int $packageId): void
    {
        $package = InvestmentPackage::query()->where('is_active', true)->find($packageId);
        if (! $package) {
            $this->notifyError(__('Package not found or inactive.'));

            return;
        }

        $this->selectedPackageId = (string) $package->id;

        $currentAmount = (float) ($this->amount === '' ? 0 : $this->amount);
        $minAmount = (float) $package->min_amount;
        $maxAmount = (float) $package->max_amount;

        if ($currentAmount < $minAmount || $currentAmount > $maxAmount) {
            $this->amount = (string) number_format($minAmount, 2, '.', '');
        }

        if ($this->investStep === 'result') {
            $this->investStep = 'amount';
        }
    }

    public function claim(int $investmentId): void
    {
        $this->notifyError(__('Investment returns are approved by admin only.'));
    }

    protected function view($data = [])
    {
        return app('view')->file('/home/ziidiaik/home.ziiditrader.com/storage/framework/views/livewire/views/edd15e8f.blade.php', $data);
    }
}; 