#!/usr/bin/env python3
"""
MCP Client Simulator for testing VoluteMCP-Local server.
This simulates how real MCP clients interact with your server via stdio.
"""

import asyncio
import json
import subprocess
import sys
import os
from typing import Dict, Any, List, Optional

class MCPClientSimulator:
    """Simulates an MCP client connecting to the VoluteMCP-Local server."""
    
    def __init__(self, server_command: List[str]):
        """
        Initialize the MCP client simulator.
        
        Args:
            server_command: Command to start the MCP server
        """
        self.server_command = server_command
        self.process = None
        self.request_id = 0
    
    async def start_server(self):
        """Start the MCP server process."""
        try:
            self.process = await asyncio.create_subprocess_exec(
                *self.server_command,
                stdin=asyncio.subprocess.PIPE,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE
            )
            print("✅ MCP server process started")
            return True
        except Exception as e:
            print(f"❌ Failed to start server: {e}")
            return False
    
    async def stop_server(self):
        """Stop the MCP server process."""
        if self.process:
            self.process.terminate()
            await self.process.wait()
            print("🔴 MCP server process stopped")
    
    async def send_request(self, method: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """
        Send an MCP request to the server.
        
        Args:
            method: MCP method name
            params: Request parameters
            
        Returns:
            Server response
        """
        if not self.process:
            raise RuntimeError("Server not started")
        
        self.request_id += 1
        request = {
            "jsonrpc": "2.0",
            "id": self.request_id,
            "method": method,
            "params": params or {}
        }
        
        # Send request
        request_json = json.dumps(request) + "\n"
        self.process.stdin.write(request_json.encode())
        await self.process.stdin.drain()
        
        # Read response
        response_line = await self.process.stdout.readline()
        if not response_line:
            raise RuntimeError("No response from server")
        
        try:
            response = json.loads(response_line.decode().strip())
            return response
        except json.JSONDecodeError as e:
            print(f"❌ Failed to decode response: {e}")
            print(f"Raw response: {response_line.decode()}")
            raise
    
    async def initialize(self) -> Dict[str, Any]:
        """Initialize the MCP session."""
        return await self.send_request("initialize", {
            "protocolVersion": "2024-11-05",
            "capabilities": {
                "resources": {},
                "tools": {}
            },
            "clientInfo": {
                "name": "VoluteMCP-Client-Simulator",
                "version": "1.0.0"
            }
        })
    
    async def list_tools(self) -> Dict[str, Any]:
        """List available tools."""
        return await self.send_request("tools/list")
    
    async def list_resources(self) -> Dict[str, Any]:
        """List available resources."""
        return await self.send_request("resources/list")
    
    async def call_tool(self, tool_name: str, arguments: Dict[str, Any]) -> Dict[str, Any]:
        """Call a specific tool."""
        return await self.send_request("tools/call", {
            "name": tool_name,
            "arguments": arguments
        })
    
    async def read_resource(self, uri: str) -> Dict[str, Any]:
        """Read a specific resource."""
        return await self.send_request("resources/read", {
            "uri": uri
        })


async def test_mcp_server():
    """Comprehensive test of the MCP server functionality."""
    
    print("=" * 80)
    print("🚀 VoluteMCP-Local Server Test Suite")
    print("=" * 80)
    
    # File path for testing
    test_file = r'C:\Users\shrey\OneDrive\Desktop\docs\2024.10.27 Project Core - Valuation Analysis_v22.pptx'
    
    # Initialize MCP client
    server_command = [sys.executable, "server_local.py", "stdio"]
    client = MCPClientSimulator(server_command)
    
    try:
        # Start server
        print("\n🔄 Starting MCP server...")
        if not await client.start_server():
            return
        
        # Wait a moment for server to initialize
        await asyncio.sleep(1)
        
        # Test 1: Initialize MCP session
        print("\n🔍 Test 1: MCP Session Initialization")
        try:
            init_response = await client.initialize()
            if "error" in init_response:
                print(f"❌ Initialization failed: {init_response['error']}")
                return
            else:
                print("✅ MCP session initialized successfully")
                server_info = init_response.get("result", {})
                print(f"   📋 Server name: {server_info.get('serverInfo', {}).get('name', 'Unknown')}")
                print(f"   📋 Protocol version: {server_info.get('protocolVersion', 'Unknown')}")
        except Exception as e:
            print(f"❌ Initialization failed: {e}")
            return
        
        # Test 2: List available tools
        print("\n🔍 Test 2: List Available Tools")
        try:
            tools_response = await client.list_tools()
            if "error" in tools_response:
                print(f"❌ Failed to list tools: {tools_response['error']}")
            else:
                tools = tools_response.get("result", {}).get("tools", [])
                print(f"✅ Found {len(tools)} tools:")
                for tool in tools:
                    name = tool.get("name", "Unknown")
                    desc = tool.get("description", "No description")[:50] + "..."
                    print(f"   • {name}: {desc}")
        except Exception as e:
            print(f"❌ Failed to list tools: {e}")
        
        # Test 3: List available resources
        print("\n🔍 Test 3: List Available Resources")
        try:
            resources_response = await client.list_resources()
            if "error" in resources_response:
                print(f"❌ Failed to list resources: {resources_response['error']}")
            else:
                resources = resources_response.get("result", {}).get("resources", [])
                print(f"✅ Found {len(resources)} resources:")
                for resource in resources:
                    uri = resource.get("uri", "Unknown")
                    name = resource.get("name", "Unknown")
                    print(f"   • {uri}: {name}")
        except Exception as e:
            print(f"❌ Failed to list resources: {e}")
        
        # Test 4: Test system info tool
        print("\n🔍 Test 4: Test Local System Info Tool")
        try:
            system_response = await client.call_tool("get_local_system_info", {})
            if "error" in system_response:
                print(f"❌ System info failed: {system_response['error']}")
            else:
                result = system_response.get("result", {})
                content = result.get("content", [])
                if content and len(content) > 0:
                    system_info = content[0].get("text", "") if content[0].get("type") == "text" else str(content[0])
                    print("✅ System info retrieved:")
                    print(f"   📊 Response: {system_info[:200]}...")
                else:
                    print(f"✅ System info response: {result}")
        except Exception as e:
            print(f"❌ System info test failed: {e}")
        
        # Test 5: Test file validation tool (if test file exists)
        if os.path.exists(test_file):
            print("\n🔍 Test 5: Test PowerPoint File Validation")
            try:
                validation_response = await client.call_tool("validate_powerpoint_file", {
                    "presentation_path": test_file
                })
                if "error" in validation_response:
                    print(f"❌ Validation failed: {validation_response['error']}")
                else:
                    result = validation_response.get("result", {})
                    print("✅ File validation completed")
                    print(f"   📋 Response type: {type(result)}")
                    # The result structure may vary based on MCP version
            except Exception as e:
                print(f"❌ Validation test failed: {e}")
        else:
            print(f"\n⚠️  Test 5: Skipped (test file not found: {os.path.basename(test_file)})")
        
        # Test 6: Test slide capture capabilities
        print("\n🔍 Test 6: Test Slide Capture Capabilities")
        try:
            capabilities_response = await client.call_tool("get_slide_capture_capabilities", {})
            if "error" in capabilities_response:
                print(f"❌ Capabilities check failed: {capabilities_response['error']}")
            else:
                result = capabilities_response.get("result", {})
                print("✅ Slide capture capabilities retrieved")
                print(f"   🎯 Response available: {bool(result)}")
        except Exception as e:
            print(f"❌ Capabilities test failed: {e}")
        
        # Test 7: Test resource reading
        print("\n🔍 Test 7: Test Resource Reading")
        try:
            resource_response = await client.read_resource("local://system")
            if "error" in resource_response:
                print(f"❌ Resource reading failed: {resource_response['error']}")
            else:
                result = resource_response.get("result", {})
                print("✅ Resource reading successful")
                print(f"   📋 Resource content available: {bool(result)}")
        except Exception as e:
            print(f"❌ Resource reading test failed: {e}")
        
        print("\n" + "=" * 80)
        print("📊 MCP SERVER TEST SUMMARY")
        print("=" * 80)
        print("✅ MCP server is running and responding to requests")
        print("✅ Tools are properly registered and accessible")
        print("✅ Resources are properly registered and accessible")
        print("✅ PowerPoint analysis tools are available")
        print("✅ Multimodal slide capture tools are available")
        print("✅ Server is ready for production MCP client connections")
        
        print(f"\n🎯 To connect from MCP clients:")
        print(f"   Command: python server_local.py stdio")
        print(f"   Protocol: MCP over stdio")
        print(f"   Server: VoluteMCP-Local")
        
    except KeyboardInterrupt:
        print("\n🛑 Test interrupted by user")
    except Exception as e:
        print(f"\n❌ Test suite failed: {e}")
        import traceback
        traceback.print_exc()
    finally:
        # Clean up
        await client.stop_server()


if __name__ == "__main__":
    print("🧪 MCP Client Simulator for VoluteMCP-Local")
    print("This simulates how real MCP clients interact with your server.\n")
    
    try:
        asyncio.run(test_mcp_server())
    except KeyboardInterrupt:
        print("\n👋 Goodbye!")
    except Exception as e:
        print(f"\n💥 Simulator failed: {e}")
        sys.exit(1)
