"""
Domain 注册中心

提供统一的 domain 组件注册和查询接口。
各模块（Collection/DataSource/Strategy）按需获取。

使用方式：
1. 在 domain/__init__.py 中注册所有组件
2. 各模块按需查询

示例：
    # 注册
    from ..common.registry import DomainRegistry
    from .contract import ContractSyncNode, ContractJsonlHandler
    
    DomainRegistry.register(
        node_type="contract",
        schema=ContractResponse,
        node_class=ContractSyncNode,
        jsonl_handler_class=ContractJsonlHandler,
    )
    
    # Collection 查询 SyncNode 类
    node_class = DomainRegistry.get_node_class("contract")
    
    # DataSource 查询 Handler
    handler_class = DomainRegistry.get_jsonl_handler("contract")
"""
from typing import Dict, Type, Optional, Any
from dataclasses import dataclass, field
from pydantic import BaseModel


@dataclass
class DomainRegistration:
    """
    单个 domain 的注册信息
    
    包含：
    - node_class: SyncNode 子类（用于 Collection 恢复）
    - strategy_class: Strategy 子类（用于 SyncSystem 初始化）
    - handlers: 各种 Handler（用于 DataSource 初始化）
    """
    node_type: str
    schema: Type[BaseModel]
    node_class: Type[Any]  # Type[SyncNode[T]]，避免循环导入
    strategy_class: Optional[Type[Any]] = None  # 可选，部分 domain 可能只读
    jsonl_handler_class: Optional[Type[Any]] = None
    api_handler_class: Optional[Type[Any]] = None
    handler_classes: Dict[str, Type[Any]] = field(default_factory=dict)
    metadata: Dict[str, Any] = field(default_factory=dict)  # 额外元数据


class DomainRegistry:
    """
    Domain 注册中心
    
    职责分离：
    - Collection: 只关心 SyncNode 类（恢复类型）
    - DataSource: 只关心 Handler 类（执行层）
    - Strategy: 只关心 Strategy 类（业务逻辑）
    
    每个 domain 只注册一次，各模块按需获取。
    """
    
    _registry: Dict[str, DomainRegistration] = {}

    _BUILTIN_HANDLER_ATTRS: Dict[str, str] = {
        "jsonl": "jsonl_handler_class",
        "api": "api_handler_class",
    }
    
    @classmethod
    def register(
        cls,
        node_type: str,
        schema: Type[BaseModel],
        node_class: Type[Any],
        strategy_class: Optional[Type[Any]] = None,
        jsonl_handler_class: Optional[Type[Any]] = None,
        api_handler_class: Optional[Type[Any]] = None,
        **metadata
    ) -> None:
        """
        注册一个 domain
        
        Args:
            node_type: 节点类型（如 "contract"）
            schema: Pydantic Schema 类
            node_class: SyncNode 子类
            strategy_class: Strategy 子类（可选）
            jsonl_handler_class: JSONL Handler 类（可选）
            api_handler_class: API Handler 类（可选）
            **metadata: 额外的元数据
            
        Raises:
            ValueError: 如果 node_type 已注册
        """
        if node_type in cls._registry:
            raise ValueError(f"Domain '{node_type}' already registered")
        
        reg = DomainRegistration(
            node_type=node_type,
            schema=schema,
            node_class=node_class,
            strategy_class=strategy_class,
            jsonl_handler_class=jsonl_handler_class,
            api_handler_class=api_handler_class,
            metadata=metadata
        )
        for datasource_type, attr_name in cls._BUILTIN_HANDLER_ATTRS.items():
            handler_class = getattr(reg, attr_name)
            if handler_class is not None:
                reg.handler_classes[datasource_type] = handler_class

        cls._registry[node_type] = reg
    
    @classmethod
    def get_node_class(cls, node_type: str) -> Type[Any]:
        """
        获取 SyncNode 类（用于 Collection 恢复）
        
        Args:
            node_type: 节点类型
            
        Returns:
            SyncNode 子类
            
        Raises:
            ValueError: 如果 node_type 未注册
        """
        reg = cls._registry.get(node_type)
        if not reg:
            raise ValueError(f"Unknown node_type: '{node_type}'. Available: {list(cls._registry.keys())}")
        return reg.node_class
    
    @classmethod
    def get_strategy_class(cls, node_type: str) -> Optional[Type[Any]]:
        """
        获取 Strategy 类（用于 SyncSystem）
        
        Args:
            node_type: 节点类型
            
        Returns:
            Strategy 类，如果未注册则返回 None
        """
        reg = cls._registry.get(node_type)
        if not reg:
            raise ValueError(f"Unknown node_type: '{node_type}'")
        return reg.strategy_class
    
    @classmethod
    def get_handler(
        cls,
        node_type: str,
        datasource_type: str,
    ) -> Optional[Type[Any]]:
        """按 datasource 类型获取 Handler 类。"""
        reg = cls._registry.get(node_type)
        if not reg:
            raise ValueError(f"Unknown node_type: '{node_type}'")
        handler_class = reg.handler_classes.get(datasource_type)
        if handler_class is not None:
            return handler_class

        attr_name = cls._BUILTIN_HANDLER_ATTRS.get(datasource_type)
        if attr_name is None:
            return None
        return getattr(reg, attr_name)

    @classmethod
    def register_handler(cls, node_type: str, datasource_type: str, handler_class: Type[Any]) -> None:
        """为已注册 domain 补充任意 datasource 类型的 Handler。"""
        reg = cls._registry.get(node_type)
        if not reg:
            raise ValueError(f"Unknown node_type: '{node_type}'")

        reg.handler_classes[datasource_type] = handler_class
        attr_name = cls._BUILTIN_HANDLER_ATTRS.get(datasource_type)
        if attr_name is not None:
            setattr(reg, attr_name, handler_class)

    @classmethod
    @classmethod
    def get_schema(cls, node_type: str) -> Type[BaseModel]:
        """获取 Schema 类"""
        reg = cls._registry.get(node_type)
        if not reg:
            raise ValueError(f"Unknown node_type: '{node_type}'")
        return reg.schema
    
    @classmethod
    def get_registration(cls, node_type: str) -> DomainRegistration:
        """获取完整的注册信息"""
        reg = cls._registry.get(node_type)
        if not reg:
            raise ValueError(f"Unknown node_type: '{node_type}'")
        return reg
    
    @classmethod
    def is_registered(cls, node_type: str) -> bool:
        """检查 node_type 是否已注册"""
        return node_type in cls._registry
    
    @classmethod
    def list_registered(cls) -> list[str]:
        """列出所有已注册的 node_type"""
        return list(cls._registry.keys())
    
    @classmethod
    def get_registered_types(cls) -> list[str]:
        """列出所有已注册的 node_type（list_registered 的别名）"""
        return cls.list_registered()
    
    @classmethod
    def clear(cls) -> None:
        """清空注册表（仅用于测试）"""
        cls._registry.clear()
    
    @classmethod
    def print_registry(cls) -> None:
        """打印所有注册的 domain 信息（用于调试）"""
        if not cls._registry:
            print("⚠️ DomainRegistry is empty - no domains registered")
            return
        
        print(f"\n{'='*80}")
        print(f"📋 DomainRegistry - {len(cls._registry)} domain(s) registered")
        print(f"{'='*80}\n")
        
        for node_type, reg in sorted(cls._registry.items()):
            print(f"🔹 {node_type}")
            print(f"   Schema:           {reg.schema.__name__}")
            print(f"   Node Class:       {reg.node_class.__name__}")
            print(f"   Strategy Class:   {reg.strategy_class.__name__ if reg.strategy_class else '❌ None'}")
            print(f"   JSONL Handler:    {reg.jsonl_handler_class.__name__ if reg.jsonl_handler_class else '❌ None'}")
            print(f"   API Handler:      {reg.api_handler_class.__name__ if reg.api_handler_class else '❌ None'}")
            extra_handler_types = sorted(
                handler_type for handler_type in reg.handler_classes if handler_type not in cls._BUILTIN_HANDLER_ATTRS
            )
            if extra_handler_types:
                print(f"   Extra Handlers:   {extra_handler_types}")
            if reg.metadata:
                print(f"   Metadata:         {reg.metadata}")
            print()
        
        print(f"{'='*80}\n")
    
    @classmethod
    def get_summary(cls) -> Dict[str, Dict[str, Any]]:
        """
        获取注册摘要（用于自动化检查）
        
        Returns:
            字典，key 为 node_type，value 为各组件的注册状态
            
        Example:
            {
                "contract": {
                    "has_node": True,
                    "has_strategy": True,
                    "has_jsonl_handler": True,
                    "has_api_handler": True,
                    "handler_types": []
                },
                ...
            }
        """
        summary = {}
        for node_type, reg in cls._registry.items():
            summary[node_type] = {
                "has_node": reg.node_class is not None,
                "has_strategy": reg.strategy_class is not None,
                "has_jsonl_handler": reg.jsonl_handler_class is not None,
                "has_api_handler": reg.api_handler_class is not None,
                "handler_types": sorted(reg.handler_classes.keys()),
            }
        return summary
