<?php

namespace App\Services\Bot;

use App\Models\BotSignal;
use App\Models\Instrument;
use App\Models\Notification;
use App\Models\Order;
use App\Models\Position;
use App\Models\User;
use App\Services\FlatTrade\BrokerAccountResolver;
use App\Services\FlatTrade\FlatTradeClient;

class EntryEngine
{
    public function __construct(
        private FlatTradeClient $client,
        private BrokerAccountResolver $resolver,
        private RegimeDetector $regimeDetector,
        private PositionSizer $positionSizer,
    ) {}

    public function scanUser(User $user, \Illuminate\Support\Collection $instruments, array $marketContext): ?BotSignal
    {
        $settings = $user->botSettings;
        if (! $settings?->auto_trade || ! $settings->bot_enabled) {
            return null;
        }

        if (! $this->resolver->bindTradingClient($this->client, $user)) {
            return null;
        }

        if (Position::where('user_id', $user->id)->where('is_open', true)->exists()) {
            return null;
        }

        $rulebook = $user->strategy?->rulebook ?? config('rulebook');
        if (! $this->withinTradingHours($rulebook)) {
            return null;
        }

        $regime = $this->regimeDetector->detect(
            $marketContext['spot'],
            $marketContext['vwap'],
            $marketContext['ema20'],
            $marketContext['ema50'],
            $marketContext['expiry'] ?? null
        );

        $preferred = $this->regimeDetector->preferredOption($regime, $rulebook) ?? 'PE';
        $candidates = $instruments
            ->where('option_type', $preferred)
            ->sortByDesc(fn ($i) => $i->latestGreek?->score ?? 0);

        $best = $candidates->first();
        if (! $best) {
            return null;
        }

        $confidence = (float) ($best->latestGreek?->score ?? 0);
        $threshold = (float) ($rulebook['global_rules']['confidence_levels']['low_confidence'] ?? 55);
        if ($confidence < $threshold) {
            return null;
        }

        if ($this->alreadyTradedStrikeToday($user, $best)) {
            return null;
        }

        $signal = BotSignal::create([
            'user_id' => $user->id,
            'instrument_id' => $best->id,
            'signal_type' => 'entry',
            'regime' => $regime,
            'confidence' => $confidence,
            'conditions_met' => ['delta_rising', 'gamma_rising'],
            'reason' => "Regime {$regime}, highest strike score",
        ]);

        $lots = $this->positionSizer->lotsForConfidence($user, $confidence, $rulebook);
        $qty = $lots * (int) $best->lot_size;
        $ltp = (float) ($best->latestTick?->ltp ?? 0);

        $response = $this->client->placeOrder([
            'exch' => 'NFO',
            'tsym' => $best->tradingsymbol,
            'qty' => (string) $qty,
            'prc' => (string) round($ltp + 0.5, 2),
            'prd' => 'I',
            'trantype' => 'B',
            'prctyp' => 'LMT',
            'ret' => 'DAY',
            'dscqty' => '0',
            'remarks' => 'autotrade_entry',
        ]);

        if (($response['stat'] ?? '') === 'Ok') {
            Order::create([
                'user_id' => $user->id,
                'instrument_id' => $best->id,
                'broker_order_no' => $response['norenordno'] ?? null,
                'exchange' => 'NFO',
                'tradingsymbol' => $best->tradingsymbol,
                'transaction_type' => 'B',
                'product_type' => 'I',
                'price_type' => 'LMT',
                'quantity' => $qty,
                'price' => round($ltp + 0.5, 2),
                'status' => 'PENDING',
                'remarks' => 'autotrade_entry',
                'placed_at' => now(),
            ]);

            Notification::create([
                'user_id' => $user->id,
                'type' => 'entry',
                'title' => 'Entry Order Placed',
                'message' => "Buy {$best->tradingsymbol} x {$qty} @ LMT",
                'meta' => ['signal_id' => $signal->id],
            ]);

            app(\App\Services\FlatTrade\FlatTradeAccountSyncService::class)->syncUser($user);
        }

        $settings->update(['last_scan_at' => now(), 'scan_side' => $preferred, 'bot_status' => 'running']);

        return $signal;
    }

    private function withinTradingHours(array $rulebook): bool
    {
        $hours = $rulebook['nifty50']['preferred_trading_hours'] ?? ['09:45-12:00', '13:00-15:00'];
        $now = now('Asia/Kolkata')->format('H:i');

        foreach ($hours as $window) {
            [$start, $end] = explode('-', $window);
            if ($now >= $start && $now <= $end) {
                return true;
            }
        }

        return false;
    }

    private function alreadyTradedStrikeToday(User $user, Instrument $instrument): bool
    {
        return Order::where('user_id', $user->id)
            ->where('instrument_id', $instrument->id)
            ->whereDate('created_at', today())
            ->exists();
    }
}
