"""SkillConfig v7 preconditions + provenance 字段单元测试"""

import pytest

from agentkit.core.exceptions import ConfigValidationError
from agentkit.skills.base import SkillConfig

# llm_generate 模式要求 prompt，所有构造提供最小 prompt
_PROMPT = {"identity": "test"}
_BASE = {"name": "x", "agent_type": "y", "task_mode": "llm_generate", "prompt": _PROMPT}


class TestSkillConfigPreconditions:
    """v7 preconditions / provenance 字段测试"""

    def test_construct_with_preconditions_and_provenance(self):
        config = SkillConfig(
            name="x",
            agent_type="y",
            task_mode="llm_generate",
            prompt=_PROMPT,
            preconditions=["用户已登录", "当前分支非 main"],
            provenance="yaml:test.yaml",
        )
        assert config.preconditions == ["用户已登录", "当前分支非 main"]
        assert config.provenance == "yaml:test.yaml"

    def test_from_dict_backward_compatible_defaults(self):
        """旧 YAML 无 preconditions/provenance 字段时取默认值"""
        config = SkillConfig.from_dict(dict(_BASE))
        assert config.preconditions is None
        assert config.provenance == ""

    def test_from_dict_with_new_fields(self):
        data = dict(_BASE)
        data["preconditions"] = ["需要网络连接"]
        data["provenance"] = "entry_point:my_skill"
        config = SkillConfig.from_dict(data)
        assert config.preconditions == ["需要网络连接"]
        assert config.provenance == "entry_point:my_skill"

    def test_to_dict_contains_new_fields(self):
        config = SkillConfig(
            name="x",
            agent_type="y",
            task_mode="llm_generate",
            prompt=_PROMPT,
            preconditions=["条件A"],
            provenance="yaml:a.yaml",
        )
        d = config.to_dict()
        assert d["preconditions"] == ["条件A"]
        assert d["provenance"] == "yaml:a.yaml"

    def test_to_dict_none_vs_empty_list_distinct(self):
        """preconditions=None 与 preconditions=[] 在 to_dict 中区分保留"""
        none_cfg = SkillConfig(
            name="x", agent_type="y", task_mode="llm_generate", prompt=_PROMPT, preconditions=None
        )
        empty_cfg = SkillConfig(
            name="x", agent_type="y", task_mode="llm_generate", prompt=_PROMPT, preconditions=[]
        )
        assert none_cfg.to_dict()["preconditions"] is None
        assert empty_cfg.to_dict()["preconditions"] == []

    def test_to_dict_default_provenance(self):
        config = SkillConfig(name="x", agent_type="y", task_mode="llm_generate", prompt=_PROMPT)
        assert config.to_dict()["provenance"] == ""

    def test_round_trip_from_dict_to_dict(self):
        data = dict(_BASE)
        data["preconditions"] = ["条件1", "条件2"]
        data["provenance"] = "skill_md:foo.md"
        config = SkillConfig.from_dict(data)
        out = config.to_dict()
        assert out["preconditions"] == ["条件1", "条件2"]
        assert out["provenance"] == "skill_md:foo.md"

    def test_preconditions_string_type_rejected(self):
        """preconditions 传字符串应抛 ConfigValidationError（防止逐字符迭代）"""
        with pytest.raises(ConfigValidationError, match="preconditions"):
            SkillConfig(
                name="x",
                agent_type="y",
                task_mode="llm_generate",
                prompt=_PROMPT,
                preconditions="必须提供代码",  # type: ignore[arg-type]
            )

    def test_preconditions_dict_type_rejected(self):
        """preconditions 传 dict 应抛 ConfigValidationError"""
        with pytest.raises(ConfigValidationError, match="preconditions"):
            SkillConfig(
                name="x",
                agent_type="y",
                task_mode="llm_generate",
                prompt=_PROMPT,
                preconditions={"key": "val"},  # type: ignore[arg-type]
            )
