"""MCP Server for ccontext."""

import asyncio
import json
import logging
from pathlib import Path
from typing import Any, Optional, Sequence

from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import (
    TextContent,
    Tool,
)

from .tools import TOOL_DESCRIPTIONS, ContextTools

# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("ccontext-mcp")

# Create server instance
server = Server("ccontext-mcp")

# Global tools instance (initialized on startup)
_tools: Optional[ContextTools] = None


def get_tools() -> ContextTools:
    """Get the tools instance, initializing if needed."""
    global _tools
    if _tools is None:
        _tools = ContextTools()
    return _tools


@server.list_tools()
async def list_tools() -> list[Tool]:
    """List available tools."""
    return [
        Tool(
            name="get_context",
            description=TOOL_DESCRIPTIONS["get_context"],
            inputSchema={
                "type": "object",
                "properties": {
                    "agent_id": {
                        "type": "string",
                        "description": "Your agent identifier (optional, for tracking)"
                    }
                },
                "required": []
            }
        ),
        Tool(
            name="update_context",
            description=TOOL_DESCRIPTIONS["update_context"],
            inputSchema={
                "type": "object",
                "properties": {
                    "goal": {
                        "type": "string",
                        "description": "New execution goal"
                    },
                    "why": {
                        "type": "string",
                        "description": "New decision rationale"
                    },
                    "agent_id": {
                        "type": "string",
                        "description": "Your agent identifier (required if updating agent_status)"
                    },
                    "agent_status": {
                        "type": "string",
                        "description": "Your current status (natural language)"
                    }
                },
                "required": []
            }
        ),
        Tool(
            name="list_tasks",
            description=TOOL_DESCRIPTIONS["list_tasks"],
            inputSchema={
                "type": "object",
                "properties": {
                    "task_id": {
                        "type": "string",
                        "description": "Get a specific task by ID"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["planned", "active", "done"],
                        "description": "Filter by status"
                    },
                    "assignee": {
                        "type": "string",
                        "description": "Filter by assignee"
                    },
                    "include_archived": {
                        "type": "boolean",
                        "description": "Include archived tasks",
                        "default": False
                    }
                },
                "required": []
            }
        ),
        Tool(
            name="create_task",
            description=TOOL_DESCRIPTIONS["create_task"],
            inputSchema={
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "Task name"
                    },
                    "goal": {
                        "type": "string",
                        "description": "Completion criteria"
                    },
                    "steps": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "name": {"type": "string"},
                                "done": {"type": "string"}
                            },
                            "required": ["name", "done"]
                        },
                        "description": "Task steps (2-8 recommended)"
                    },
                    "task_id": {
                        "type": "string",
                        "description": "Custom task ID (auto-generated if not provided)"
                    },
                    "assignee": {
                        "type": "string",
                        "description": "Assignee agent ID"
                    }
                },
                "required": ["name", "goal", "steps"]
            }
        ),
        Tool(
            name="update_task",
            description=TOOL_DESCRIPTIONS["update_task"],
            inputSchema={
                "type": "object",
                "properties": {
                    "task_id": {
                        "type": "string",
                        "description": "Task ID to update"
                    },
                    "status": {
                        "type": "string",
                        "enum": ["planned", "active", "done"],
                        "description": "New task status"
                    },
                    "name": {
                        "type": "string",
                        "description": "New task name"
                    },
                    "goal": {
                        "type": "string",
                        "description": "New completion criteria"
                    },
                    "assignee": {
                        "type": "string",
                        "description": "New assignee"
                    },
                    "step_id": {
                        "type": "string",
                        "description": "Step ID to update"
                    },
                    "step_status": {
                        "type": "string",
                        "enum": ["pending", "in_progress", "done"],
                        "description": "New step status"
                    },
                    "steps": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {"type": "string"},
                                "name": {"type": "string"},
                                "done": {"type": "string"},
                                "status": {"type": "string", "enum": ["pending", "in_progress", "done"]}
                            },
                            "required": ["id", "name", "done", "status"]
                        },
                        "description": "Replace all steps"
                    }
                },
                "required": ["task_id"]
            }
        ),
        Tool(
            name="delete_task",
            description=TOOL_DESCRIPTIONS["delete_task"],
            inputSchema={
                "type": "object",
                "properties": {
                    "task_id": {
                        "type": "string",
                        "description": "Task ID to delete"
                    }
                },
                "required": ["task_id"]
            }
        ),
        Tool(
            name="add_entry",
            description=TOOL_DESCRIPTIONS["add_entry"],
            inputSchema={
                "type": "object",
                "properties": {
                    "type": {
                        "type": "string",
                        "enum": ["note", "reference"],
                        "description": "Entry type"
                    },
                    "content": {
                        "type": "string",
                        "description": "Note content or reference description"
                    },
                    "uri": {
                        "type": "string",
                        "description": "File path/URI (required for references)"
                    },
                    "score": {
                        "type": "integer",
                        "minimum": 10,
                        "maximum": 100,
                        "default": 15,
                        "description": "Initial score (higher = persists longer)"
                    }
                },
                "required": ["type", "content"]
            }
        ),
        Tool(
            name="update_entry",
            description=TOOL_DESCRIPTIONS["update_entry"],
            inputSchema={
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Entry ID (N001 or R001)"
                    },
                    "content": {
                        "type": "string",
                        "description": "New content"
                    },
                    "score": {
                        "type": "integer",
                        "description": "New score (to renew/extend)"
                    }
                },
                "required": ["id"]
            }
        ),
        Tool(
            name="remove_entry",
            description=TOOL_DESCRIPTIONS["remove_entry"],
            inputSchema={
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Entry ID (N001 or R001)"
                    }
                },
                "required": ["id"]
            }
        ),
    ]


@server.call_tool()
async def call_tool(name: str, arguments: dict[str, Any]) -> Sequence[TextContent]:
    """Handle tool calls."""
    tools = get_tools()
    
    try:
        if name == "get_context":
            result = tools.get_context(
                agent_id=arguments.get("agent_id")
            )
        elif name == "update_context":
            result = tools.update_context(
                goal=arguments.get("goal"),
                why=arguments.get("why"),
                agent_id=arguments.get("agent_id"),
                agent_status=arguments.get("agent_status"),
            )
        elif name == "list_tasks":
            result = tools.list_tasks(
                task_id=arguments.get("task_id"),
                status=arguments.get("status"),
                assignee=arguments.get("assignee"),
                include_archived=arguments.get("include_archived", False),
            )
        elif name == "create_task":
            result = tools.create_task(
                name=arguments["name"],
                goal=arguments["goal"],
                steps=arguments["steps"],
                task_id=arguments.get("task_id"),
                assignee=arguments.get("assignee"),
            )
        elif name == "update_task":
            result = tools.update_task(
                task_id=arguments["task_id"],
                status=arguments.get("status"),
                name=arguments.get("name"),
                goal=arguments.get("goal"),
                assignee=arguments.get("assignee"),
                step_id=arguments.get("step_id"),
                step_status=arguments.get("step_status"),
                steps=arguments.get("steps"),
            )
        elif name == "delete_task":
            result = tools.delete_task(
                task_id=arguments["task_id"]
            )
        elif name == "add_entry":
            result = tools.add_entry(
                type=arguments["type"],
                content=arguments["content"],
                uri=arguments.get("uri"),
                score=arguments.get("score", 15),
            )
        elif name == "update_entry":
            result = tools.update_entry(
                id=arguments["id"],
                content=arguments.get("content"),
                score=arguments.get("score"),
            )
        elif name == "remove_entry":
            result = tools.remove_entry(
                id=arguments["id"]
            )
        else:
            raise ValueError(f"Unknown tool: {name}")
        
        return [TextContent(type="text", text=json.dumps(result, indent=2))]
    
    except ValueError as e:
        return [TextContent(type="text", text=json.dumps({"error": str(e)}))]
    except Exception as e:
        logger.exception(f"Error calling tool {name}")
        return [TextContent(type="text", text=json.dumps({"error": f"Internal error: {str(e)}"}))]


async def run_server():
    """Run the MCP server."""
    async with stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            server.create_initialization_options()
        )


def main():
    """Main entry point."""
    asyncio.run(run_server())


if __name__ == "__main__":
    main()
