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

Tests verify request validation in chat API routes:
- Title length validation
- Status value validation
- Message content validation
- Pagination parameter validation
"""

import json


class TestSessionRouteValidation:
    """Tests for session route input validation."""

    def test_create_session_accepts_valid_request(self, authenticated_client):
        """Test that valid session creation request succeeds."""
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test query", "title": "Test Title"},
            content_type="application/json",
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["success"] is True

    def test_create_session_without_body(self, authenticated_client):
        """Test that session can be created with empty body."""
        response = authenticated_client.post(
            "/api/chat/sessions",
            json={},  # Empty body
            content_type="application/json",
        )
        # Should succeed - body fields are optional
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["success"] is True

    def test_update_session_invalid_title_length(self, authenticated_client):
        """Test that titles over 500 chars are rejected."""
        # First create a session
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Try to update with a too-long title
        long_title = "A" * 501
        response = authenticated_client.patch(
            f"/api/chat/sessions/{session_id}",
            json={"title": long_title},
            content_type="application/json",
        )
        assert response.status_code == 400
        data = json.loads(response.data)
        assert data["success"] is False
        assert "too long" in data["error"].lower()

    def test_update_session_invalid_status_value(self, authenticated_client):
        """Test that invalid status values are rejected."""
        # First create a session
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Try to update with an invalid status
        response = authenticated_client.patch(
            f"/api/chat/sessions/{session_id}",
            json={"status": "invalid_status"},
            content_type="application/json",
        )
        assert response.status_code == 400
        data = json.loads(response.data)
        assert data["success"] is False
        assert "invalid" in data["error"].lower()

    def test_get_session_nonexistent_uuid(self, authenticated_client):
        """Test that nonexistent session returns 404."""
        response = authenticated_client.get(
            "/api/chat/sessions/00000000-0000-0000-0000-000000000000"
        )
        assert response.status_code == 404
        data = json.loads(response.data)
        assert data["success"] is False


class TestMessageRouteValidation:
    """Tests for message route input validation."""

    def test_send_message_empty_content_rejected(self, authenticated_client):
        """Test that empty message content is rejected."""
        # Create a session first
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Try to send empty message
        response = authenticated_client.post(
            f"/api/chat/sessions/{session_id}/messages",
            json={"content": ""},
            content_type="application/json",
        )
        assert response.status_code == 400
        data = json.loads(response.data)
        assert data["success"] is False
        assert "required" in data["error"].lower()

    def test_send_message_missing_content_rejected(self, authenticated_client):
        """Test that missing content field is rejected."""
        # Create a session first
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Try to send message without content
        response = authenticated_client.post(
            f"/api/chat/sessions/{session_id}/messages",
            json={},
            content_type="application/json",
        )
        assert response.status_code == 400
        data = json.loads(response.data)
        assert data["success"] is False

    def test_send_message_content_length_limit(self, authenticated_client):
        """Test that message content is limited to 10,000 characters."""
        # Create a session first
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Try to send message with content > 10000 chars
        long_content = "A" * 10001
        response = authenticated_client.post(
            f"/api/chat/sessions/{session_id}/messages",
            json={"content": long_content, "trigger_research": False},
            content_type="application/json",
        )
        assert response.status_code == 400
        data = json.loads(response.data)
        assert data["success"] is False
        assert "too long" in data["error"].lower() or "10000" in data["error"]

    def test_send_message_to_nonexistent_session(self, authenticated_client):
        """Test that sending to nonexistent session returns 404."""
        response = authenticated_client.post(
            "/api/chat/sessions/00000000-0000-0000-0000-000000000000/messages",
            json={"content": "Test message", "trigger_research": False},
            content_type="application/json",
        )
        assert response.status_code == 404
        data = json.loads(response.data)
        assert data["success"] is False


class TestPaginationValidation:
    """Tests for pagination parameter validation."""

    def test_get_messages_pagination_limits(self, authenticated_client):
        """Test that pagination parameters are bounded correctly."""
        # Create a session
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Test with limit > 100 (should be capped)
        response = authenticated_client.get(
            f"/api/chat/sessions/{session_id}/messages?limit=200&offset=0"
        )
        assert response.status_code == 200
        # Response should succeed (limit is capped internally)
        data = json.loads(response.data)
        assert data["success"] is True

    def test_get_messages_invalid_offset(self, authenticated_client):
        """Test that invalid offset falls back to default."""
        # Create a session
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Test with invalid offset (should fall back to 0)
        response = authenticated_client.get(
            f"/api/chat/sessions/{session_id}/messages?offset=invalid"
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["success"] is True

    def test_list_sessions_invalid_status_falls_back(
        self, authenticated_client
    ):
        """Test that invalid status falls back to 'active'."""
        response = authenticated_client.get(
            "/api/chat/sessions?status=invalid_status"
        )
        # Should succeed and return active sessions
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["success"] is True

    def test_list_sessions_valid_status_values(self, authenticated_client):
        """Test that all valid status values are accepted."""
        valid_statuses = ["active", "archived", "deleted", "all"]

        for status in valid_statuses:
            response = authenticated_client.get(
                f"/api/chat/sessions?status={status}"
            )
            assert response.status_code == 200, (
                f"Status '{status}' should be valid"
            )
            data = json.loads(response.data)
            assert data["success"] is True


class TestStatusTransitionValidation:
    """Tests for session status transition validation."""

    def test_session_can_be_archived(self, authenticated_client):
        """Test that active session can be archived."""
        # Create session
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Archive it
        response = authenticated_client.patch(
            f"/api/chat/sessions/{session_id}",
            json={"status": "archived"},
            content_type="application/json",
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["success"] is True
        assert data["session"]["status"] == "archived"

    def test_session_can_be_deleted(self, authenticated_client):
        """Test that session can be permanently deleted."""
        # Create session
        create_response = authenticated_client.post(
            "/api/chat/sessions",
            json={"initial_query": "Test"},
            content_type="application/json",
        )
        session_id = json.loads(create_response.data)["session_id"]

        # Delete it (hard delete)
        response = authenticated_client.delete(
            f"/api/chat/sessions/{session_id}"
        )
        assert response.status_code == 200
        data = json.loads(response.data)
        assert data["success"] is True

        # Verify it's gone
        get_response = authenticated_client.get(
            f"/api/chat/sessions/{session_id}"
        )
        assert get_response.status_code == 404
