"""
Command Agent for Task Manager MCP Servers

Adapted from the original project's CommandAgent for use in MCP servers.
This agent parses natural language commands into structured function calls.
"""

import requests
import json
from typing import Dict, Any, Optional
import os
import re


class CommandAgent:
    """
    一个AI智能体，负责将用户的自然语言指令解析为可执行的函数调用。
    """
    
    def __init__(self, api_key: Optional[str] = None, base_url: Optional[str] = None):
        """
        初始化CommandAgent。
        """
        self.api_key = api_key or os.environ.get("OPENAI_API_KEY")
        self.base_url = base_url or os.environ.get("OPENAI_BASE_URL", "https://api.openai.com/v1")
        if not self.api_key:
            raise ValueError("API key must be provided or set as an environment variable (OPENAI_API_KEY).")
        self.system_prompt = self._build_system_prompt()

    def _build_system_prompt(self) -> str:
        """构建系统提示词，描述可用的工具和命令格式。"""
        tools_description = """
Available tools and their expected JSON format:

1. **list_tasks** - List all tasks or tasks for a specific project
   ```json
   {
     "tool": "list_tasks",
     "parameters": {
       "project_id": "optional_project_id",
       "status": "optional_status_filter"
     }
   }
   ```

2. **get_task** - Get details of a specific task
   ```json
   {
     "tool": "get_task", 
     "parameters": {
       "task_id": "task_id_here"
     }
   }
   ```

3. **update_task** - Update task properties
   ```json
   {
     "tool": "update_task",
     "parameters": {
       "task_id": "task_id_here",
       "updates": {
         "status": "new_status",
         "priority": "new_priority",
         "assignee": "new_assignee"
       }
     }
   }
   ```

4. **delete_task** - Delete a task
   ```json
   {
     "tool": "delete_task",
     "parameters": {
       "task_id": "task_id_here"
     }
   }
   ```

5. **list_projects** - List all projects
   ```json
   {
     "tool": "list_projects",
     "parameters": {}
   }
   ```

6. **get_project** - Get project details
   ```json
   {
     "tool": "get_project",
     "parameters": {
       "project_id": "project_id_here"
     }
   }
   ```

7. **list_resources** - List available resources
   ```json
   {
     "tool": "list_resources",
     "parameters": {
       "type": "optional_type_filter"
     }
   }
   ```

ONLY respond with the JSON object. Do not add any extra text or explanation.
"""
        return f"You are a command interpretation assistant for a task management system. Your only job is to convert user's natural language requests into a specific JSON format. {tools_description}"

    def parse_command(self, user_input: str) -> Dict[str, Any]:
        """
        Receives user input and uses an LLM to convert it into a command dictionary.
        """
        api_url = f"{self.base_url}/chat/completions"
        if not self.base_url.endswith('/v1'):
            api_url = f"{self.base_url}/v1/chat/completions"

        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }

        payload = {
            "model": "gpt-4-turbo",
            "messages": [
                {"role": "system", "content": self.system_prompt},
                {"role": "user", "content": user_input}
            ],
            "temperature": 0.0,
        }

        try:
            response = requests.post(api_url, headers=headers, json=payload, timeout=30)
            response.raise_for_status()
            
            response_data = response.json()
            content = response_data.get("choices", [{}])[0].get("message", {}).get("content", "")
            
            if not content:
                return {"tool": "unknown", "parameters": {}, "error": "Empty response from LLM"}
            
            # Try to parse JSON directly
            try:
                result = json.loads(content)
                return result
            except json.JSONDecodeError:
                # Try to extract JSON from the content
                json_match = re.search(r'\{.*\}', content, re.DOTALL)
                if json_match:
                    try:
                        result = json.loads(json_match.group())
                        return result
                    except json.JSONDecodeError:
                        pass
                
                return {
                    "tool": "unknown", 
                    "parameters": {}, 
                    "error": f"Could not parse JSON from response: {content}"
                }
                
        except requests.exceptions.RequestException as e:
            return {"tool": "unknown", "parameters": {}, "error": f"API request failed: {str(e)}"}
        except Exception as e:
            return {"tool": "unknown", "parameters": {}, "error": f"Unexpected error: {str(e)}"}
