"""Tests for metadata_tools module."""

from unittest.mock import AsyncMock, MagicMock

import pytest

from openzim_mcp.config import OpenZimMcpConfig
from openzim_mcp.exceptions import OpenZimMcpRateLimitError
from openzim_mcp.server import OpenZimMcpServer


class TestRegisterMetadataTools:
    """Test metadata tools registration."""

    def test_register_metadata_tools(self, test_config: OpenZimMcpConfig):
        """Test that metadata tools are registered correctly."""
        server = OpenZimMcpServer(test_config)
        assert server.mcp is not None


class TestGetZimMetadataTool:
    """Test get_zim_metadata tool functionality."""

    @pytest.fixture
    def server(self, test_config: OpenZimMcpConfig) -> OpenZimMcpServer:
        """Create a test server instance."""
        return OpenZimMcpServer(test_config)

    @pytest.mark.asyncio
    async def test_get_zim_metadata_success(self, server: OpenZimMcpServer):
        """Test successful metadata retrieval."""
        server.async_zim_operations.get_zim_metadata = AsyncMock(
            return_value='{"title": "Test", "language": "en"}'
        )
        server.rate_limiter.check_rate_limit = MagicMock()

        result = await server.async_zim_operations.get_zim_metadata("/path/to/file.zim")

        assert "title" in result
        server.async_zim_operations.get_zim_metadata.assert_called_once_with(
            "/path/to/file.zim"
        )

    @pytest.mark.asyncio
    async def test_get_zim_metadata_rate_limit_error(self, server: OpenZimMcpServer):
        """Test rate limit handling in get_zim_metadata."""
        error = OpenZimMcpRateLimitError("Rate limit exceeded")
        error_msg = server._create_enhanced_error_message(
            operation="get ZIM metadata",
            error=error,
            context="File: /test/file.zim",
        )
        assert "get ZIM metadata" in error_msg or "Operation" in error_msg

    @pytest.mark.asyncio
    async def test_get_zim_metadata_generic_exception(self, server: OpenZimMcpServer):
        """Test generic exception handling in get_zim_metadata."""
        server.async_zim_operations.get_zim_metadata = AsyncMock(
            side_effect=Exception("Test error")
        )

        with pytest.raises(Exception) as exc_info:
            await server.async_zim_operations.get_zim_metadata("/path/to/file.zim")
        assert "Test error" in str(exc_info.value)


class TestGetMainPageTool:
    """Test get_main_page tool functionality."""

    @pytest.fixture
    def server(self, test_config: OpenZimMcpConfig) -> OpenZimMcpServer:
        """Create a test server instance."""
        return OpenZimMcpServer(test_config)

    @pytest.mark.asyncio
    async def test_get_main_page_success(self, server: OpenZimMcpServer):
        """Test successful main page retrieval."""
        server.async_zim_operations.get_main_page = AsyncMock(
            return_value="Main page content"
        )
        server.rate_limiter.check_rate_limit = MagicMock()

        result = await server.async_zim_operations.get_main_page("/path/to/file.zim")

        assert result == "Main page content"
        server.async_zim_operations.get_main_page.assert_called_once_with(
            "/path/to/file.zim"
        )

    @pytest.mark.asyncio
    async def test_get_main_page_rate_limit_error(self, server: OpenZimMcpServer):
        """Test rate limit handling in get_main_page."""
        error = OpenZimMcpRateLimitError("Rate limit exceeded")
        error_msg = server._create_enhanced_error_message(
            operation="get main page",
            error=error,
            context="File: /test/file.zim",
        )
        assert "get main page" in error_msg or "Operation" in error_msg


class TestListNamespacesTool:
    """Test list_namespaces tool functionality."""

    @pytest.fixture
    def server(self, test_config: OpenZimMcpConfig) -> OpenZimMcpServer:
        """Create a test server instance."""
        return OpenZimMcpServer(test_config)

    @pytest.mark.asyncio
    async def test_list_namespaces_success(self, server: OpenZimMcpServer):
        """Test successful namespace listing."""
        server.async_zim_operations.list_namespaces = AsyncMock(
            return_value='{"namespaces": ["A", "C", "M"]}'
        )
        server.rate_limiter.check_rate_limit = MagicMock()

        result = await server.async_zim_operations.list_namespaces("/path/to/file.zim")

        assert "namespaces" in result
        server.async_zim_operations.list_namespaces.assert_called_once_with(
            "/path/to/file.zim"
        )

    @pytest.mark.asyncio
    async def test_list_namespaces_rate_limit_error(self, server: OpenZimMcpServer):
        """Test rate limit handling in list_namespaces."""
        error = OpenZimMcpRateLimitError("Rate limit exceeded")
        error_msg = server._create_enhanced_error_message(
            operation="list namespaces",
            error=error,
            context="File: /test/file.zim",
        )
        assert "list namespaces" in error_msg or "Operation" in error_msg

    @pytest.mark.asyncio
    async def test_list_namespaces_generic_exception(self, server: OpenZimMcpServer):
        """Test generic exception handling in list_namespaces."""
        server.async_zim_operations.list_namespaces = AsyncMock(
            side_effect=Exception("Test error")
        )

        with pytest.raises(Exception) as exc_info:
            await server.async_zim_operations.list_namespaces("/path/to/file.zim")
        assert "Test error" in str(exc_info.value)


class TestInputSanitizationMetadata:
    """Test input sanitization in metadata tools."""

    def test_sanitize_file_path(self, test_config: OpenZimMcpConfig):
        """Test that file paths are validated correctly."""
        from openzim_mcp.constants import INPUT_LIMIT_FILE_PATH
        from openzim_mcp.exceptions import OpenZimMcpValidationError
        from openzim_mcp.security import sanitize_input

        # Valid path should pass
        valid_path = "x" * 100
        sanitized = sanitize_input(valid_path, INPUT_LIMIT_FILE_PATH)
        assert sanitized == valid_path

        # Long path should raise error
        long_path = "x" * 2000
        with pytest.raises(OpenZimMcpValidationError):
            sanitize_input(long_path, INPUT_LIMIT_FILE_PATH)
