"""
DcisionAI FastMCP Server

FastMCP-compatible server for FastMCP Cloud deployment.
This uses the FastMCP framework instead of standard MCP SDK.

Entrypoint for FastMCP Cloud: dcisionai_mcp_server.fastmcp_server:mcp
"""

import os
from fastmcp import FastMCP
from fastapi import FastAPI
from fastapi.responses import JSONResponse
from dcisionai_mcp_server.client import DcisionAIClient
from dcisionai_mcp_server.config import MCPConfig

# Create FastMCP app with domain-aware name
_domain_filter = MCPConfig.get_domain_filter()
if _domain_filter != "all":
    server_name = f"DcisionAI Optimization Server - {_domain_filter.upper()} Edition"
else:
    server_name = "DcisionAI Optimization Server"

mcp = FastMCP(server_name)

# Initialize client
_client = DcisionAIClient()

# Try to access FastMCP's underlying FastAPI app for health endpoint
# FastMCP wraps FastAPI internally
try:
    # FastMCP may expose the app directly or via _app attribute
    app = getattr(mcp, 'app', None) or getattr(mcp, '_app', None)
    if app and isinstance(app, FastAPI):
        @app.get("/health")
        async def health_check():
            """Health check endpoint for Railway deployment"""
            return JSONResponse({"status": "ok", "service": "dcisionai-mcp-server"})
    else:
        # Fallback: create a wrapper FastAPI app
        wrapper_app = FastAPI(title=server_name)
        
        @wrapper_app.get("/health")
        async def health_check():
            """Health check endpoint for Railway deployment"""
            return JSONResponse({"status": "ok", "service": "dcisionai-mcp-server"})
        
        # Mount FastMCP routes if possible
        # Note: This is a fallback - FastMCP should handle routing
        app = wrapper_app
except Exception:
    # If we can't access the app, we'll handle health in start script
    app = None


@mcp.tool()
async def dcisionai_solve(problem_description: str) -> str:
    """
    Solve an optimization problem using DcisionAI.
    
    Provides full optimization workflow including problem classification,
    intent extraction, model generation, solving, and business explanation.
    
    Args:
        problem_description: Natural language description of the optimization problem
        
    Returns:
        JSON string with optimization results
    """
    import json
    try:
        result = await _client.optimize(problem_description)
        return json.dumps(result, indent=2)
    except Exception as e:
        return json.dumps({"error": str(e)}, indent=2)


@mcp.tool()
async def dcisionai_solve_with_model(model_id: str, data: dict) -> str:
    """
    Solve an optimization problem using a deployed DcisionAI model.
    
    Args:
        model_id: ID of the deployed model to use
        data: Model-specific input data (as dictionary)
        
    Returns:
        JSON string with optimization results
    """
    import json
    try:
        result = await _client.optimize_with_model(model_id, data)
        return json.dumps(result, indent=2)
    except Exception as e:
        return json.dumps({"error": str(e)}, indent=2)


# Note: dcisionai_explain_solution removed - explanation is included in dcisionai_solve results


@mcp.resource("dcisionai://models/list")
async def get_models() -> str:
    """
    Get list of deployed DcisionAI models.
    
    Returns:
        JSON string with list of models (filtered by domain if configured)
    """
    import json
    try:
        models_response = await _client.get_models()
        
        # Apply domain filtering if configured
        domain_filter = MCPConfig.get_domain_filter()
        if domain_filter != "all":
            models_list = models_response.get("models", [])
            filtered_models = [
                model for model in models_list
                if model.get("domain", "").lower() == domain_filter.lower()
            ]
            models_response = {
                "models": filtered_models,
                "filtered_by_domain": domain_filter,
                "total_models": len(models_list),
                "filtered_count": len(filtered_models)
            }
        
        return json.dumps(models_response, indent=2)
    except Exception as e:
        return json.dumps({"error": str(e)}, indent=2)


@mcp.resource("dcisionai://solvers/list")
async def get_solvers() -> str:
    """
    Get list of all available optimization solvers.
    
    Returns:
        JSON string with list of solvers
    """
    import json
    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"}
        ]
    }
    return json.dumps(solvers, indent=2)


# Main entry point for FastMCP
if __name__ == "__main__":
    # Railway provides PORT env var, FastMCP should handle it automatically
    # But we can also explicitly set host/port if needed
    port = int(os.getenv("PORT", "8080"))
    host = os.getenv("HOST", "0.0.0.0")
    mcp.run(host=host, port=port)

