# app/src/trading/debug/service.py

from __future__ import annotations

import time
from datetime import datetime

from src.core.config import load_settings
from src.trading.debug.execution import DebugExecutionEngine
from src.trading.debug.state import DebugPositionState, DebugTradeState
from src.trading.execution.models import ExecutionDecision


class DebugTradeService:
    _state = DebugTradeState()

    _confirm_repeats = 2
    _ready_confidence = 0.3

    def get_state(self) -> DebugTradeState:
        if not self._state.symbol:
            self._state.symbol = load_settings().default_symbol

        return self._state

    def reset(self) -> DebugTradeState:
        state = self.get_state()

        state.status = "RUNNING"
        state.last_signal = "HOLD"
        state.last_signal_confidence = 0.0
        state.last_signal_repeat_count = 1
        state.last_signal_reason = "[DEBUG] RESET HOLD"
        state.signal_started_at = time.monotonic()

        state.decision_status = "WAITING"
        state.decision_reason = "[DEBUG] Reset."
        state.is_signal_confirmed = False
        state.is_signal_ready = False

        state.execution_block_reason = None
        state.execution_size_adjustment_reason = None

        state.position = DebugPositionState()

        return state

    def stop(self) -> DebugTradeState:
        state = self.get_state()
        state.status = "OFF"
        return state

    def set_signal(
        self,
        *,
        signal: str,
        confidence: float = 0.0,
        repeat_count: int = 1,
        reason: str | None = None,
        force_ready: bool = False,
    ) -> DebugTradeState:
        state = self.get_state()

        normalized_signal = signal.strip().upper()
        if normalized_signal not in {"BUY", "SELL", "HOLD"}:
            normalized_signal = "HOLD"

        previous_signal = state.last_signal

        state.status = "RUNNING"
        state.last_signal = normalized_signal
        state.last_signal_confidence = max(0.0, min(1.0, confidence))
        state.last_signal_repeat_count = max(1, int(repeat_count))
        state.last_signal_reason = reason or f"[DEBUG] SIGNAL {normalized_signal}"

        if previous_signal != normalized_signal or state.signal_started_at is None:
            state.signal_started_at = time.monotonic()

        self._update_decision_state(state, force_ready=force_ready)

        return state

    def set_signal_duration(
        self,
        *,
        signal: str,
        seconds: int,
        confidence: float = 0.0,
        force_ready: bool = False,
    ) -> DebugTradeState:
        repeat_count = max(1, int(max(0, seconds) / 5))

        state = self.set_signal(
            signal=signal,
            confidence=confidence,
            repeat_count=repeat_count,
            reason=f"[DEBUG] {signal.upper()} {seconds}s",
            force_ready=force_ready,
        )

        state.signal_started_at = time.monotonic() - max(0, seconds)

        return state

    def open_long(self) -> tuple[DebugTradeState, ExecutionDecision]:
        state = self.set_signal(
            signal="BUY",
            confidence=0.95,
            repeat_count=3,
            reason="[DEBUG] OPEN LONG",
            force_ready=True,
        )

        result = DebugExecutionEngine().process(state)
        return state, result

    def open_short(self) -> tuple[DebugTradeState, ExecutionDecision]:
        state = self.set_signal(
            signal="SELL",
            confidence=0.95,
            repeat_count=3,
            reason="[DEBUG] OPEN SHORT",
            force_ready=True,
        )

        result = DebugExecutionEngine().process(state)
        return state, result

    def flip(self) -> tuple[DebugTradeState, ExecutionDecision]:
        state = self.get_state()

        if state.position.side == "LONG":
            target_signal = "SELL"
        elif state.position.side == "SHORT":
            target_signal = "BUY"
        else:
            return state, ExecutionDecision(
                "NONE",
                False,
                "[DEBUG] Flip невозможен: нет открытой позиции.",
            )

        state = self.set_signal(
            signal=target_signal,
            confidence=0.95,
            repeat_count=3,
            reason="[DEBUG] AUTO FLIP",
            force_ready=True,
        )

        result = DebugExecutionEngine().process(state)
        return state, result

    def close(self, *, reason: str = "DEBUG_CLOSE") -> tuple[DebugTradeState, ExecutionDecision]:
        state = self.get_state()
        result = DebugExecutionEngine().close_position(state, forced_reason=reason)
        return state, result

    def update_market(self) -> DebugTradeState:
        state = self.get_state()

        state.last_check_at = datetime.now().strftime("%H:%M:%S")

        if state.status != "RUNNING":
            return state

        DebugExecutionEngine().update_unrealized_pnl(state)
        return state

    def process(self) -> tuple[DebugTradeState, ExecutionDecision]:
        state = self.get_state()

        state.last_check_at = datetime.now().strftime("%H:%M:%S")

        result = DebugExecutionEngine().process(state)
        return state, result

    def _update_decision_state(
        self,
        state: DebugTradeState,
        *,
        force_ready: bool = False,
    ) -> None:
        state.is_signal_confirmed = False
        state.is_signal_ready = False

        if state.last_signal == "HOLD":
            state.decision_status = "WAITING"
            state.decision_reason = "[DEBUG] Нет торгового направления."
            return

        if force_ready:
            state.is_signal_confirmed = True
            state.is_signal_ready = True
            state.decision_status = "READY"
            state.decision_reason = "[DEBUG] Signal forced READY."
            return

        if state.last_signal_repeat_count < self._confirm_repeats:
            state.decision_status = "CONFIRMING"
            state.decision_reason = (
                f"[DEBUG] Сигнал {state.last_signal} подтверждается: "
                f"{state.last_signal_repeat_count}/{self._confirm_repeats}."
            )
            return

        state.is_signal_confirmed = True

        if state.last_signal_confidence < self._ready_confidence:
            state.decision_status = "BLOCKED"
            state.decision_reason = (
                f"[DEBUG] Confidence низкая: "
                f"{state.last_signal_confidence:.2f} < {self._ready_confidence:.2f}."
            )
            return

        state.is_signal_ready = True
        state.decision_status = "READY"
        state.decision_reason = "[DEBUG] Signal ready."