#!/usr/bin/env python3
"""
FastMCP testing infrastructure for Migadu MCP Server
"""

import pytest
from fastmcp import Client


@pytest.fixture
def mcp_server():
    """Fixture providing initialized FastMCP server for testing"""
    from fastmcp import FastMCP
    from migadu_mcp.tools.mailbox_tools import register_mailbox_tools
    from migadu_mcp.tools.identity_tools import register_identity_tools
    from migadu_mcp.tools.alias_tools import register_alias_tools
    from migadu_mcp.tools.rewrite_tools import register_rewrite_tools
    from migadu_mcp.tools.resource_tools import register_resources

    # Create a fresh server instance for testing to avoid duplicate warnings
    test_mcp = FastMCP("Test Migadu Server")
    register_mailbox_tools(test_mcp)
    register_identity_tools(test_mcp)
    register_alias_tools(test_mcp)
    register_rewrite_tools(test_mcp)
    register_resources(test_mcp)

    # Add test prompts
    @test_mcp.prompt
    def mailbox_creation_wizard(domain: str, user_requirements: str) -> str:
        return f"Test prompt for {domain}: {user_requirements}"

    @test_mcp.prompt
    def bulk_operation_planner(domain: str, operation_type: str, targets: str) -> str:
        return f"Test bulk operation for {domain}: {operation_type} on {targets}"

    return test_mcp


class TestMigaduMCPTools:
    """Test suite for Migadu MCP tools using FastMCP's built-in client"""

    async def test_list_tools(self, mcp_server):
        """Test that all expected tools are registered"""
        async with Client(mcp_server) as client:
            tools = await client.list_tools()
            tool_names = [tool.name for tool in tools]

            # Expected tools based on new List[Dict] consolidated API
            expected_tools = [
                # Mailbox tools
                "list_mailboxes",
                "get_mailbox",
                "create_mailbox",
                "update_mailbox",
                "delete_mailbox",
                "reset_mailbox_password",
                "set_autoresponder",
                # Alias tools
                "list_aliases",
                "get_alias",
                "create_alias",
                "update_alias",
                "delete_alias",
                # Identity tools
                "list_identities",
                "create_identity",
                "update_identity",
                "delete_identity",
                # Rewrite tools
                "list_rewrites",
                "get_rewrite",
                "create_rewrite",
                "update_rewrite",
                "delete_rewrite",
            ]

            print(f"Found {len(tool_names)} tools: {sorted(tool_names)}")
            print(f"Expected {len(expected_tools)} tools: {sorted(expected_tools)}")

            # Check that all expected tools are present
            missing_tools = [tool for tool in expected_tools if tool not in tool_names]
            extra_tools = [tool for tool in tool_names if tool not in expected_tools]

            if missing_tools:
                print(f"Missing tools: {missing_tools}")
            if extra_tools:
                print(f"Extra tools: {extra_tools}")

            # All expected tools should be present
            for tool in expected_tools:
                assert tool in tool_names, f"Missing tool: {tool}"

    async def test_list_resources(self, mcp_server):
        """Test that all expected resources are registered"""
        async with Client(mcp_server) as client:
            resources = await client.list_resources()
            # Resources should be empty since we have resource templates
            assert isinstance(resources, list)

    async def test_list_resource_templates(self, mcp_server):
        """Test that resource templates are registered"""
        async with Client(mcp_server) as client:
            templates = await client.list_resource_templates()
            template_uris = [template.uriTemplate for template in templates]

            # Expected resource templates based on resource_tools.py
            expected_templates = [
                "mailboxes://{domain}",
                "mailbox://{domain}/{local_part}",
                "identities://{domain}/{mailbox}",
                "forwardings://{domain}/{mailbox}",
                "aliases://{domain}",
                "rewrites://{domain}",
            ]

            print(
                f"Found {len(template_uris)} resource templates: {sorted(template_uris)}"
            )
            print(
                f"Expected {len(expected_templates)} templates: {sorted(expected_templates)}"
            )

            # Check that all expected templates are present
            for template in expected_templates:
                assert template in template_uris, (
                    f"Missing resource template: {template}"
                )

    async def test_list_prompts(self, mcp_server):
        """Test that prompts are registered"""
        async with Client(mcp_server) as client:
            prompts = await client.list_prompts()
            prompt_names = [prompt.name for prompt in prompts]

            # Check for expected prompts
            assert "mailbox_creation_wizard" in prompt_names
            assert "bulk_operation_planner" in prompt_names


class TestMigaduMCPIntegration:
    """Integration tests that require valid Migadu credentials"""

    @pytest.mark.integration
    async def test_list_mailboxes_integration(self, mcp_server):
        """Integration test for listing mailboxes (requires valid env vars)"""
        async with Client(mcp_server) as client:
            try:
                result = await client.call_tool("list_mailboxes", {})
                # Should return a valid result structure
                assert len(result) > 0
                # Just check we got some kind of response
                assert result[0] is not None
            except Exception as e:
                # If no valid credentials, should get a configuration error
                assert (
                    "migadu_email" in str(e).lower()
                    or "api_key" in str(e).lower()
                    or "migadu_domain" in str(e).lower()
                )

    @pytest.mark.integration
    async def test_read_mailboxes_resource(self, mcp_server):
        """Integration test for reading mailboxes resource"""
        async with Client(mcp_server) as client:
            try:
                # This would need a real domain configured
                result = await client.read_resource("mailboxes://example.com")
                assert isinstance(result, list)
            except Exception as e:
                # Expected if no valid configuration
                assert "migadu_email" in str(e).lower() or "api_key" in str(e).lower()


# Integration tests are configured via pyproject.toml pytest markers
