#!/usr/bin/env python3
"""
Wolfram Alpha MCP Server Wrapper - 科学计算和知识引擎
"""
import os
import sys
import json
import asyncio
import logging
from typing import Any, Dict, List, Optional
import httpx
import xml.etree.ElementTree as ET
from mcp.server import Server, NotificationOptions
from mcp.server.models import InitializationOptions
import mcp.server.stdio
import mcp.types as types

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

class WolframAlphaServer:
    def __init__(self):
        self.app_id = os.getenv("WOLFRAM_APP_ID", "")
        if not self.app_id:
            logger.warning("WOLFRAM_APP_ID not set. Please set it in environment variables.")
        
        self.base_url = "https://api.wolframalpha.com/v2/query"
        self.server = Server("wolfram-alpha")
        
        # 设置工具ListHandle/Process器
        @self.server.list_tools()
        async def handle_list_tools() -> List[types.Tool]:
            return [
                self._query_tool(),
                self._simple_query_tool(),
                self._solve_equation_tool(),
                self._calculate_tool(),
                self._get_facts_tool()
            ]
        
        # 设置工具调用Handle/Process器
        @self.server.call_tool()
        async def handle_call_tool(name: str, arguments: Optional[Dict[str, Any]]) -> List[types.TextContent]:
            return await self._handle_tool_call(name, arguments or {})
    
    def _query_tool(self) -> types.Tool:
        return types.Tool(
            name="wolfram_query",
            description="Query Wolfram Alpha for any question or computation",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Question or computation to send to Wolfram Alpha"
                    },
                    "format": {
                        "type": "string",
                        "enum": ["plaintext", "image", "sound", "all"],
                        "description": "Output format (default: plaintext)",
                        "default": "plaintext"
                    }
                },
                "required": ["query"]
            }
        )
    
    def _simple_query_tool(self) -> types.Tool:
        return types.Tool(
            name="wolfram_simple",
            description="Get a simple, short answer from Wolfram Alpha",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Question to get a simple answer for"
                    }
                },
                "required": ["query"]
            }
        )
    
    def _solve_equation_tool(self) -> types.Tool:
        return types.Tool(
            name="solve_equation",
            description="Solve mathematical equations",
            inputSchema={
                "type": "object",
                "properties": {
                    "equation": {
                        "type": "string",
                        "description": "Equation to solve (e.g., 'x^2 + 5x + 6 = 0')"
                    }
                },
                "required": ["equation"]
            }
        )
    
    def _calculate_tool(self) -> types.Tool:
        return types.Tool(
            name="calculate",
            description="Perform mathematical calculations",
            inputSchema={
                "type": "object",
                "properties": {
                    "expression": {
                        "type": "string",
                        "description": "Mathematical expression to calculate (e.g., 'sqrt(16) + 3^2')"
                    }
                },
                "required": ["expression"]
            }
        )
    
    def _get_facts_tool(self) -> types.Tool:
        return types.Tool(
            name="get_facts",
            description="Get facts about a topic (person, place, thing, concept)",
            inputSchema={
                "type": "object",
                "properties": {
                    "topic": {
                        "type": "string",
                        "description": "Topic to get facts about"
                    }
                },
                "required": ["topic"]
            }
        )
    
    async def _query_wolfram(self, query: str, simple: bool = False) -> Dict[str, Any]:
        """Query Wolfram Alpha API using direct HTTP requests"""
        if not self.app_id:
            return {"error": "Wolfram Alpha API key not configured. Please set WOLFRAM_APP_ID."}
        
        try:
            # Use/UsingJSON输出格式，更容易解析
            params = {
                'appid': self.app_id,
                'input': query,
                'format': 'plaintext',
                'output': 'JSON'
            }
            
            async with httpx.AsyncClient() as client:
                response = await client.get(self.base_url, params=params, timeout=30.0)
                
                if response.status_code != 200:
                    return {"error": f"API returned status code {response.status_code}"}
                
                data = response.json()
                queryresult = data.get('queryresult', {})
                
                if not queryresult.get('success', False):
                    error = queryresult.get('error', {})
                    return {"error": f"Query failed: {error.get('msg', 'Unknown error')}"}
                
                if simple:
                    # 对于简单Query，只Return第一个有意义的Result
                    pods = queryresult.get('pods', [])
                    for pod in pods:
                        if pod.get('id') in ['Result', 'DecimalApproximation', 'Value']:
                            subpods = pod.get('subpods', [])
                            if subpods and subpods[0].get('plaintext'):
                                return {
                                    "answer": subpods[0]['plaintext'],
                                    "success": True
                                }
                    
                    # 如果没有找到特定的Resultpod，Return第一个非输入的pod
                    for pod in pods:
                        if pod.get('id') != 'Input':
                            subpods = pod.get('subpods', [])
                            if subpods and subpods[0].get('plaintext'):
                                return {
                                    "answer": subpods[0]['plaintext'],
                                    "success": True
                                }
                    
                    return {"error": "No simple answer found"}
                
                else:
                    # 完整Query，Return所有pods
                    response = {
                        "success": True,
                        "pods": []
                    }
                    
                    pods = queryresult.get('pods', [])
                    for pod in pods:
                        pod_data = {
                            "title": pod.get('title', ''),
                            "id": pod.get('id', ''),
                            "subpods": []
                        }
                        
                        subpods = pod.get('subpods', [])
                        for subpod in subpods:
                            subpod_data = {}
                            
                            plaintext = subpod.get('plaintext', '')
                            if plaintext:
                                subpod_data['plaintext'] = plaintext
                            
                            img = subpod.get('img', {})
                            if img:
                                subpod_data['image'] = {
                                    'src': img.get('src', ''),
                                    'alt': img.get('alt', ''),
                                    'width': img.get('width', 0),
                                    'height': img.get('height', 0)
                                }
                            
                            if subpod_data:
                                pod_data['subpods'].append(subpod_data)
                        
                        if pod_data['subpods']:
                            response['pods'].append(pod_data)
                    
                    # 添加假设Info/Information
                    assumptions = queryresult.get('assumptions', [])
                    if assumptions:
                        response['assumptions'] = []
                        if isinstance(assumptions, dict):
                            assumptions = [assumptions]
                        for assumption in assumptions:
                            response['assumptions'].append({
                                'type': assumption.get('type', ''),
                                'word': assumption.get('word', ''),
                                'values': assumption.get('values', [])
                            })
                    
                    # 添加警告Info/Information
                    warnings = queryresult.get('warnings', {})
                    if warnings:
                        response['warnings'] = []
                        for key, value in warnings.items():
                            if isinstance(value, dict):
                                response['warnings'].append({
                                    'type': key,
                                    'text': value.get('text', str(value))
                                })
                    
                    return response
                
        except httpx.TimeoutException:
            return {"error": "Query timeout - please try a simpler query"}
        except Exception as e:
            logger.error(f"Wolfram Alpha query error: {e}")
            return {"error": f"Query failed: {str(e)}"}
    
    async def _handle_tool_call(self, name: str, arguments: Dict[str, Any]) -> List[types.TextContent]:
        """Handle tool calls"""
        try:
            if name == "wolfram_query":
                query = arguments["query"]
                result = await self._query_wolfram(query, simple=False)
                
            elif name == "wolfram_simple":
                query = arguments["query"]
                result = await self._query_wolfram(query, simple=True)
                
            elif name == "solve_equation":
                equation = arguments["equation"]
                query = f"solve {equation}"
                result = await self._query_wolfram(query, simple=False)
                
            elif name == "calculate":
                expression = arguments["expression"]
                result = await self._query_wolfram(expression, simple=True)
                
            elif name == "get_facts":
                topic = arguments["topic"]
                query = f"facts about {topic}"
                result = await self._query_wolfram(query, simple=False)
                
            else:
                result = {"error": f"Unknown tool: {name}"}
            
            return [types.TextContent(
                type="text",
                text=json.dumps(result, indent=2)
            )]
            
        except Exception as e:
            logger.error(f"Error in tool {name}: {e}")
            return [types.TextContent(
                type="text",
                text=json.dumps({"error": str(e)})
            )]
    
    async def run(self):
        """Run the server"""
        async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
            await self.server.run(
                read_stream,
                write_stream,
                InitializationOptions(
                    server_name="wolfram-alpha",
                    server_version="0.1.0",
                    capabilities=self.server.get_capabilities(
                        notification_options=NotificationOptions(),
                        experimental_capabilities={},
                    ),
                ),
            )

async def main():
    server = WolframAlphaServer()
    await server.run()

if __name__ == "__main__":
    asyncio.run(main())
