"""
Contextra AI Analytics — Scenario Registry

역할:
  - @register_scenario 데코레이터로 시나리오 엔진 자동 등록
  - registry 검증 (fail-fast)
  - strategy map / dependency map 제공
"""

from __future__ import annotations

import logging
from typing import Any, Callable, Dict, List


logger = logging.getLogger(__name__)

_SCENARIO_REGISTRY: Dict[str, Dict[str, Any]] = {}


def register_scenario(
    name: str,
    dependencies: List[str] | None = None,
    severity_map: Dict[str, str] | None = None,
    cooldown_seconds: float = 30.0,
    zone_name: str | None = None,
) -> Callable[[type], type]:
    """시나리오 엔진 클래스를 registry에 등록하는 데코레이터.

    v2 구동 정책 — 선언적 의존성 (ai_engine 철학 이식):
      - dependencies: 시나리오가 요구하는 det 클래스 목록.
        플랫폼이 capability × deps 교집합으로 활성화를 해석한다.
      - zone_name: 요구 논리 zone 이름 (None이면 zone 불필요).
        미정의 스트림은 resolve_activation에서 명시적 사유로 비활성화된다.

    검증 정책 (lenient):
      - AbstractScenario 상속 여부 확인하지만, 상속하지 않아도 evaluate() 메서드가 있으면 등록 허용
      - 이는 시나리오 엔진이 import 순환을 피하기 위해 standalone 클래스로 작성할 수 있게 함
    """
    def decorator(cls: type) -> type:
        # AbstractScenario가 아직 import되지 않았을 수 있으므로 deferred check
        has_abstract = False
        try:
            from .base_scenario import AbstractScenario as _AS
            if issubclass(cls, _AS):
                has_abstract = True
        except (ImportError, TypeError):
            pass

        # evaluate() 메서드가 있는지 확인 (minimum contract)
        if not hasattr(cls, "evaluate"):
            raise TypeError(f"@register_scenario target {name} must have an evaluate method")

        _SCENARIO_REGISTRY[name] = {
            "class": cls,
            "dependencies": dependencies or [],
            "severity_map": severity_map or {},
            "cooldown_seconds": cooldown_seconds,
            # v2 — zone 요구 선언 (None이면 zone 불필요).
            "zone_name": zone_name,
            "has_abstract_base": has_abstract,
        }
        logger.info("[registry] Registered scenario %s (deps=%s zone=%s)", name, dependencies or [], zone_name)
        return cls
    return decorator


def get_registered_scenarios() -> List[str]:
    return list(_SCENARIO_REGISTRY.keys())


# ============================================================================
# Standalone API functions
# ============================================================================

def _validate_registry():
    if not _SCENARIO_REGISTRY:
        logger.warning("[registry] No scenarios registered")


def get_strategy_map() -> Dict[str, Callable]:
    """시나리오 이름 → 인스턴스 매핑."""
    _validate_registry()
    return {name: entry["class"]() for name, entry in _SCENARIO_REGISTRY.items()}


def get_class_map() -> Dict[str, type]:
    """v2 — 시나리오 이름 → 엔진 클래스 (인스턴스화 전). cfg 주입용."""
    _validate_registry()
    return {name: entry["class"] for name, entry in _SCENARIO_REGISTRY.items()}


def get_dependency_map() -> Dict[str, List[str]]:
    """시나리오 이름 → required_classes 매핑."""
    _validate_registry()
    return {name: entry["dependencies"] for name, entry in _SCENARIO_REGISTRY.items()}


def get_registry_meta() -> Dict[str, Dict[str, Any]]:
    """v2 — 활성화 해석용 metadata (policy.resolve_activation 입력).

    Returns:
        {name: {"class": cls, "dependencies": [...], "zone_name": str|None}}
    """
    _validate_registry()
    return {
        name: {
            "class": entry["class"],
            "dependencies": list(entry["dependencies"]),
            "zone_name": entry.get("zone_name"),
        }
        for name, entry in _SCENARIO_REGISTRY.items()
    }
