<?php

namespace App\Services\Bot;

use App\Models\Notification;
use App\Models\Order;
use App\Models\Position;
use App\Models\TradeJournal;
use App\Models\User;
use App\Services\FlatTrade\BrokerAccountResolver;
use App\Services\FlatTrade\FlatTradeAccountSyncService;
use App\Services\FlatTrade\FlatTradeClient;

class ExitEngine
{
    public function __construct(
        private FlatTradeClient $client,
        private BrokerAccountResolver $resolver,
        private FlatTradeAccountSyncService $accountSync,
    ) {}

    public function evaluate(Position $position, float $currentLtp, array $rulebook): ?string
    {
        if (! $position->is_open || $position->net_quantity <= 0) {
            return null;
        }

        $entry = (float) $position->net_avg_price;
        if ($entry <= 0) {
            return null;
        }

        $pnlPct = (($currentLtp - $entry) / $entry) * 100;
        $peak = max((float) $position->peak_ltp, $currentLtp);
        $position->update(['peak_ltp' => $peak, 'ltp' => $currentLtp]);

        $exitRules = $rulebook['exit_rules'] ?? [];

        if ($pnlPct <= -((float) ($exitRules['stop_loss']['premium_loss_percent'] ?? 15))) {
            return 'stop_loss';
        }

        $trail = $exitRules['trailing_stop'] ?? [];
        if (($trail['enabled'] ?? false) && $pnlPct >= (float) ($trail['activate_at_profit_percent'] ?? 3)) {
            $giveback = (($peak - $currentLtp) / $entry) * 100;
            if ($giveback >= (float) ($trail['trail_from_peak_percent'] ?? 3)) {
                return 'trailing_stop';
            }
        }

        $fullTarget = (float) ($exitRules['profit_booking']['normal_trade']['full_exit'] ?? 25);
        if ($pnlPct >= $fullTarget) {
            return 'profit_booking';
        }

        return null;
    }

    public function executeExit(User $user, Position $position, string $reason, array $rulebook): void
    {
        if (! $this->resolver->bindTradingClient($this->client, $user)) {
            return;
        }

        $ltp = (float) ($position->ltp ?? $position->net_avg_price);

        $response = $this->client->placeOrder([
            'exch' => $position->exchange,
            'tsym' => $position->tradingsymbol,
            'qty' => (string) abs($position->net_quantity),
            'prc' => (string) max(0.05, round($ltp - 0.5, 2)),
            'prd' => $position->product_type,
            'trantype' => 'S',
            'prctyp' => 'LMT',
            'ret' => 'DAY',
            'dscqty' => '0',
            'remarks' => 'autotrade_exit_'.$reason,
        ]);

        if (($response['stat'] ?? '') === 'Ok') {
            Order::create([
                'user_id' => $user->id,
                'instrument_id' => $position->instrument_id,
                'broker_order_no' => $response['norenordno'] ?? null,
                'exchange' => $position->exchange,
                'tradingsymbol' => $position->tradingsymbol,
                'transaction_type' => 'S',
                'product_type' => $position->product_type,
                'price_type' => 'LMT',
                'quantity' => abs($position->net_quantity),
                'price' => max(0.05, round($ltp - 0.5, 2)),
                'status' => 'PENDING',
                'remarks' => 'autotrade_exit_'.$reason,
                'placed_at' => now(),
            ]);

            $this->accountSync->syncUser($user);

            $pnl = ($ltp - (float) $position->net_avg_price) * $position->net_quantity;

            TradeJournal::create([
                'user_id' => $user->id,
                'instrument_id' => $position->instrument_id,
                'entry_price' => $position->net_avg_price,
                'exit_price' => $ltp,
                'pnl' => $pnl,
                'exited_at' => now(),
                'entered_at' => $position->opened_at,
            ]);

            Notification::create([
                'user_id' => $user->id,
                'type' => 'exit',
                'title' => 'Exit: '.str_replace('_', ' ', ucfirst($reason)),
                'message' => "Closed {$position->tradingsymbol}. P&L ₹".number_format($pnl, 2),
            ]);
        }
    }
}
