#!/usr/bin/env python3
"""
Command line interface for Web Forager.
This module provides the entry point for the `web-forager` command.
"""

import argparse
import json
import logging
import sys
from typing import Callable, Dict, List, Union

from .duckduckgo_news import duckduckgo_news_search
from .duckduckgo_search import duckduckgo_search
from .jina_fetch import fetch_url
from .server import mcp


def _handle_version(args: argparse.Namespace) -> int:
    """Handle the version command."""
    from . import __version__

    print(f"Web Forager v{__version__}")

    if not getattr(args, "debug", False):
        return 0

    # Show additional version information in debug mode
    import platform

    print(f"Python version: {platform.python_version()}")
    print(f"Platform: {platform.platform()}")

    try:
        from ddgs import __version__ as ddgs_version

        print(f"ddgs version: {ddgs_version}")
    except ImportError:
        print("ddgs: not available")

    return 0


def _handle_search(args: argparse.Namespace) -> int:
    """Handle the search command."""
    try:
        query = " ".join(args.query)
        output_format = getattr(args, "output_format", "json")
        results = duckduckgo_search(
            query=query,
            max_results=args.max_results,
            safesearch=args.safesearch,
            output_format=output_format,
        )

        if output_format == "text":
            print(results)
        else:
            print(json.dumps(results, indent=2, ensure_ascii=False))
        return 0
    except Exception as e:
        logging.error(f"Search error: {str(e)}")
        return 1


def _handle_news(args: argparse.Namespace) -> int:
    """Handle the news command."""
    try:
        query = " ".join(args.query)
        output_format = getattr(args, "output_format", "json")
        results = duckduckgo_news_search(
            query=query,
            max_results=args.max_results,
            safesearch=args.safesearch,
            output_format=output_format,
        )

        if output_format == "text":
            print(results)
        else:
            print(json.dumps(results, indent=2, ensure_ascii=False))
        return 0
    except Exception as e:
        logging.error(f"News search error: {str(e)}")
        return 1


def _handle_fetch(args: argparse.Namespace) -> int:
    """Handle the fetch command."""
    try:
        result = fetch_url(
            url=args.url,
            output_format=args.format,
            max_length=args.max_length,
            with_images=args.with_images,
        )

        if args.format == "json":
            print(json.dumps(result, indent=2, ensure_ascii=False))
        else:
            print(result)
        return 0
    except Exception as e:
        logging.error(f"Fetch error: {str(e)}")
        return 1


def _handle_serve(args: argparse.Namespace) -> int:
    """Handle the serve command."""
    from . import __version__

    logging.info(f"Starting Web Forager MCP Server v{__version__} (STDIO transport)")
    logging.info("Press Ctrl+C to stop the server")

    # Register "search" as an alias for "duckduckgo_search" for backward compatibility.
    # Some MCP clients may expect the shorter name. This simply delegates to the main tool.
    @mcp.tool()
    def search(
        query: str,
        max_results: int = 5,
        safesearch: str = "moderate",
        output_format: str = "json",
    ) -> Union[List[Dict[str, str]], str]:
        """Search DuckDuckGo for the given query."""
        logging.debug(
            f"Searching for: {query} (max_results: {max_results}, safesearch: {safesearch}, output_format: {output_format})"
        )
        results = duckduckgo_search(query, max_results, safesearch, output_format)
        if isinstance(results, list):
            logging.debug(f"Found {len(results)} results")
        return results

    try:
        mcp.run(transport="stdio")
        return 0
    except KeyboardInterrupt:
        logging.info("Server stopped by user")
        return 0
    except Exception as e:
        logging.error(f"Error running MCP server: {e}")
        return 1


def _setup_parser() -> argparse.ArgumentParser:
    """Set up the argument parser with all subcommands."""
    parser = argparse.ArgumentParser(
        description="Web Forager - Search and content retrieval via MCP protocol"
    )
    subparsers = parser.add_subparsers(dest="command", required=True)

    # Serve command
    serve_parser = subparsers.add_parser(
        "serve", help="Start the MCP server over STDIO"
    )
    serve_parser.add_argument(
        "--debug", action="store_true", help="Enable debug logging"
    )

    # Search command
    search_parser = subparsers.add_parser("search", help="Search DuckDuckGo directly")
    search_parser.add_argument("query", nargs="+", help="Search query")
    search_parser.add_argument(
        "--max-results", type=int, default=5, help="Maximum number of results to return"
    )
    search_parser.add_argument(
        "--safesearch",
        choices=["on", "moderate", "off"],
        default="moderate",
        help="Safe search setting (default: moderate)",
    )
    search_parser.add_argument(
        "--output-format",
        choices=["json", "text"],
        default="json",
        dest="output_format",
        help="Output format: 'json' for structured data, 'text' for LLM-friendly (default: json)",
    )

    # News command
    news_parser = subparsers.add_parser("news", help="Search DuckDuckGo news directly")
    news_parser.add_argument("query", nargs="+", help="News search query")
    news_parser.add_argument(
        "--max-results", type=int, default=10, help="Maximum number of results to return"
    )
    news_parser.add_argument(
        "--safesearch",
        choices=["on", "moderate", "off"],
        default="moderate",
        help="Safe search setting (default: moderate)",
    )
    news_parser.add_argument(
        "--output-format",
        choices=["json", "text"],
        default="json",
        dest="output_format",
        help="Output format: 'json' for structured data, 'text' for LLM-friendly (default: json)",
    )

    # Fetch command
    fetch_parser = subparsers.add_parser(
        "fetch", help="Fetch and convert content from a URL"
    )
    fetch_parser.add_argument("url", help="URL to fetch content from")
    fetch_parser.add_argument(
        "--format",
        choices=["markdown", "json"],
        default="markdown",
        help="Output format (default: markdown)",
    )
    fetch_parser.add_argument(
        "--max-length", type=int, help="Maximum length of content to return"
    )
    fetch_parser.add_argument(
        "--with-images", action="store_true", help="Generate alt text for images"
    )

    # Version command
    version_parser = subparsers.add_parser("version", help="Show version information")
    version_parser.add_argument(
        "--debug", action="store_true", help="Show detailed version information"
    )

    return parser


def main() -> int:
    """Main entry point for the command line interface."""
    parser = _setup_parser()
    args = parser.parse_args()

    # Configure logging
    log_level = logging.DEBUG if getattr(args, "debug", False) else logging.INFO
    logging.basicConfig(
        level=log_level, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s"
    )

    # Command dispatch
    handlers: Dict[str, Callable[[argparse.Namespace], int]] = {
        "version": _handle_version,
        "search": _handle_search,
        "news": _handle_news,
        "fetch": _handle_fetch,
        "serve": _handle_serve,
    }

    handler = handlers.get(args.command)
    if handler:
        return handler(args)

    return 0


if __name__ == "__main__":
    sys.exit(main())
