# -*- coding: utf-8 -*-
"""
CuratorDaemon 集成 KnowledgeCurator 测试
验证守护线程在每轮循环中同时管理 skill 和 knowledge 生命周期。
"""
from unittest.mock import MagicMock, patch

import pytest

from abyss.curator import CuratorDaemon


class TestCuratorDaemonKnowledgeIntegration:
    """CuratorDaemon 接收可选 knowledge_curator 参数。"""

    def test_accepts_knowledge_curator_param(self):
        """构造函数接收 knowledge_curator 参数并保存。"""
        fake_kc = MagicMock()
        daemon = CuratorDaemon(knowledge_curator=fake_kc)
        assert daemon._knowledge_curator is fake_kc

    def test_knowledge_curator_defaults_none(self):
        """不传 knowledge_curator 时默认 None（向后兼容）。"""
        daemon = CuratorDaemon()
        assert daemon._knowledge_curator is None

    def test_run_one_cycle_calls_knowledge_curator(self):
        """非 busy 时，单轮循环调用 knowledge_curator.apply_automatic_transitions。"""
        fake_kc = MagicMock()
        fake_kc.apply_automatic_transitions.return_value = {
            "marked_stale": 0, "archived": 0, "reactivated": 0, "checked": 0
        }
        daemon = CuratorDaemon(knowledge_curator=fake_kc)
        daemon.agent_busy = False

        # mock skill curator 不运行（避免修改真实文件）
        with patch("abyss.curator.maybe_run_curator", return_value=None):
            daemon._run_one_cycle()

        fake_kc.apply_automatic_transitions.assert_called_once()

    def test_run_one_cycle_skips_knowledge_when_busy(self):
        """agent_busy=True 时跳过 knowledge curator。"""
        fake_kc = MagicMock()
        daemon = CuratorDaemon(knowledge_curator=fake_kc)
        daemon.agent_busy = True

        daemon._run_one_cycle()

        fake_kc.apply_automatic_transitions.assert_not_called()

    def test_run_one_cycle_skips_knowledge_when_none(self):
        """knowledge_curator=None 时不报错，只跑 skill curator。"""
        daemon = CuratorDaemon(knowledge_curator=None)
        daemon.agent_busy = False

        with patch("abyss.curator.maybe_run_curator", return_value=None):
            # 不应抛异常
            daemon._run_one_cycle()

    def test_knowledge_curator_exception_does_not_break_loop(self):
        """knowledge_curator 抛异常不影响主循环（静默失败）。"""
        fake_kc = MagicMock()
        fake_kc.apply_automatic_transitions.side_effect = RuntimeError("boom")
        daemon = CuratorDaemon(knowledge_curator=fake_kc)
        daemon.agent_busy = False

        with patch("abyss.curator.maybe_run_curator", return_value=None):
            # 不应抛异常
            daemon._run_one_cycle()
