# -*- coding: utf-8 -*-
"""subagent protocol 模块测试"""
import json
from abyss.subagent.protocol import (
    TaskStatus,
    TaskDefinition,
    TaskResult,
    SubAgentProtocol,
)


class TestTaskDefinition:
    """TaskDefinition 序列化测试"""

    def test_minimal_dict(self):
        td = TaskDefinition(task="analyze code")
        d = td.to_dict()
        assert d["task"] == "analyze code"
        assert "sub_id" in d

    def test_full_dict_roundtrip(self):
        td = TaskDefinition(
            task="fix bug",
            sub_id="42",
            context="src/main.py",
            methodology="debug",
            metadata={"priority": "high"},
        )
        d = td.to_dict()
        td2 = TaskDefinition.from_dict(d)
        assert td2.task == "fix bug"
        assert td2.sub_id == "42"
        assert td2.context == "src/main.py"
        assert td2.methodology == "debug"
        assert td2.metadata == {"priority": "high"}

    def test_defaults(self):
        td = TaskDefinition(task="test")
        assert td.sub_id == ""
        assert td.context == ""
        assert td.methodology is None
        assert td.metadata == {}


class TestTaskResult:
    """TaskResult 序列化测试"""

    def test_success_factory(self):
        r = TaskResult.success(sub_id="1", output="all good", duration_ms=150, tool_rounds=3)
        assert r.is_success is True
        assert r.is_failed is False
        assert r.output == "all good"
        assert r.duration_ms == 150
        assert r.tool_rounds == 3

    def test_failure_factory(self):
        r = TaskResult.failure(sub_id="2", error="something broke")
        assert r.is_success is False
        assert r.is_failed is True
        assert r.error == "something broke"
        assert r.output == ""

    def test_timeout_factory(self):
        r = TaskResult.timeout(sub_id="3", max_rounds=30)
        assert r.status == TaskStatus.TIMEOUT
        assert "30" in r.error

    def test_to_dict_roundtrip(self):
        r = TaskResult.success(sub_id="1", output="ok", duration_ms=100)
        d = r.to_dict()
        r2 = TaskResult.from_dict(d)
        assert r2.status == TaskStatus.SUCCESS
        assert r2.output == "ok"
        assert r2.duration_ms == 100

    def test_dict_with_status_string(self):
        """status 字段是字符串值，能正确反序列化。"""
        r = TaskResult.failure(sub_id="x", error="fail")
        d = r.to_dict()
        assert d["status"] == "failed"
        r2 = TaskResult.from_dict(d)
        assert r2.status == TaskStatus.FAILED

    def test_unknown_status_defaults_to_failed(self):
        r = TaskResult.from_dict({"status": "bogus", "error": "?"})
        assert r.status == TaskStatus.FAILED

    def test_cancelled_status(self):
        r = TaskResult(status=TaskStatus.CANCELLED, sub_id="4", error="esc")
        d = r.to_dict()
        r2 = TaskResult.from_dict(d)
        assert r2.status == TaskStatus.CANCELLED


class TestSubAgentProtocol:
    """SubAgentProtocol 编解码测试"""

    def test_encode_decode_task(self):
        td = TaskDefinition(task="search code", context="src/", methodology="architecture")
        json_str = SubAgentProtocol.encode_task(td)
        assert "protocol" in json_str
        assert "subagent" in json_str
        assert "version" in json_str

        td2 = SubAgentProtocol.decode_task(json_str)
        assert td2.task == "search code"
        assert td2.context == "src/"
        assert td2.methodology == "architecture"

    def test_encode_task_auto_sub_id(self):
        td = TaskDefinition(task="hello")
        json_str = SubAgentProtocol.encode_task(td)
        payload = json.loads(json_str)
        assert len(payload["task"]["sub_id"]) == 8  # UUID[:8]

    def test_encode_decode_result(self):
        r = TaskResult.success(sub_id="5", output="done", duration_ms=200)
        json_str = SubAgentProtocol.encode_result(r)
        r2 = SubAgentProtocol.decode_result(json_str)
        assert r2.status == TaskStatus.SUCCESS
        assert r2.output == "done"
        assert r2.duration_ms == 200

    def test_build_summary_all_success(self):
        results = [
            TaskResult.success("1", "a"),
            TaskResult.success("2", "b"),
            TaskResult.success("3", "c"),
        ]
        summary = SubAgentProtocol.build_summary(results)
        assert "全部成功" in summary

    def test_build_summary_mixed(self):
        results = [
            TaskResult.success("1", "a"),
            TaskResult.failure("2", "error in 2"),
            TaskResult.success("3", "c"),
        ]
        summary = SubAgentProtocol.build_summary(results)
        assert "成功 2" in summary
        assert "失败 1" in summary
        assert "error in 2" in summary

    def test_build_summary_truncates_many_failures(self):
        """超过5个失败项时截断。"""
        results = [TaskResult.failure(str(i), f"error {i}") for i in range(10)]
        summary = SubAgentProtocol.build_summary(results)
        assert "还有" in summary
