"""
task_type_registry.py — Task type handler Protocol + Registry.

启动时一次性加载 handler，运行时只读。
零依赖：不导入项目内其他模块。
"""

from __future__ import annotations

import logging
from pathlib import Path
from typing import TYPE_CHECKING, Dict, Optional, Protocol, runtime_checkable

if TYPE_CHECKING:
    from src.daemon.prompt_composer import PromptContext

logger = logging.getLogger("moziplus-v2.registry")


# ---------------------------------------------------------------------------
# Protocol
# ---------------------------------------------------------------------------

@runtime_checkable
class TaskTypeHandler(Protocol):
    """所有 task type handler 的统一接口。"""

    # 属性（通过 __init__ 设置）
    task_type: str  # 类型标识：'task' | 'mail' | 'toolchain'
    virtual_project: Optional[str]  # 虚拟项目 ID，如 '_mail'、'_toolchain'。普通任务为 None

    def build_prompt(self, context: "PromptContext") -> str:
        """构建 Agent prompt（通过 PromptComposer 拼 section）。"""
        ...

    def pre_spawn(self, task_id: str, db_path: Path) -> bool:
        """spawn 前业务准备。默认 True，mail/toolchain override 为 auto_working。"""
        ...

    def post_complete(
        self,
        task_id: str,
        agent_id: str,
        outcome: str,
        db_path: Path,
    ) -> None:
        """spawn 完成后的业务处理。统一流程：crash→verify→mark→notify。"""
        ...

    def check_completion(self, task_id: str, db_path: Path) -> bool:
        """ticker 级别的完成检查。"""
        ...

    def get_sections(self) -> list:
        """返回此 handler 的 prompt section 列表。"""
        ...


# ---------------------------------------------------------------------------
# Registry
# ---------------------------------------------------------------------------

class TaskTypeRegistry:
    """Task type handler 注册表。启动时一次性加载，运行时只读。"""

    _handlers: Dict[str, TaskTypeHandler] = {}

    @classmethod
    def register(cls, handler: TaskTypeHandler) -> None:
        """注册一个 handler。启动时调用一次。"""
        if handler.task_type in cls._handlers:
            raise ValueError(f"Task type '{handler.task_type}' already registered")
        cls._handlers[handler.task_type] = handler
        vp = getattr(handler, "virtual_project", None)
        logger.info("Registered task type handler: %s (virtual_project=%s)", handler.task_type, vp)

    @classmethod
    def get_by_project(cls, project_id: str) -> Optional[TaskTypeHandler]:
        """通过 project_id 查找 handler（匹配 virtual_project）。"""
        for h in cls._handlers.values():
            if h.virtual_project == project_id:
                return h
        return None

    @classmethod
    def get(cls, task_type: str) -> Optional[TaskTypeHandler]:
        """通过 task_type 标识查找 handler。"""
        return cls._handlers.get(task_type)

    @classmethod
    def virtual_projects(cls) -> list[str]:
        """返回所有已注册的虚拟项目 ID（ticker 自动发现用）。"""
        return [
            h.virtual_project
            for h in cls._handlers.values()
            if h.virtual_project is not None
        ]

    @classmethod
    def clear(cls) -> None:
        """清空注册表（仅测试用）。"""
        cls._handlers = {}
