"""
Arcade MCP Server Runner

Provides a unified interface for running MCP servers with either:
- stdio transport for direct client connections
- HTTP/SSE transport with FastAPI for web-based connections

Usage:
    # Run with stdio transport
    python -m arcade_mcp_server stdio

    # Run with HTTP transport (default)
    python -m arcade_mcp_server

    # Run with specific toolkit
    python -m arcade_mcp_server --toolkit my_toolkit

    # Run in development mode with hot reload
    python -m arcade_mcp_server --reload --debug
"""

import asyncio
import os
import sys
from pathlib import Path

from dotenv import load_dotenv
from loguru import logger

from arcade_mcp_server.logging_utils import setup_logging
from arcade_mcp_server.stdio_runner import initialize_tool_catalog, run_stdio_server


def main() -> None:
    """Main entry point for arcade_mcp_server module."""
    import argparse

    parser = argparse.ArgumentParser(
        description="Run Arcade MCP Server",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  # Auto-discover tools from current directory
  python -m arcade_mcp_server

  # Run with stdio transport for Claude Desktop
  python -m arcade_mcp_server stdio

  # Load specific arcade package
  python -m arcade_mcp_server --tool-package github
  python -m arcade_mcp_server -p slack

  # Discover all installed arcade packages
  python -m arcade_mcp_server --discover-installed --show-packages

  # Development mode with hot reload
  python -m arcade_mcp_server --debug --reload

  # Run from a different directory
  python -m arcade_mcp_server --cwd /path/to/project
  python -m arcade_mcp_server --cwd ~/my-tools stdio

Auto-discovery looks for Python files with @tool decorated functions in:
  - Current directory (*.py)
  - tools/ subdirectory
  - arcade_tools/ subdirectory
        """,
    )

    # Transport selection (positional for backwards compatibility)
    parser.add_argument(
        "transport",
        nargs="?",
        default="http",
        choices=["stdio", "http", "streamable-http"],
        help="Transport type (default: http)",
    )

    # Optional arguments
    parser.add_argument(
        "--host",
        default="127.0.0.1",
        help="Host to bind to (HTTP mode only)",
    )
    parser.add_argument(
        "--port",
        type=int,
        default=8000,
        help="Port to bind to (HTTP mode only)",
    )
    parser.add_argument(
        "--tool-package",
        "--package",
        "-p",
        dest="tool_package",
        help="Specific tool package to load (e.g., 'github' for arcade-github)",
    )
    parser.add_argument(
        "--discover-installed",
        "--all",
        action="store_true",
        help="Discover all installed arcade tool packages",
    )
    parser.add_argument(
        "--show-packages",
        action="store_true",
        help="Show loaded packages during discovery",
    )
    parser.add_argument(
        "--reload",
        action="store_true",
        help="Enable auto-reload on code changes (HTTP mode only)",
    )
    parser.add_argument(
        "--debug",
        action="store_true",
        help="Enable debug mode with verbose logging",
    )
    parser.add_argument(
        "--otel-enable",
        action="store_true",
        help="Send logs to OpenTelemetry",
    )
    parser.add_argument(
        "--env-file",
        help="Path to environment file",
    )
    parser.add_argument(
        "--name",
        help="Server name",
    )
    parser.add_argument(
        "--version",
        help="Server version",
    )
    parser.add_argument(
        "--cwd",
        help="Directory to change to before running (for tool discovery)",
    )
    parser.add_argument(
        "--workers",
        default=1,
        type=int,
        help=argparse.SUPPRESS,
    )

    args = parser.parse_args()

    # Change working directory if specified
    if args.cwd:
        cwd_path = Path(args.cwd).resolve()
        if not cwd_path.exists():
            print(f"Error: Directory does not exist: {args.cwd}", file=sys.stderr)
            sys.exit(1)
        if not cwd_path.is_dir():
            print(f"Error: Path is not a directory: {args.cwd}", file=sys.stderr)
            sys.exit(1)
        os.chdir(cwd_path)
        # Update logging to show the new directory

    # Load environment variables
    if args.env_file:
        load_dotenv(args.env_file)

    # Setup logging
    log_level = "DEBUG" if args.debug else "INFO"
    setup_logging(level=log_level, stdio_mode=(args.transport == "stdio"))

    if args.workers > 1 and args.transport == "stdio":
        logger.error("Cannot use --workers > 1 with stdio transport")
        sys.exit(1)

    # Build kwargs for server
    server_kwargs = {}
    if args.name:
        server_kwargs["name"] = args.name
    if args.version:
        server_kwargs["version"] = args.version

    # Run appropriate server
    try:
        if args.transport == "stdio":
            # Discover tools only for stdio mode (HTTP mode handles its own discovery)
            catalog = initialize_tool_catalog(
                tool_package=args.tool_package,
                show_packages=args.show_packages,
                discover_installed=args.discover_installed,
                server_name=server_kwargs.get("name"),
                server_version=server_kwargs.get("version"),
            )
            logger.info("Starting MCP server with stdio transport")
            asyncio.run(
                run_stdio_server(catalog, debug=args.debug, env_file=args.env_file, **server_kwargs)
            )
        else:
            logger.info(f"Starting MCP server with HTTP transport on {args.host}:{args.port}")
            from arcade_mcp_server.worker import run_arcade_mcp

            run_arcade_mcp(
                host=args.host,
                port=args.port,
                reload=args.reload,
                debug=args.debug,
                otel_enable=args.otel_enable,
                tool_package=args.tool_package,
                discover_installed=args.discover_installed,
                show_packages=args.show_packages,
                workers=args.workers,
                **server_kwargs,
            )
    except (KeyboardInterrupt, asyncio.CancelledError):
        logger.info("Server stopped")
        sys.exit(0)
    except Exception as e:
        logger.error(f"Server error: {e}")
        sys.exit(1)


if __name__ == "__main__":
    main()
