"""`SpecResolver`：内置 + 用户 skill 的统一只读解析入口（Prompt 外置方案A · 步4）。

内置 Agent（`SPECS`，纯内存）与用户 Skill（`SkillRegistry`，DB）二者都产出 `AgentSpec`。
resolver 提供统一 `.get(name)`：

- **内置优先、零 DB**：先查内置 `SPECS`（纯内存查表）；命中内置 name 时**绝不触发**任何
  `SkillRegistry` 调用（评审 HIGH / 不变量 #3：四审 prompt 不被用户 skill 偷换的安全边界，
  其守卫前移在 `SkillRegistry` 入库期，故读路径对内置永远是确定性纯内存）。
- 未命中内置才查 `SkillRegistry`；都无 → `AppError(NOT_FOUND)`。

`build` 是**纯合并**，不做保留名冲突校验（守卫前移至 `SkillRegistry.load`）。
`output_schema_for`：内置 → `SCHEMA_CATALOG[name]` 真类；纯用户 skill → None。
name 语义锁死为**精确字符串相等**（无大小写折叠、无连字符归一、无模糊匹配）。

不可变：`build` 用 `dict(SPECS)` 复制一份内置快照，resolver 不改入参。
"""

from __future__ import annotations

from pydantic import BaseModel
from ww_agents import SCHEMA_CATALOG, SPECS, AgentSpec

from ww_skills.skill_registry import SkillRegistryLike


class SpecResolver:
    """内置（SPECS，纯内存）+ 用户 skill（SkillRegistry，DB）的统一只读解析入口。"""

    def __init__(self, builtin: dict[str, AgentSpec], skills: SkillRegistryLike) -> None:
        self._builtin = builtin
        self._skills = skills

    @classmethod
    def build(cls, skills: SkillRegistryLike) -> SpecResolver:
        """纯合并：拷贝内置 SPECS 快照 + 持有 SkillRegistry（不做冲突校验，守卫已前移）。"""
        return cls(builtin=dict(SPECS), skills=skills)

    def get(self, name: str) -> AgentSpec:
        """先查内置（纯内存、零 DB）；未命中才查 SkillRegistry；都无 → NOT_FOUND。

        命中内置 name 时**绝不触发** SkillRegistry 调用（确定性 + 安全边界）。
        """
        builtin = self._builtin.get(name)
        if builtin is not None:
            return builtin
        return self._skills.get(name)

    def output_schema_for(self, name: str) -> type[BaseModel] | None:
        """命中内置 → SCHEMA_CATALOG[name]；纯用户 skill / 未知 → None。

        精确字符串相等命中——拼错近似 name（如 `character_gen` vs `character-gen`）→ None
        不报错（预期行为，非 bug）。
        """
        if name in self._builtin:
            return SCHEMA_CATALOG[name]
        return None

    def names(self) -> list[str]:
        """内置 + 用户 skill 的全部 name（去重、排序）。"""
        return sorted(set(self._builtin) | set(self._skills.names()))

    def list_scope(self, scope: str) -> list[AgentSpec]:
        """按 scope 过滤内置 + 用户 skill，按 name 排序。"""
        merged = [s for s in self._builtin.values() if s.scope == scope]
        merged.extend(self._skills.list_scope(scope))
        return sorted(merged, key=lambda s: s.name)
