from __future__ import annotations

"""
Integration tests for get-id MCP tool.

Copyright (C) 2025 Luciano Guerche

This file is part of rabbitmq-mcp-server.

rabbitmq-mcp-server is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

rabbitmq-mcp-server is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with rabbitmq-mcp-server. If not, see <https://www.gnu.org/licenses/>.
"""

import json

import pytest

from rabbitmq_mcp_connection.tools.get_id import handle_get_id


@pytest.mark.integration
@pytest.mark.asyncio
class TestGetIdToolIntegration:
    """Integration tests for get-id tool via MCP protocol."""

    async def test_valid_operation_lookup_queues_list(self) -> None:
        """Test looking up queues.list operation."""
        result = await handle_get_id("queues.list", correlation_id="integration-test-1")

        assert result.success is True
        assert result.error is None

        schema = result.result["schema"]
        assert schema["operation_id"] == "queues.list"
        assert "summary" in schema or "description" in schema
        assert "formatted" in result.result

    async def test_valid_operation_lookup_exchanges_delete(self) -> None:
        """Test looking up exchanges.delete_by_params operation."""
        result = await handle_get_id(
            "exchanges.delete_by_params", correlation_id="integration-test-2"
        )

        assert result.success is True
        schema = result.result["schema"]
        assert schema["operation_id"] == "exchanges.delete_by_params"

        # Should have modification hint
        if "usage_hints" in schema:
            hints = schema["usage_hints"]
            assert any("modifies resources" in hint for hint in hints)

    async def test_valid_operation_lookup_bindings_create(self) -> None:
        """Test looking up bindings_e_q.create_by_params operation."""
        result = await handle_get_id(
            "bindings_e_q.create_by_params", correlation_id="integration-test-3"
        )

        assert result.success is True
        schema = result.result["schema"]
        assert schema["operation_id"] == "bindings_e_q.create_by_params"

    async def test_invalid_operation_lookup(self) -> None:
        """Test looking up non-existent operation."""
        result = await handle_get_id(
            "invalid.operation", correlation_id="integration-test-4"
        )

        assert result.success is False
        assert result.error is not None
        assert result.error.code == "OPERATION_NOT_FOUND"
        assert "invalid.operation" in result.error.message

    async def test_invalid_operation_with_suggestions(self) -> None:
        """Test error includes similar operation suggestions."""
        result = await handle_get_id("queues.lst", correlation_id="integration-test-5")

        assert result.success is False
        assert result.error is not None
        # Should suggest "queues.list" or similar
        assert (
            "Did you mean" in result.error.message
            or "search-ids" in result.error.message
        )

    async def test_empty_operation_id(self) -> None:
        """Test empty operation_id."""
        result = await handle_get_id("", correlation_id="integration-test-6")

        assert result.success is False
        assert result.error is not None

    async def test_malformed_operation_id_missing_namespace(self) -> None:
        """Test operation_id without namespace."""
        result = await handle_get_id(
            "invalidoperation", correlation_id="integration-test-7"
        )

        assert result.success is False
        assert result.error is not None

    async def test_response_format_json_structure(self) -> None:
        """Test response has correct JSON structure."""
        result = await handle_get_id("queues.list", correlation_id="integration-test-8")

        assert result.success is True
        assert "schema" in result.result
        assert "formatted" in result.result

        # Verify formatted is valid JSON
        formatted = result.result["formatted"]
        parsed = json.loads(formatted)
        assert "operation_id" in parsed

    async def test_response_format_pretty_printed(self) -> None:
        """Test formatted response uses 2-space indentation."""
        result = await handle_get_id("queues.list", correlation_id="integration-test-9")

        formatted = result.result["formatted"]

        # Check for indentation (pretty-printed)
        lines = formatted.split("\n")
        assert len(lines) > 1  # Multi-line output

        # Check for 2-space indentation
        indented_lines = [line for line in lines if line.startswith("  ")]
        assert len(indented_lines) > 0

    async def test_usage_hints_authentication(self) -> None:
        """Test usage hints appear for operations requiring auth."""
        result = await handle_get_id(
            "queues.list", correlation_id="integration-test-10"
        )

        assert result.success is True
        schema = result.result["schema"]

        # If requires_auth is set, should have hint
        if schema.get("requires_auth"):
            assert "usage_hints" in schema
            hints = schema["usage_hints"]
            assert any("authentication" in hint.lower() for hint in hints)

    async def test_usage_hints_modification(self) -> None:
        """Test usage hints for resource-modifying operations."""
        # Test with DELETE operation
        result = await handle_get_id(
            "exchanges.delete_by_params", correlation_id="integration-test-11"
        )

        assert result.success is True
        schema = result.result["schema"]

        if "usage_hints" in schema:
            hints = schema["usage_hints"]
            # Should warn about modification
            assert any("modifies" in hint.lower() for hint in hints)

    async def test_correlation_id_in_logs(self) -> None:
        """Test correlation_id is passed through (no exceptions)."""
        # This test verifies no exceptions are raised when correlation_id is provided
        result = await handle_get_id(
            "queues.list", correlation_id="test-correlation-id-123"
        )
        assert result.success is True

    async def test_multiple_operations_consistency(self) -> None:
        """Test multiple operation lookups return consistent structure."""
        operations = ["queues.list", "exchanges.list", "bindings.list"]

        results = []
        for op_id in operations:
            result = await handle_get_id(
                op_id, correlation_id=f"consistency-test-{op_id}"
            )
            if result.success:
                results.append(result)

        # All results should have same keys
        assert len(results) > 0
        keys_sets = [set(r.result.keys()) for r in results]
        # All should have "schema" and "formatted"
        for keys in keys_sets:
            assert "schema" in keys
            assert "formatted" in keys
