"""
{{ project_name }} MCP API Service
FastMCP/API central connection point
"""

import asyncio
import logging
from contextlib import asynccontextmanager
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel
from typing import Dict, Any, List, Optional
import uvicorn
from fastmcp import FastMCP
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# Global MCP client registry
mcp_clients: Dict[str, ClientSession] = {}

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan manager"""
    logger.info("Starting MCP API Service...")
    
    # Initialize MCP clients for registered services
    await initialize_mcp_clients()
    
    yield
    
    # Cleanup
    logger.info("Shutting down MCP API Service...")
    await cleanup_mcp_clients()

app = FastAPI(
    title="{{ project_name }} MCP API",
    description="Central MCP/API connection point for {{ project_name }}",
    version="1.0.0",
    lifespan=lifespan
)

# CORS middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Pydantic models
class MCPRequest(BaseModel):
    service: str
    method: str
    params: Dict[str, Any] = {}

class MCPResponse(BaseModel):
    success: bool
    data: Any = None
    error: Optional[str] = None

class ServiceStatus(BaseModel):
    name: str
    status: str
    connected: bool

# Health check
@app.get("/health")
async def health_check():
    """Health check endpoint"""
    return {"status": "healthy", "service": "mcp-api"}

# MCP service registry
@app.get("/services", response_model=List[ServiceStatus])
async def list_services():
    """List registered MCP services"""
    services = []
    for name, client in mcp_clients.items():
        services.append(ServiceStatus(
            name=name,
            status="connected" if client else "disconnected",
            connected=bool(client)
        ))
    return services

# MCP call endpoint
@app.post("/mcp/call", response_model=MCPResponse)
async def mcp_call(request: MCPRequest):
    """Make MCP call to registered service"""
    try:
        if request.service not in mcp_clients:
            raise HTTPException(status_code=404, detail=f"Service {request.service} not found")
        
        client = mcp_clients[request.service]
        if not client:
            raise HTTPException(status_code=503, detail=f"Service {request.service} not connected")
        
        # Make MCP call
        result = await client.call_tool(request.method, request.params)
        
        return MCPResponse(success=True, data=result)
        
    except Exception as e:
        logger.error(f"MCP call failed: {e}")
        return MCPResponse(success=False, error=str(e))

# Agent discovery endpoint
@app.get("/agents")
async def discover_agents():
    """Discover available agents through semantic layer"""
    try:
        if "semantic-layer" in mcp_clients:
            client = mcp_clients["semantic-layer"]
            agents = await client.call_tool("list_agents", {})
            return {"agents": agents}
        else:
            return {"agents": [], "message": "Semantic layer not available"}
    except Exception as e:
        logger.error(f"Agent discovery failed: {e}")
        return {"agents": [], "error": str(e)}

# Agent routing endpoint
@app.post("/agents/{agent_name}/query")
async def route_to_agent(agent_name: str, query: Dict[str, Any]):
    """Route query to specific agent through semantic layer"""
    try:
        if "semantic-layer" in mcp_clients:
            client = mcp_clients["semantic-layer"]
            result = await client.call_tool("route_to_agent", {
                "agent_name": agent_name,
                "query": query
            })
            return result
        else:
            raise HTTPException(status_code=503, detail="Semantic layer not available")
    except Exception as e:
        logger.error(f"Agent routing failed: {e}")
        raise HTTPException(status_code=500, detail=str(e))

async def initialize_mcp_clients():
    """Initialize MCP clients for registered services"""
    # Register semantic layer
    try:
        semantic_params = StdioServerParameters(
            command="python",
            args=["-m", "semantic_layer.mcp_server"],
            env={}
        )
        
        async with stdio_client(semantic_params) as (read, write):
            async with ClientSession(read, write) as session:
                await session.initialize()
                mcp_clients["semantic-layer"] = session
                logger.info("Connected to semantic layer MCP server")
                
    except Exception as e:
        logger.warning(f"Failed to connect to semantic layer: {e}")

async def cleanup_mcp_clients():
    """Cleanup MCP client connections"""
    for name, client in mcp_clients.items():
        try:
            if client:
                await client.close()
                logger.info(f"Closed connection to {name}")
        except Exception as e:
            logger.error(f"Error closing connection to {name}: {e}")
    
    mcp_clients.clear()

if __name__ == "__main__":
    uvicorn.run(
        "main:app",
        host="0.0.0.0",
        port=9000,
        reload=True,
        log_level="info"
    )