from __future__ import annotations

from typing import Any, Callable

from app.services.scenes.gate_rules import GateRule, SceneRoute
from app.services.scenes.scene_descriptor import SceneDescriptor


class SceneRegistry:
    """场景注册表单例。

    所有场景在 import 时注册,门控/路由/执行/字段过滤全部从这里查询。
    gate_classify 节点是它的唯一消费者(单一决策点)。
    """

    def __init__(self) -> None:
        self._scenes: dict[str, SceneDescriptor] = {}
        self._flow_to_scene: dict[str, str] = {}

    # ---- 注册 ----

    def register(self, descriptor: SceneDescriptor) -> SceneDescriptor:
        self._scenes[descriptor.scene_id] = descriptor
        if descriptor.flow_id:
            self._flow_to_scene[descriptor.flow_id] = descriptor.scene_id
        return descriptor

    # ---- 查询 ----

    def get(self, scene_id: str) -> SceneDescriptor | None:
        return self._scenes.get(str(scene_id or "").strip())

    def all_scenes(self) -> list[SceneDescriptor]:
        return list(self._scenes.values())

    def scenes_sorted_by_priority(self) -> list[SceneDescriptor]:
        """按 priority 升序排列(数字小优先)。"""
        return sorted(self._scenes.values(), key=lambda s: s.priority)

    def all_scene_ids(self) -> list[str]:
        return [s.scene_id for s in self._scenes.values()]

    def all_assigned_agents(self) -> list[str]:
        return [s.assigned_agent for s in self._scenes.values() if s.assigned_agent]

    def all_flow_ids(self) -> list[str]:
        return [s.flow_id for s in self._scenes.values() if s.flow_id]

    def all_signal_keywords(self) -> set[str]:
        keywords: set[str] = set()
        for scene in self._scenes.values():
            keywords.update(scene.signal_keywords)
        return keywords

    def all_side_effect_actions(self) -> set[str]:
        actions: set[str] = set()
        for scene in self._scenes.values():
            actions.update(scene.side_effect_actions)
        return actions

    def all_noop_actions(self) -> set[str]:
        actions: set[str] = set()
        for scene in self._scenes.values():
            actions.update(scene.noop_actions)
        return actions

    def resolve_scene_by_action(self, action_type: str) -> SceneDescriptor | None:
        normalized = str(action_type or "").strip()
        for scene in self._scenes.values():
            if normalized in scene.side_effect_actions or normalized in scene.noop_actions:
                return scene
        return None

    def resolve_scene_by_flow(self, flow_id: str) -> SceneDescriptor | None:
        scene_id = self._flow_to_scene.get(str(flow_id or "").strip())
        return self.get(scene_id) if scene_id else None

    def field_allowlist_for(
        self,
        scene_id: str,
        *,
        fallback: frozenset[str] | None = None,
    ) -> frozenset[str]:
        scene = self.get(scene_id)
        if scene and scene.ontology_fields:
            return frozenset(scene.ontology_fields)
        return fallback or frozenset()

    def resumable_scenes(self) -> list[SceneDescriptor]:
        """返回所有声明了 can_resume=True 的场景。"""
        return [s for s in self._scenes.values() if s.can_resume]

    def prompt_fragments(self) -> str:
        """拼接所有场景的 prompt_fragment,供 system prompt 注入。"""
        fragments = [s.prompt_fragment for s in self._scenes.values() if s.prompt_fragment]
        return "".join(fragments)

    def intent_summary(self) -> str:
        """拼接场景列表摘要,供 system prompt 引用。"""
        fragments = [f"{s.scene_id}（{s.label}）" for s in self._scenes.values()]
        return "、".join(fragments) if fragments else "（暂无已注册场景）"


# 全局单例
REGISTRY = SceneRegistry()


def register_scene(descriptor: SceneDescriptor) -> SceneDescriptor:
    """注册场景到全局单例。"""
    return REGISTRY.register(descriptor)
