# allow: no-sut-import — black-box HTTP test; drives real routes through the Flask test client
"""
Unit tests for ChatService class.

Tests service layer methods directly with database operations.
"""

import json


class TestChatServiceCreateSession:
    """Tests for ChatService.create_session method."""

    def test_create_session_returns_uuid(self, authenticated_client):
        """Test that create_session returns a valid UUID."""
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test query"},
            content_type="application/json",
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        session_id = data["session_id"]

        # UUID format check (8-4-4-4-12 hex chars)
        parts = session_id.split("-")
        assert len(parts) == 5
        assert len(parts[0]) == 8
        assert len(parts[1]) == 4
        assert len(parts[2]) == 4
        assert len(parts[3]) == 4
        assert len(parts[4]) == 12

    def test_create_session_initializes_accumulated_context(
        self, authenticated_client
    ):
        """Test that new sessions have initialized accumulated context."""
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(response.data)["session_id"]

        # Get session and check accumulated context
        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)

        # Session should have accumulated_context field
        assert "accumulated_context" in data["session"]


class TestChatServiceAddMessage:
    """Tests for ChatService.add_message method."""

    def test_add_message_increments_sequence(self, authenticated_client):
        """Test that adding messages increments sequence numbers."""
        # Create session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_resp.data)["session_id"]

        # Add messages
        for i in range(3):
            authenticated_client.post(
                f"/api/chat/sessions/{session_id}/messages",
                json={"content": f"Message {i}", "trigger_research": False},
                content_type="application/json",
            )

        # Get messages and verify sequences
        messages_resp = authenticated_client.get(
            f"/api/chat/sessions/{session_id}/messages"
        )
        data = json.loads(messages_resp.data)

        sequences = [m["sequence_number"] for m in data["messages"]]
        assert sequences == [1, 2, 3]


class TestChatServiceGetSession:
    """Tests for ChatService.get_session method."""

    def test_get_session_returns_all_fields(self, authenticated_client):
        """Test that get_session returns all expected fields."""
        # Create session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test query here"},
            content_type="application/json",
        )
        session_id = json.loads(create_resp.data)["session_id"]

        # Get session
        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)["session"]

        expected_fields = [
            "id",
            "title",
            "status",
            "message_count",
            "created_at",
        ]
        for field in expected_fields:
            assert field in data, f"Missing field: {field}"

    def test_get_session_nonexistent_returns_404(self, authenticated_client):
        """Test that getting nonexistent session returns 404."""
        response = authenticated_client.get(
            "/api/chat/sessions/nonexistent-uuid-here"
        )
        assert response.status_code == 404


class TestChatServiceListSessions:
    """Tests for ChatService.list_sessions method."""

    def test_list_sessions_filters_by_status(self, authenticated_client):
        """Test that list_sessions correctly filters by status."""
        # Create active session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Active"},
            content_type="application/json",
        )
        active_id = json.loads(create_resp.data)["session_id"]

        # Create and archive another session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Archived"},
            content_type="application/json",
        )
        archived_id = json.loads(create_resp.data)["session_id"]

        authenticated_client.patch(
            f"/api/chat/sessions/{archived_id}",
            json={"status": "archived"},
            content_type="application/json",
        )

        # List active only
        active_list = authenticated_client.get(
            "/api/chat/sessions?status=active"
        )
        active_data = json.loads(active_list.data)
        active_ids = [s["id"] for s in active_data["sessions"]]

        assert active_id in active_ids
        assert archived_id not in active_ids

        # List archived only
        archived_list = authenticated_client.get(
            "/api/chat/sessions?status=archived"
        )
        archived_data = json.loads(archived_list.data)
        archived_ids = [s["id"] for s in archived_data["sessions"]]

        assert archived_id in archived_ids
        assert active_id not in archived_ids

    def test_list_sessions_respects_limit(self, authenticated_client):
        """Test that list_sessions respects limit parameter."""
        # Create multiple sessions
        for i in range(5):
            authenticated_client.post(
                "/api/chat/sessions",
                json={"initial_query": f"Session {i}"},
                content_type="application/json",
            )

        # List with limit
        response = authenticated_client.get("/api/chat/sessions?limit=3")
        data = json.loads(response.data)
        assert len(data["sessions"]) <= 3


class TestChatServiceUpdateSession:
    """Tests for ChatService update methods."""

    def test_update_title_persists(self, authenticated_client):
        """Test that title updates are persisted."""
        # Create session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Original"},
            content_type="application/json",
        )
        session_id = json.loads(create_resp.data)["session_id"]

        # Update title
        new_title = "Updated Title"
        authenticated_client.patch(
            f"/api/chat/sessions/{session_id}",
            json={"title": new_title},
            content_type="application/json",
        )

        # Verify persistence
        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)
        assert data["session"]["title"] == new_title

    def test_archive_changes_status(self, authenticated_client):
        """Test that archiving changes session status."""
        # Create session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "To archive"},
            content_type="application/json",
        )
        session_id = json.loads(create_resp.data)["session_id"]

        # Archive
        authenticated_client.patch(
            f"/api/chat/sessions/{session_id}",
            json={"status": "archived"},
            content_type="application/json",
        )

        # Verify
        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)
        assert data["session"]["status"] == "archived"


class TestTitleGeneration:
    """Tests for title generation logic."""

    def test_title_from_short_query(self, authenticated_client):
        """Test title generation from short query."""
        short_query = "What is Python?"
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": short_query},
            content_type="application/json",
        )
        session_id = json.loads(response.data)["session_id"]

        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)

        # Title should match or contain the query
        assert short_query in data["session"]["title"]

    def test_title_from_long_query_truncated(self, authenticated_client):
        """Test that long queries are truncated in title."""
        long_query = "A" * 150  # Longer than 100 chars
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": long_query},
            content_type="application/json",
        )
        session_id = json.loads(response.data)["session_id"]

        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)

        # Title should be truncated and end with ellipsis
        title = data["session"]["title"]
        assert len(title) <= 110  # 100 chars + "..."
        assert title.endswith("...")

    def test_title_generation_empty_query(self, authenticated_client):
        """Test title generation with empty query."""
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": ""},
            content_type="application/json",
        )
        session_id = json.loads(response.data)["session_id"]

        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)

        # Should generate a default title with date
        title = data["session"]["title"]
        assert title is not None
        assert len(title) > 0


class TestMessageCount:
    """Tests for message counting."""

    def test_message_count_accuracy(self, authenticated_client):
        """Test that message count is accurate."""
        # Create session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_resp.data)["session_id"]

        # Add 7 messages
        for i in range(7):
            authenticated_client.post(
                f"/api/chat/sessions/{session_id}/messages",
                json={"content": f"Message {i}", "trigger_research": False},
                content_type="application/json",
            )

        # Check count
        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)
        assert data["session"]["message_count"] == 7

    def test_message_count_starts_at_zero(self, authenticated_client):
        """Test that new sessions have zero message count."""
        # Create session
        create_resp = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_resp.data)["session_id"]

        # Check initial count
        get_resp = authenticated_client.get(f"/api/chat/sessions/{session_id}")
        data = json.loads(get_resp.data)
        assert data["session"]["message_count"] == 0
