"""
Tests for Agnost Conversation SDK client.
"""

import pytest
from unittest.mock import Mock, patch

from agnost_conversation import (
    ConversationClient,
    ConversationConfig,
    Interaction,
)


class TestConversationConfig:
    """Tests for ConversationConfig."""

    def test_default_config(self):
        config = ConversationConfig()
        assert config.endpoint == "https://api.agnost.ai"
        assert config.debug is False

    def test_custom_config(self):
        config = ConversationConfig(
            endpoint="https://custom.endpoint.com",
            debug=True
        )
        assert config.endpoint == "https://custom.endpoint.com"
        assert config.debug is True

    def test_endpoint_trailing_slash_stripped(self):
        config = ConversationConfig(endpoint="https://api.agnost.ai/")
        assert config.endpoint == "https://api.agnost.ai"


class TestConversationClient:
    """Tests for ConversationClient."""

    def test_init_not_initialized_by_default(self):
        client = ConversationClient()
        assert client.is_initialized is False

    @patch('agnost_conversation.client.requests.Session')
    def test_init_success(self, mock_session):
        client = ConversationClient()
        result = client.init("test-write-key")
        assert result is True
        assert client.is_initialized is True

    @patch('agnost_conversation.client.requests.Session')
    def test_init_twice_returns_true(self, mock_session):
        client = ConversationClient()
        client.init("test-write-key")
        result = client.init("test-write-key")
        assert result is True

    def test_track_ai_without_init_returns_none(self):
        client = ConversationClient()
        result = client.track_ai(user_id="user_123", event="test")
        assert result is None

    def test_track_ai_missing_required_fields(self):
        client = ConversationClient()
        client._initialized = True
        result = client.track_ai(user_id="", event="test")
        assert result is None
        result = client.track_ai(user_id="user_123", event="")
        assert result is None

    def test_identify_without_init_returns_false(self):
        client = ConversationClient()
        result = client.identify("user_123", {"name": "John"})
        assert result is False

    def test_begin_without_init_returns_none(self):
        client = ConversationClient()
        result = client.begin(user_id="user_123", event="test")
        assert result is None


class TestInteraction:
    """Tests for Interaction class."""

    def test_interaction_set_input(self):
        callback = Mock()
        interaction = Interaction(
            event_id="event_123",
            user_id="user_123",
            event="test",
            convo_id=None,
            agent_name=None,
            properties=None,
            _send_callback=callback
        )
        interaction.set_input("test input")
        assert interaction._input == "test input"

    def test_interaction_set_property(self):
        callback = Mock()
        interaction = Interaction(
            event_id="event_123",
            user_id="user_123",
            event="test",
            convo_id=None,
            agent_name=None,
            properties=None,
            _send_callback=callback
        )
        interaction.set_property("key", "value")
        assert interaction.properties["key"] == "value"

    def test_interaction_set_properties(self):
        callback = Mock()
        interaction = Interaction(
            event_id="event_123",
            user_id="user_123",
            event="test",
            convo_id=None,
            agent_name=None,
            properties=None,
            _send_callback=callback
        )
        interaction.set_properties({"a": 1, "b": 2})
        assert interaction.properties["a"] == 1
        assert interaction.properties["b"] == 2

    def test_interaction_finish_calls_callback(self):
        callback = Mock()
        interaction = Interaction(
            event_id="event_123",
            user_id="user_123",
            event="test",
            convo_id="convo_123",
            agent_name="test-agent",
            properties={"initial": "prop"},
            _send_callback=callback
        )
        interaction.set_input("test input")
        event_id = interaction.finish(output="test output", latency=100)

        assert event_id == "event_123"
        callback.assert_called_once()

    def test_interaction_cannot_modify_after_finish(self):
        callback = Mock()
        interaction = Interaction(
            event_id="event_123",
            user_id="user_123",
            event="test",
            convo_id=None,
            agent_name=None,
            properties=None,
            _send_callback=callback
        )
        interaction.finish(output="done")

        with pytest.raises(RuntimeError):
            interaction.set_input("more input")

        with pytest.raises(RuntimeError):
            interaction.set_property("key", "value")

        with pytest.raises(RuntimeError):
            interaction.finish(output="again")


if __name__ == "__main__":
    pytest.main([__file__, "-v"])
