# app/src/trading/market_intelligence/runtime/service.py

from __future__ import annotations

import time

from src.trading.market_intelligence.common.models import (
    EngineContext,
    EngineRegistration,
    RuntimeResult,
)
from src.trading.market_intelligence.common.types import EngineName
from src.trading.market_intelligence.engine.protocol import EngineProtocol
from src.trading.market_intelligence.runtime.dependencies import RuntimeDependencies
from src.trading.market_intelligence.runtime.registry import RuntimeRegistry
from src.trading.market_intelligence.runtime.runner import RuntimeRunner
from src.trading.market_intelligence.runtime.validation import RuntimeValidation


class RuntimeService:
    """Единая публичная точка входа Runtime Layer."""

    def __init__(self) -> None:
        """Создать Runtime Service."""
        self._registry = RuntimeRegistry()
        self._validation = RuntimeValidation()
        self._dependencies = RuntimeDependencies()
        self._runner = RuntimeRunner()

    def register_engine(
        self,
        engine_type: type[EngineProtocol],
    ) -> None:
        """Зарегистрировать класс Engine."""
        self._registry.register(engine_type)

    def unregister_engine(
        self,
        engine_name: EngineName,
    ) -> None:
        """Удалить Engine из Runtime."""
        self._registry.unregister(engine_name)

    def get_engine(
        self,
        engine_name: EngineName,
    ) -> EngineRegistration | None:
        """Вернуть регистрацию Engine по имени."""
        return self._registry.get(engine_name)

    async def analyze(
        self,
        context: EngineContext,
    ) -> RuntimeResult:
        """Выполнить анализ через зарегистрированные Engine."""
        started_at = time.time()

        self._validation.validate(self._registry)

        registrations = self._registry.list()
        ordered_registrations = self._dependencies.resolve(registrations)

        engine_results = []

        for registration in ordered_registrations:
            result = await self._runner.run(
                registration=registration,
                context=context,
            )
            engine_results.append(result)

        finished_at = time.time()

        return RuntimeResult(
            engine_results=tuple(engine_results),
            started_at=started_at,
            finished_at=finished_at,
            duration_ms=(finished_at - started_at) * 1000,
            metadata={
                "runtime_component": "RuntimeService",
            },
        )