import mcp_hn.hn as hn
from mcp.server.models import InitializationOptions
import mcp.types as types
from mcp.server import NotificationOptions, Server
import mcp.server.stdio
import json

DEFAULT_NUM_STORIES = 10

server = Server("hn")

@server.list_tools()
async def handle_list_tools() -> list[types.Tool]:
    """
    List available tools.
    Each tool specifies its arguments using JSON Schema validation.
    """
    return [
        types.Tool(
            name="get_stories",
            description="Get stories from Hacker News. The options are `top`, `new`, `ask_hn`, `show_hn` for types of stories. This doesn't include the comments. Use `get_story_info` to get the comments.",
            inputSchema={
                "type": "object",
                "properties": {
                    "story_type": {
                        "type": "string",
                        "description": "Type of stories to get, one of: `top`, `new`, `ask_hn`, `show_hn`",
                    },
                    "num_stories": {
                        "type": "integer",
                        "description": "Number of stories to get",
                    },
                },
            },
        ),
        types.Tool(
            name="get_user_info",
            description="Get user info from Hacker News, including the stories they've submitted",
            inputSchema={
                "type": "object",
                "properties": {
                    "user_name": {
                        "type": "string",
                        "description": "Username of the user",
                    },
                    "num_stories": {
                        "type": "integer",
                        "description": f"Number of stories to get, defaults to {DEFAULT_NUM_STORIES}",
                    },
                },
                "required": ["user_name"],
            },
        ),
        types.Tool(
            name="search_stories",
            description="Search stories from Hacker News. It is generally recommended to use simpler queries to get a broader set of results (less than 5 words). Very targetted queries may not return any results.",
            inputSchema={
                "type": "object",
                "properties": {
                    "query": {
                        "type": "string",
                        "description": "Search query",
                    },
                    "search_by_date": {
                        "type": "boolean",
                        "description": "Search by date, defaults to False. If this is False, then we search by relevance, then points, then number of comments.",
                    },
                    "num_results": {
                        "type": "integer",
                        "description": f"Number of results to get, defaults to {DEFAULT_NUM_STORIES}",
                    },
                },
                "required": ["query"],
            },
        ),
        types.Tool(
            name="get_story_info",
            description="Get detailed story info from Hacker News, including the comments",
            inputSchema={
                "type": "object",
                "properties": {
                    "story_id": {
                        "type": "integer",
                        "description": "Story ID",
                    },
                },
            },
        ),
    ]

@server.call_tool()
async def handle_call_tool(
    name: str, arguments: dict | None
) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
    """
    Handle tool execution requests.
    """
    if name == "get_stories":
        story_type = arguments.get("story_type", "top")
        num_stories = arguments.get("num_stories", DEFAULT_NUM_STORIES)
        output = hn.get_stories(story_type, num_stories)
        return [types.TextContent(type="text", text=json.dumps(output, indent=2))]
    elif name == "search_stories":
        query = arguments.get("query")
        search_by_date = arguments.get("search_by_date", False)
        num_results = arguments.get("num_results", DEFAULT_NUM_STORIES)
        output = json.dumps(hn.search_stories(query, num_results, search_by_date), indent=2)
        return [types.TextContent(type="text", text=output)]
    elif name == "get_story_info":
        story_id = int(arguments.get("story_id"))
        output = json.dumps(hn.get_story_info(story_id), indent=2)
        return [types.TextContent(type="text", text=output)]
    elif name == "get_user_info":
        user_name = arguments.get("user_name")
        num_stories = arguments.get("num_stories", DEFAULT_NUM_STORIES)
        output = json.dumps(hn.get_user_info(user_name, num_stories), indent=2)
        return [types.TextContent(type="text", text=output)]
    else:
        raise ValueError(f"Unknown tool: {name}")

async def main():
    # Run the server using stdin/stdout streams
    async with mcp.server.stdio.stdio_server() as (read_stream, write_stream):
        await server.run(
            read_stream,
            write_stream,
            InitializationOptions(
                server_name="hn",
                server_version="0.1.0",
                capabilities=server.get_capabilities(
                    notification_options=NotificationOptions(),
                    experimental_capabilities={},
                ),
            ),
        )
