"""Tests for compression config integration (U4)

Covers:
1. ServerConfig.compression field
2. create_app compression setup
3. ConfigDrivenAgent compressor passthrough
"""

import tempfile
from unittest.mock import AsyncMock, MagicMock, patch

import pytest

from agentkit.server.config import ServerConfig


# ---------------------------------------------------------------------------
# 1. ServerConfig.compression
# ---------------------------------------------------------------------------


class TestServerConfigCompression:
    """Test compression field on ServerConfig"""

    def test_default_compression_is_empty_dict(self):
        config = ServerConfig()
        assert config.compression == {}

    def test_compression_from_dict(self):
        data = {
            "compression": {
                "enabled": True,
                "provider": "headroom",
                "compressors": ["smart_crusher"],
            }
        }
        config = ServerConfig.from_dict(data)
        assert config.compression["enabled"] is True
        assert config.compression["provider"] == "headroom"
        assert config.compression["compressors"] == ["smart_crusher"]

    def test_compression_none_when_not_in_yaml(self):
        data = {"server": {"host": "0.0.0.0"}}
        config = ServerConfig.from_dict(data)
        assert config.compression == {}

    def test_compression_hot_reload(self):
        """_try_reload_config should update compression"""
        with tempfile.NamedTemporaryFile(
            mode="w", suffix=".yaml", delete=False
        ) as f:
            f.write(
                "server:\n  host: 0.0.0.0\n  port: 8001\n"
                "compression:\n  enabled: false\n"
            )
            f.flush()
            config = ServerConfig.from_yaml(f.name)
            assert config.compression == {"enabled": False}

            # Write new content
            f2 = open(f.name, "w")
            f2.write(
                "server:\n  host: 0.0.0.0\n  port: 8001\n"
                "compression:\n  enabled: true\n  provider: headroom\n"
            )
            f2.close()

            config._try_reload_config(f.name)
            assert config.compression["enabled"] is True
            assert config.compression["provider"] == "headroom"


# ---------------------------------------------------------------------------
# 2. create_app compression setup
# ---------------------------------------------------------------------------


class TestCreateAppCompression:
    """Test compression setup in create_app"""

    def test_compressor_created_when_enabled(self):
        from agentkit.server.app import create_app

        with patch("agentkit.core.compressor.create_compressor") as mock_create:
            mock_compressor = MagicMock()
            mock_create.return_value = mock_compressor

            server_config = ServerConfig(
                compression={"enabled": True, "provider": "summary"}
            )
            app = create_app(server_config=server_config)

            mock_create.assert_called_once_with({"enabled": True, "provider": "summary"})
            assert app.state.compressor is mock_compressor

    def test_compressor_none_when_disabled(self):
        from agentkit.server.app import create_app

        with patch("agentkit.core.compressor.create_compressor") as mock_create:
            # create_compressor returns None when disabled
            mock_create.return_value = None

            server_config = ServerConfig(
                compression={"enabled": False}
            )
            app = create_app(server_config=server_config)

            mock_create.assert_called_once_with({"enabled": False})
            assert app.state.compressor is None

    def test_compressor_none_when_no_config(self):
        from agentkit.server.app import create_app

        with patch("agentkit.core.compressor.create_compressor") as mock_create:
            mock_create.return_value = None

            # No server_config at all
            app = create_app()

            # create_compressor should not be called (no server_config)
            mock_create.assert_not_called()
            assert app.state.compressor is None


# ---------------------------------------------------------------------------
# 3. ConfigDrivenAgent compressor passthrough
# ---------------------------------------------------------------------------


class TestConfigDrivenAgentCompression:
    """Test compressor passthrough from ConfigDrivenAgent to ReActEngine"""

    @pytest.fixture
    def agent_config(self):
        from agentkit.core.config_driven import AgentConfig

        return AgentConfig(
            name="test_agent",
            agent_type="test",
            task_mode="llm_generate",
            prompt={"identity": "test", "instructions": "test"},
        )

    @pytest.fixture
    def skill_config(self):
        from agentkit.skills.base import SkillConfig

        return SkillConfig(
            name="test_skill",
            agent_type="test",
            description="test",
            prompt={"identity": "test", "instructions": "test instructions"},
            execution_mode="react",
        )

    def test_compressor_stored_on_agent(self, agent_config):
        from agentkit.core.config_driven import ConfigDrivenAgent

        mock_compressor = MagicMock()
        agent = ConfigDrivenAgent(
            config=agent_config,
            compressor=mock_compressor,
        )
        assert agent._compressor is mock_compressor

    def test_no_compressor_backward_compatible(self, agent_config):
        from agentkit.core.config_driven import ConfigDrivenAgent

        agent = ConfigDrivenAgent(config=agent_config)
        assert agent._compressor is None

    @pytest.mark.asyncio
    async def test_compressor_passed_to_react_engine(self, skill_config):
        from agentkit.core.config_driven import ConfigDrivenAgent

        mock_compressor = MagicMock()

        with patch.object(
            ConfigDrivenAgent, "__init__", return_value=None
        ) as mock_init:
            # We need to test _handle_react directly, so set up the agent manually
            agent = object.__new__(ConfigDrivenAgent)
            agent._config = skill_config
            agent._skill_config = skill_config
            agent._prompt_template = None
            agent._tools = []
            agent._memory_retriever = None
            agent._compressor = mock_compressor
            agent._evolution_enabled = False
            agent._current_module = None
            agent._active_tokens = {}
            agent.name = "test_agent"

            # Mock the ReActEngine
            mock_engine = MagicMock()
            mock_result = MagicMock()
            mock_result.output = '{"result": "ok"}'
            mock_engine.execute = AsyncMock(return_value=mock_result)
            agent._react_engine = mock_engine

            from agentkit.core.protocol import TaskMessage
            from datetime import datetime, timezone

            task = TaskMessage(
                task_id="t1",
                agent_name="test_agent",
                task_type="test",
                input_data={"query": "hello"},
                priority=1,
                created_at=datetime.now(timezone.utc),
                callback_url=None,
            )

            await agent._handle_react(task)

            # Verify compressor was passed to execute
            mock_engine.execute.assert_called_once()
            call_kwargs = mock_engine.execute.call_args.kwargs
            assert call_kwargs["compressor"] is mock_compressor

    @pytest.mark.asyncio
    async def test_no_compressor_backward_compatible_react(self, skill_config):
        from agentkit.core.config_driven import ConfigDrivenAgent

        with patch.object(
            ConfigDrivenAgent, "__init__", return_value=None
        ):
            agent = object.__new__(ConfigDrivenAgent)
            agent._config = skill_config
            agent._skill_config = skill_config
            agent._prompt_template = None
            agent._tools = []
            agent._memory_retriever = None
            agent._compressor = None
            agent._evolution_enabled = False
            agent._current_module = None
            agent._active_tokens = {}
            agent.name = "test_agent"

            mock_engine = MagicMock()
            mock_result = MagicMock()
            mock_result.output = '{"result": "ok"}'
            mock_engine.execute = AsyncMock(return_value=mock_result)
            agent._react_engine = mock_engine

            from agentkit.core.protocol import TaskMessage
            from datetime import datetime, timezone

            task = TaskMessage(
                task_id="t2",
                agent_name="test_agent",
                task_type="test",
                input_data={"query": "hello"},
                priority=1,
                created_at=datetime.now(timezone.utc),
                callback_url=None,
            )

            await agent._handle_react(task)

            call_kwargs = mock_engine.execute.call_args.kwargs
            assert call_kwargs["compressor"] is None
