<?php

use App\Models\PortfolioHolding;
use App\Models\Security;
use App\Models\SecurityOrder;
use App\Models\Wallet;
use App\Models\WalletTransaction;
use App\Mail\AdminTransactionMail;
use App\Services\DefaultCurrencyService;
use App\Services\Sms\SmsAfrikasTalking;
use App\Services\Trading\TradingSettingsService;
use App\Traits\Vrm\Livewire\WithNotifications;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;
use Livewire\Attributes\Computed;
use Livewire\Attributes\Layout;
use Livewire\Component;

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

    public int $securityId;
    public string $amount = '';
    public string $investmentStep = 'form';
    public float $submittedInvestmentAmount = 0.0;
    public int $submittedInvestmentQuantity = 0;

    public function mount(int $security): void
    {
        $this->useToasts();
        $this->securityId = $security;

        $exists = Security::query()
            ->where('is_active', true)
            ->whereKey($this->securityId)
            ->exists();

        abort_unless($exists, 404);
    }

    #[Computed]
    public function security(): Security
    {
        return Security::query()
            ->where('is_active', true)
            ->findOrFail($this->securityId);
    }

    #[Computed]
    public function currentSharePrice(): float
    {
        return max(0.0001, (float) $this->security->latestPrice());
    }

    #[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 isMarketOpen(): bool
    {
        return app(TradingSettingsService::class)->isMarketOpen();
    }

    #[Computed]
    public function holding(): array
    {
        $holding = PortfolioHolding::query()
            ->where('user_id', auth()->id())
            ->where('security_id', $this->securityId)
            ->first();

        if (! $holding) {
            return [
                'quantity' => 0,
                'current_value' => 0,
                'total_invested' => 0,
            ];
        }

        $quantity = (int) $holding->quantity;
        $totalInvested = (float) $holding->total_invested;

        return [
            'quantity' => $quantity,
            'current_value' => $this->currentSharePrice * $quantity,
            'total_invested' => $totalInvested,
        ];
    }

    #[Computed]
    public function hasInvested(): bool
    {
        return $this->holding['quantity'] > 0 || $this->holding['total_invested'] > 0;
    }

    #[Computed]
    public function investmentLogs(): array
    {
        return SecurityOrder::query()
            ->where('user_id', auth()->id())
            ->where('security_id', $this->securityId)
            ->where('order_type', 'buy')
            ->latest('traded_at')
            ->limit(10)
            ->get()
            ->map(function (SecurityOrder $order): array {
                return [
                    'id' => $order->id,
                    'amount' => (float) $order->total_amount,
                    'quantity' => (int) $order->quantity,
                    'status' => (string) $order->status,
                    'date' => $order->traded_at?->format('M d, Y h:i A') ?? 'N/A',
                ];
            })
            ->all();
    }

    public function goToInvestmentConfirmation(): void
    {
        $preparedOrder = $this->prepareInvestmentOrder();

        if ($preparedOrder === null) {
            return;
        }

        $this->investmentStep = 'confirm';
    }

    public function backToInvestmentForm(): void
    {
        $this->investmentStep = 'form';
    }

    public function submitInvestment(): bool
    {
        if ($this->investmentStep !== 'confirm') {
            $this->goToInvestmentConfirmation();

            return false;
        }

        $preparedOrder = $this->prepareInvestmentOrder();

        if ($preparedOrder === null) {
            $this->investmentStep = 'form';

            return false;
        }

        /** @var \App\Models\Security $security */
        $security = $preparedOrder['security'];
        /** @var \App\Models\Wallet $wallet */
        $wallet = $preparedOrder['wallet'];
        $quantity = $preparedOrder['quantity'];
        $totalAmount = $preparedOrder['total_amount'];
        $pricePerShare = $preparedOrder['price_per_share'];

        DB::transaction(function () use ($security, $wallet, $quantity, $totalAmount, $pricePerShare): void {
            SecurityOrder::query()->create([
                'user_id' => auth()->id(),
                'security_id' => $security->id,
                'wallet_id' => $wallet->id,
                'order_type' => 'buy',
                'status' => 'pending',
                'price_per_share' => $pricePerShare,
                'quantity' => $quantity,
                'volume' => $quantity,
                'total_amount' => $totalAmount,
                'currency_code' => app(DefaultCurrencyService::class)->code(),
                'traded_at' => now(),
                'profit_loss_amount' => 0,
                'profit_loss_percent' => 0,
                'is_active' => true,
            ]);

            $wallet->used_amount = (float) $wallet->used_amount + $totalAmount;
            $wallet->save();

            WalletTransaction::query()->create([
                'wallet_id' => $wallet->id,
                'user_id' => auth()->id(),
                'type' => 'order_debit',
                'status' => 'pending',
                'amount' => $totalAmount,
                'currency_code' => app(DefaultCurrencyService::class)->code(),
                'description' => "Pending buy order for {$security->trading_name}",
                'meta' => ['security_id' => $security->id, 'quantity' => $quantity, 'order_type' => 'buy'],
            ]);
        });

        $adminEmail = config('mail.admin_address');
        if (filled($adminEmail)) {
            Mail::to((string) $adminEmail)
                ->queue(new AdminTransactionMail(
                    auth()->user()->name,
                    auth()->user()->email,
                    $totalAmount,
                    app(DefaultCurrencyService::class)->code(),
                    'shares_buy',
                    'submitted',
                    'trade'
                ));
        }
        app(SmsAfrikasTalking::class)->sendShortMessage(
            auth()->user()->phone,
            "Investment request submitted for {$security->trading_name}.",
        );

        $this->submittedInvestmentAmount = $totalAmount;
        $this->submittedInvestmentQuantity = $quantity;
        $this->amount = '';
        $this->investmentStep = 'result';
        $this->notifySuccess(__('Investment request submitted and pending admin approval.'));
        $this->dispatch('security-order-submitted');

        return true;
    }

    public function resetInvestmentFlow(): void
    {
        $this->amount = '';
        $this->investmentStep = 'form';
        $this->submittedInvestmentAmount = 0.0;
        $this->submittedInvestmentQuantity = 0;
    }

    protected function prepareInvestmentOrder(): ?array
    {
        $this->validate([
            'amount' => ['required', 'numeric', 'min:0.01'],
        ]);

        if (! $this->isMarketOpen) {
            $this->notifyError(__('Market is currently closed. Trading is unavailable.'));

            return null;
        }

        $security = $this->security;
        $wallet = $this->wallet;
        $amount = (float) $this->amount;
        $pricePerShare = $this->currentSharePrice;
        $quantity = (int) floor($amount / $pricePerShare);

        if ($quantity <= 0) {
            $this->notifyError(__('Amount is too low for this security price.'));

            return null;
        }

        if ($quantity < $security->min_shares) {
            $this->notifyError(__('Quantity must be at least :min shares.', ['min' => $security->min_shares]));

            return null;
        }

        if ($security->max_shares_purchase > 0 && $quantity > $security->max_shares_purchase) {
            $this->notifyError(__('Quantity exceeds max shares per purchase.'));

            return null;
        }

        $existingHoldingQuantity = (int) auth()->user()
            ->portfolioHoldings()
            ->where('security_id', $security->id)
            ->value('quantity');

        if ($security->max_shares_holding > 0 && ($existingHoldingQuantity + $quantity) > $security->max_shares_holding) {
            $this->notifyError(__('Order exceeds your maximum allowed holding for this security.'));

            return null;
        }

        $totalAmount = $pricePerShare * $quantity;

        if ($wallet->available_balance < $totalAmount) {
            $this->notifyError(__('You do not have enough available balance. Please make a deposit first.'));

            return null;
        }

        return [
            'security' => $security,
            'wallet' => $wallet,
            'quantity' => $quantity,
            'total_amount' => $totalAmount,
            'price_per_share' => $pricePerShare,
        ];
    }

    protected function view($data = [])
    {
        return app('view')->file('/home1/xxwewbmy/zidii.fxinvest.io/storage/framework/views/livewire/views/debd74a0.blade.php', $data);
    }
}; 