# app/src/trading/market_intelligence/common/events.py

from __future__ import annotations

from dataclasses import dataclass, field
from time import time

from src.trading.market_intelligence.common.models import EngineResult
from src.trading.market_intelligence.common.payloads import (
    engine_result_to_payload,
)
from src.trading.market_intelligence.common.snapshots import (
    EngineSnapshot,
    build_engine_snapshot,
    engine_snapshot_to_payload,
)
from src.trading.market_intelligence.common.types import (
    EngineName,
    PayloadDict,
    SymbolName,
    TimeframeName,
)


@dataclass(frozen=True, slots=True)
class MarketIntelligenceEvent:
    # Событие Market Intelligence описывает факт завершения
    # аналитического действия.
    #
    # Важно: этот объект сам ничего не публикует.
    # Он только задаёт единый формат события, который позже сможет
    # использовать EventBus, журнал или Runtime.
    event_type: str
    engine_name: EngineName
    symbol: SymbolName
    timeframe: TimeframeName
    created_at: float
    payload: PayloadDict = field(default_factory=dict)


def build_engine_result_event(
    result: EngineResult,
    *,
    event_type: str = "market_intelligence.engine_result",
) -> MarketIntelligenceEvent:
    # Формирует событие напрямую из EngineResult.
    #
    # Используется, когда нужно зафиксировать сам факт получения
    # результата Engine без отдельного Snapshot.
    return MarketIntelligenceEvent(
        event_type=event_type,
        engine_name=result.engine_name,
        symbol=result.symbol,
        timeframe=result.timeframe,
        created_at=time(),
        payload=engine_result_to_payload(result),
    )


def build_engine_snapshot_event(
    snapshot: EngineSnapshot,
    *,
    event_type: str = "market_intelligence.engine_snapshot",
) -> MarketIntelligenceEvent:
    # Формирует событие из уже созданного Snapshot.
    #
    # Такой вариант нужен, когда сначала фиксируется состояние результата,
    # а уже затем это состояние передаётся во внешний слой событий.
    return MarketIntelligenceEvent(
        event_type=event_type,
        engine_name=snapshot.engine_name,
        symbol=snapshot.symbol,
        timeframe=snapshot.timeframe,
        created_at=time(),
        payload=engine_snapshot_to_payload(snapshot),
    )


def build_result_snapshot_event(
    result: EngineResult,
    *,
    event_type: str = "market_intelligence.engine_snapshot",
) -> MarketIntelligenceEvent:
    # Удобный безопасный путь:
    # EngineResult -> EngineSnapshot -> Event.
    #
    # Это сохраняет единый порядок фиксации результата анализа.
    snapshot = build_engine_snapshot(result)

    return build_engine_snapshot_event(
        snapshot,
        event_type=event_type,
    )


def market_intelligence_event_to_payload(
    event: MarketIntelligenceEvent,
) -> PayloadDict:
    # Преобразует событие в обычный словарь.
    #
    # Функция нужна для будущей передачи события в журнал,
    # EventBus или внешний Runtime-слой.
    return {
        "event_type": event.event_type,
        "engine_name": event.engine_name,
        "symbol": event.symbol,
        "timeframe": event.timeframe,
        "created_at": event.created_at,
        "payload": event.payload,
    }