# app/src/trading/auto/execution_semantic.py

from __future__ import annotations

from src.integrations.exchange.status import ExchangeStatusCode
from src.trading.auto.state import AutoTradeState


class AutoExecutionSemanticMixin:
    _execution_confidence_required_score: float

    # синхронизировать semantic-статус execution слоя для UI
    def _sync_execution_semantic_state(self, state: AutoTradeState) -> None:
        if state.execution_block_reason:
            state.execution_semantic_status = "BLOCKED"
            state.execution_semantic_message = (
                f"⛔ Исполнение · {state.execution_block_message}"
                if state.execution_block_message
                else "⛔ Исполнение · заблокировано"
            )
            state.execution_semantic_reason = state.execution_block_reason
            return

        if state.execution_quality == "BLOCKED":
            state.execution_semantic_status = "BLOCKED"
            state.execution_semantic_message = self._execution_block_semantic_message(state)
            state.execution_semantic_reason = state.execution_quality_reason
            return

        if state.decision_status == "BLOCKED":
            state.execution_semantic_status = "BLOCKED"

            if (
                state.execution_confidence_score is not None
                and state.execution_confidence_score < self._execution_confidence_required_score
            ):
                state.execution_semantic_message = "⛔ Исполнение · низкая уверенность"
                state.execution_semantic_reason = state.execution_confidence_reason
                return

            state.execution_semantic_message = "⛔ Исполнение · сигнал заблокирован"
            state.execution_semantic_reason = state.decision_reason
            return

        if state.position_side != "NONE":
            state.execution_semantic_status = "POSITION_OPEN"
            state.execution_semantic_message = "📌 Исполнение · позиция открыта"
            state.execution_semantic_reason = state.last_execution_reason
            return

        if state.decision_status == "READY" and state.is_signal_ready:
            state.execution_semantic_status = "READY"
            state.execution_semantic_message = "✅ Исполнение · готово"
            state.execution_semantic_reason = state.decision_reason
            return

        if state.decision_status == "CONFIRMING":
            state.execution_semantic_status = "WAITING_SIGNAL"
            state.execution_semantic_message = "⏳ Исполнение · ждёт подтверждения"
            state.execution_semantic_reason = state.decision_reason
            return

        if state.last_signal in {"BUY", "SELL"}:
            state.execution_semantic_status = "WAITING_SIGNAL"
            state.execution_semantic_message = "⏳ Исполнение · сигнал проверяется"
            state.execution_semantic_reason = state.decision_reason
            return

        state.execution_semantic_status = "IDLE"
        state.execution_semantic_message = ""
        state.execution_semantic_reason = state.decision_reason

    # вернуть человекочитаемое сообщение блокировки execution слоя
    def _execution_block_semantic_message(self, state: AutoTradeState) -> str:
        reason = str(state.execution_quality_reason or "")
        message = str(state.execution_quality_message or "")

        if self._is_exchange_unavailable(reason):
            return "⛔ Исполнение · биржа недоступна"

        if self._is_exchange_break(reason):
            return "⏸️ Исполнение · перерыв на бирже"

        if self._is_auth_error(reason):
            return "⛔ Исполнение · неверный API Key"

        if reason == "STALE_SNAPSHOT":
            return "⛔ Исполнение · рынок неактуален"

        if reason == "HIGH_SPREAD":
            return "⛔ Исполнение · высокий spread"

        if reason == "SNAPSHOT_ERROR":
            return "⛔ Исполнение · нет данных рынка"

        if reason == "SNAPSHOT_UNAVAILABLE":
            return "⚠️ Исполнение · нет стакана"

        if message:
            return f"⛔ Исполнение · {message}"

        return "⛔ Исполнение · заблокировано"

    # проверить, что блокировка пришла из единого exchange status layer
    def _is_exchange_unavailable(self, reason: str) -> bool:
        # Поддерживаем оба формата:
        # 1) внутренние execution reason: EXCHANGE_UNAVAILABLE / TIME_ERROR
        # 2) значения ExchangeStatusCode, если они попадут сюда напрямую.
        return reason in {
            "EXCHANGE_UNAVAILABLE",
            "TIME_ERROR",
            ExchangeStatusCode.EXCHANGE_UNAVAILABLE.value,
            ExchangeStatusCode.TIME_ERROR.value,
        }

    # проверить, что причина блокировки — торговый перерыв, а не ошибка доступа
    def _is_exchange_break(self, reason: str) -> bool:
        # AutoExecutionQualityMixin сейчас кладёт MARKET_BREAK,
        # а ExchangeStatusCode может прийти как BREAK.
        return reason in {
            "MARKET_BREAK",
            ExchangeStatusCode.BREAK.value,
        }

    # проверить ошибку приватного доступа / API key
    def _is_auth_error(self, reason: str) -> bool:
        # Поддерживаем внутренний AUTH_ERROR и enum-value.
        return reason in {
            "AUTH_ERROR",
            ExchangeStatusCode.AUTH_ERROR.value,
        }