#!/usr/bin/env python3
"""
List Models from MCP Server

This script can work in two modes:
1. Direct backend API call (current - no MCP protocol)
2. Via MCP protocol using uvx (requires MCP SDK)

By default, it uses direct backend API call for simplicity.
Use --mcp flag to test via actual MCP protocol (like Cursor does).
"""

import asyncio
import json
import sys
import argparse
from pathlib import Path

# Add parent directory to path
sys.path.insert(0, str(Path(__file__).parent.parent))

from dcisionai_mcp_server.client import DcisionAIClient
from dcisionai_mcp_server.config import MCPConfig


async def list_models():
    """List all available models"""
    print("\n" + "="*80)
    print("DcisionAI MCP Server - Available Models")
    print("="*80)
    print(f"Backend URL: {MCPConfig.get_api_url()}")
    print(f"Domain Filter: {MCPConfig.get_domain_filter()}")
    print("="*80)
    
    try:
        client = DcisionAIClient()
        data = await client.get_models()
        
        models = data.get("models", [])
        
        # Apply domain filtering if configured
        domain_filter = MCPConfig.get_domain_filter()
        if domain_filter != "all":
            models = [
                model for model in models
                if model.get("domain", "").lower() == domain_filter.lower()
            ]
            print(f"\n📊 Domain Filter: {domain_filter}")
            print(f"   Total Models Available: {len(data.get('models', []))}")
            print(f"   Filtered Models: {len(models)}")
            print()
        
        if not models:
            print("⚠️  No models found")
            if domain_filter != "all":
                print(f"   (Filtered by domain: {domain_filter})")
            return False
        
        print(f"\n✅ Found {len(models)} model(s):\n")
        
        for i, model in enumerate(models, 1):
            print(f"{i}. {model.get('name')} ({model.get('id')})")
            print(f"   Domain: {model.get('domain', 'N/A')}")
            print(f"   Status: {model.get('status', 'N/A')}")
            print(f"   Problem Type: {model.get('problem_type', 'N/A')}")
            print(f"   Solver: {model.get('solver', 'N/A')}")
            print(f"   Variables: {model.get('variables', 'N/A')}, Constraints: {model.get('constraints', 'N/A')}")
            print(f"   Avg Solve Time: {model.get('avg_solve_time', 'N/A')}s")
            
            # Show description
            description = model.get('description', '')
            if description:
                print(f"   Description: {description[:100]}{'...' if len(description) > 100 else ''}")
            
            # Show data requirements
            data_reqs = model.get('data_requirements', {})
            if data_reqs:
                required = data_reqs.get('required', [])
                optional = data_reqs.get('optional', [])
                if required:
                    print(f"   Required Parameters: {len(required)}")
                if optional:
                    print(f"   Optional Parameters: {len(optional)}")
            
            print()
        
        return True
        
    except Exception as e:
        print(f"\n❌ Failed to list models: {e}")
        import traceback
        traceback.print_exc()
        return False


async def list_solvers():
    """List all available solvers"""
    print("\n" + "="*80)
    print("DcisionAI MCP Server - Available Solvers")
    print("="*80)
    
    # Static solver list (matches what's in resources/solvers.py)
    solvers = {
        "mathematical": [
            {"name": "HiGHS", "type": "LP/MIP", "description": "High-performance LP/MIP solver"},
            {"name": "SCIP", "type": "MIP", "description": "Solving Constraint Integer Programs"},
            {"name": "OR-Tools", "type": "CP-SAT", "description": "Google OR-Tools constraint programming"}
        ],
        "heuristic": [
            {"name": "DAME", "type": "Evolutionary", "description": "DcisionAI Multi-Objective Adaptive Engine"}
        ]
    }
    
    mathematical = solvers.get("mathematical", [])
    heuristic = solvers.get("heuristic", [])
    
    print(f"\n✅ Mathematical Solvers ({len(mathematical)}):")
    for solver in mathematical:
        print(f"   • {solver.get('name')} ({solver.get('type')})")
        print(f"     {solver.get('description')}")
    
    print(f"\n✅ Heuristic Solvers ({len(heuristic)}):")
    for solver in heuristic:
        print(f"   • {solver.get('name')} ({solver.get('type')})")
        print(f"     {solver.get('description')}")
    
    print()
    return True


async def list_models_via_mcp():
    """List models via actual MCP protocol (using uvx like Cursor)"""
    print("\n" + "="*80)
    print("MCP SERVER TEST - Via uvx (MCP Protocol)")
    print("="*80)
    print("⚠️  This requires MCP SDK: pip install mcp --break-system-packages")
    print("="*80)
    
    try:
        from mcp import ClientSession, StdioServerParameters
        from mcp.client.stdio import stdio_client
    except ImportError:
        print("\n❌ MCP SDK not installed")
        print("   Install with: pip install mcp --break-system-packages")
        print("   Or use: python3 -m pip install --user mcp")
        return False
    
    try:
        # Create server parameters for uvx (exactly like Cursor does)
        server_params = StdioServerParameters(
            command="uvx",
            args=["dcisionai-mcp-server@latest"],
            env=None
        )
        
        print("\n🔄 Connecting to MCP server via uvx...")
        print("   Command: uvx dcisionai-mcp-server@latest")
        
        async with stdio_client(server_params) as (read, write):
            async with ClientSession(read, write) as session:
                # Initialize
                init_result = await session.initialize()
                print(f"✅ Connected to MCP server: {init_result.serverInfo.name if init_result.serverInfo else 'dcisionai-optimization'}")
                
                # List resources
                print("\n📋 Listing MCP resources...")
                resources = await session.list_resources()
                print(f"   Found {len(resources.resources)} resources")
                
                # Read models resource
                print("\n📊 Reading dcisionai://models/list resource...")
                result = await session.read_resource("dcisionai://models/list")
                
                if result.contents:
                    content = result.contents[0]
                    models_data = json.loads(content.text if hasattr(content, 'text') else str(content))
                    
                    models = models_data.get("models", [])
                    print(f"\n✅ Retrieved {len(models)} models via MCP protocol:\n")
                    
                    for i, model in enumerate(models, 1):
                        print(f"{i}. {model.get('name')} ({model.get('id')})")
                        print(f"   Domain: {model.get('domain')}")
                        print(f"   Type: {model.get('problem_type')}")
                        print()
                    
                    return True
                else:
                    print("❌ No content in resource response")
                    return False
                    
    except Exception as e:
        print(f"❌ Failed to connect via MCP protocol: {e}")
        import traceback
        traceback.print_exc()
        return False


async def main():
    """Main function"""
    parser = argparse.ArgumentParser(description="List models from DcisionAI MCP Server")
    parser.add_argument("--mcp", action="store_true", help="Use MCP protocol via uvx (like Cursor) instead of direct API call")
    args = parser.parse_args()
    
    if args.mcp:
        print("\n🔌 Using MCP Protocol (via uvx)")
        success = await list_models_via_mcp()
    else:
        print("\n🔌 Using Direct Backend API Call")
        print("   (Use --mcp flag to test via MCP protocol like Cursor)")
        success1 = await list_models()
        success2 = await list_solvers()
        success = success1 and success2
    
    print("="*80)
    if success:
        print("✅ Successfully listed models")
    else:
        print("⚠️  Some operations failed")
    print("="*80)
    
    return success


if __name__ == "__main__":
    success = asyncio.run(main())
    sys.exit(0 if success else 1)
