"""CLI entry point for Capcat.

Routes subcommands to legacy capcat_legacy.py / cli.py logic via delegating
stubs.  Every heavy import lives inside the function body (lazy import) so
startup stays fast and circular-import-safe.
"""
from __future__ import annotations
import sys


# ---------------------------------------------------------------------------
# Help
# ---------------------------------------------------------------------------

def _print_help() -> None:
    print(
        "Usage: capcat <command> [options]\n\n"
        "Commands:\n"
        "  init             Initialize a capcat project in the current directory\n"
        "  catch            Launch the interactive TUI\n"
        "  single <url>     Fetch a single article\n"
        "  fetch <sources>  Batch fetch from sources\n"
        "  bundle <name>    Fetch a bundle\n"
        "  list sources     List available sources\n"
        "  add-source       Add a new source\n"
        "  remove-source    Remove a source\n"
        "  generate-config  Generate a YAML config\n"
        "\nOptions:\n"
        "  -L <file>        Log output to file\n"
        "  -V, --verbose    Verbose output\n"
        "  -q, --quiet      Quiet output\n"
        "  --media          Download media files\n"
        "  --html           Generate HTML output\n"
        "  --update         Update existing articles\n"
        "  --help           Show this help\n"
    )


# ---------------------------------------------------------------------------
# Entry point
# ---------------------------------------------------------------------------

def main() -> None:
    """Main entry point.  Routes to TUI or CLI dispatch."""
    args = sys.argv[1:]
    if args and args[0] == "catch":
        from capcat.tui import run
        run()
    else:
        _dispatch(args)


# ---------------------------------------------------------------------------
# Top-level dispatch
# ---------------------------------------------------------------------------

def _dispatch(args: list[str]) -> None:
    if not args or args[0] in ("-h", "--help"):
        _print_help()
        return

    # Handle -L <file> global option before command routing
    log_file = None
    if "-L" in args:
        idx = args.index("-L")
        if idx + 1 < len(args):
            log_file = args[idx + 1]
            args = args[:idx] + args[idx + 2:]
        else:
            print("capcat: -L requires a filename argument")
            raise SystemExit(1)

    command = args[0]
    rest = args[1:]

    if command == "init":
        _cmd_init(rest)
    elif command == "single":
        _cmd_single(rest, log_file=log_file)
    elif command == "fetch":
        _cmd_fetch(rest, log_file=log_file)
    elif command == "bundle":
        _cmd_bundle(rest, log_file=log_file)
    elif command == "list":
        _cmd_list(rest)
    elif command == "add-source":
        _cmd_add_source(rest)
    elif command == "remove-source":
        _cmd_remove_source(rest)
    elif command == "generate-config":
        _cmd_generate_config(rest)
    else:
        print(f"capcat: unknown command '{command}'. Run 'capcat --help'.")
        raise SystemExit(1)


# ---------------------------------------------------------------------------
# Helpers: parse common flags out of a raw arg list
# ---------------------------------------------------------------------------

def _pop_flag(args: list[str], *flags: str) -> tuple[bool, list[str]]:
    """Remove boolean flags from *args*, return (found, remaining)."""
    found = False
    remaining = []
    for a in args:
        if a in flags:
            found = True
        else:
            remaining.append(a)
    return found, remaining


def _pop_value(args: list[str], *flags: str,
               default: str | None = None) -> tuple[str | None, list[str]]:
    """Remove a flag that takes one value, return (value, remaining)."""
    remaining: list[str] = []
    value = default
    skip_next = False
    for i, a in enumerate(args):
        if skip_next:
            skip_next = False
            continue
        if a in flags and i + 1 < len(args):
            value = args[i + 1]
            skip_next = True
        else:
            remaining.append(a)
    return value, remaining


# ---------------------------------------------------------------------------
# init
# ---------------------------------------------------------------------------

def _cmd_init(args: list[str]) -> None:
    from pathlib import Path
    from capcat.commands.init import init_project, AlreadyInitializedError
    reinit = "--reinit" in args
    try:
        init_project(Path.cwd(), reinit=reinit)
        print("Capcat project initialized.")
        print("  Config/   -- your sources, themes, and config")
        print("  .capcat/  -- internal state (don't edit)")
        print(
            "\nRun 'capcat catch' for the interactive menu "
            "or 'capcat --help' for commands."
        )
    except AlreadyInitializedError as exc:
        print(f"Error: {exc}")
        raise SystemExit(1)


# ---------------------------------------------------------------------------
# single <url>
# ---------------------------------------------------------------------------

def _cmd_single(args: list[str], log_file: str | None = None) -> None:
    """capcat single <url> [--output DIR] [--media] [--html] [--update]
       [--verbose] [--quiet] [--log-file FILE]
    """
    if not args or args[0] in ("-h", "--help"):
        print("Usage: capcat single <url> [--output DIR] [--media] "
              "[--html] [--update] [-V] [-q]")
        return

    verbose, args = _pop_flag(args, "-V", "--verbose")
    quiet, args = _pop_flag(args, "-q", "--quiet")
    media, args = _pop_flag(args, "-M", "--media")
    html, args = _pop_flag(args, "-H", "--html")
    update, args = _pop_flag(args, "-U", "--update")
    output, args = _pop_value(args, "-o", "--output", default=".")
    lf, args = _pop_value(args, "-L", "--log-file")
    log_file = lf or log_file

    if not args:
        print("capcat single: URL required")
        raise SystemExit(1)

    url = args[0]

    _setup_logging(verbose=verbose, quiet=quiet, log_file=log_file)

    from capcat.commands.single import scrape_single_article
    scrape_single_article(
        url=url,
        output_dir=output,
        verbose=verbose,
        files=media,
        generate_html=html,
        update_mode=update,
    )


# ---------------------------------------------------------------------------
# fetch <sources>
# ---------------------------------------------------------------------------

def _cmd_fetch(args: list[str], log_file: str | None = None) -> None:
    """capcat fetch <sources> [--count N] [--output DIR] [--media] [--html]
       [--update] [--verbose] [--quiet] [--log-file FILE]
    """
    if not args or args[0] in ("-h", "--help"):
        print("Usage: capcat fetch <sources> [--count N] [--output DIR] "
              "[--media] [--html] [--update] [-V] [-q]")
        return

    verbose, args = _pop_flag(args, "-V", "--verbose")
    quiet, args = _pop_flag(args, "-q", "--quiet")
    media, args = _pop_flag(args, "-M", "--media")
    html, args = _pop_flag(args, "-H", "--html")
    update, args = _pop_flag(args, "-U", "--update")
    output, args = _pop_value(args, "-o", "--output", default=".")
    count_str, args = _pop_value(args, "-c", "--count", default="30")
    lf, args = _pop_value(args, "-L", "--log-file")
    log_file = lf or log_file

    if not args:
        print("capcat fetch: source list required (comma-separated)")
        raise SystemExit(1)

    sources = [s.strip() for s in args[0].split(",")]
    count = int(count_str)

    _setup_logging(verbose=verbose, quiet=quiet, log_file=log_file)

    import argparse as _argparse
    from capcat.core.logging_config import get_logger
    from capcat.commands.fetch import process_sources

    _args = _argparse.Namespace(
        count=count, quiet=quiet, verbose=verbose, media=media
    )
    logger = get_logger(__name__)
    process_sources(
        sources=sources,
        args=_args,
        config=None,
        logger=logger,
        generate_html=html,
        output_dir=output,
    )


# ---------------------------------------------------------------------------
# bundle <name>
# ---------------------------------------------------------------------------

def _cmd_bundle(args: list[str], log_file: str | None = None) -> None:
    """capcat bundle <name> [--count N] [--output DIR] [--media] [--html]
       [--all] [--update] [--verbose] [--quiet] [--log-file FILE]
    """
    if not args or args[0] in ("-h", "--help"):
        print("Usage: capcat bundle <name> [--count N] [--output DIR] "
              "[--media] [--html] [--all] [--update] [-V] [-q]")
        return

    verbose, args = _pop_flag(args, "-V", "--verbose")
    quiet, args = _pop_flag(args, "-q", "--quiet")
    media, args = _pop_flag(args, "-M", "--media")
    html, args = _pop_flag(args, "-H", "--html")
    update, args = _pop_flag(args, "-U", "--update")
    all_bundles, args = _pop_flag(args, "-A", "--all")
    output, args = _pop_value(args, "-o", "--output", default=".")
    count_str, args = _pop_value(args, "-c", "--count", default="30")
    lf, args = _pop_value(args, "-L", "--log-file")
    log_file = lf or log_file

    from capcat.core.source_system.bundle_service import get_available_bundles
    bundles = get_available_bundles()

    if all_bundles:
        ordered = ["techpro", "tech", "news", "science", "ai"]
        active = [b for b in ordered if b in bundles and bundles[b]]
        bundle_name = f"all-bundles-ordered({', '.join(active)})"
        sources = active
    else:
        if not args:
            print("capcat bundle: bundle name required (or --all)")
            raise SystemExit(1)
        bundle_name = args[0]
        if bundle_name not in bundles:
            print(f"capcat bundle: unknown bundle '{bundle_name}'. "
                  f"Available: {', '.join(sorted(bundles.keys()))}")
            raise SystemExit(1)
        sources = bundles[bundle_name]["sources"]

    count = int(count_str)

    _setup_logging(verbose=verbose, quiet=quiet, log_file=log_file)

    import argparse as _argparse
    from capcat.core.logging_config import get_logger
    from capcat.commands.fetch import process_sources

    _args = _argparse.Namespace(
        count=count, quiet=quiet, verbose=verbose, media=media
    )
    logger = get_logger(__name__)
    process_sources(
        sources=sources,
        args=_args,
        config=None,
        logger=logger,
        generate_html=html,
        output_dir=output,
    )


# ---------------------------------------------------------------------------
# list [sources|bundles|all]
# ---------------------------------------------------------------------------

def _cmd_list(args: list[str]) -> None:
    """capcat list [sources|bundles|all]"""
    what = "all"
    if args and args[0] not in ("-h", "--help"):
        what = args[0]

    if what in ("-h", "--help"):
        print("Usage: capcat list [sources|bundles|all]")
        return

    from capcat.core.source_system.source_registry import SourceRegistry
    registry = SourceRegistry()
    registry.discover_sources()

    if what in ("sources", "all"):
        print("\nAvailable sources:")
        for sid in sorted(registry.get_available_sources()):
            cfg = registry.get_source_config(sid)
            name = cfg.display_name if cfg else sid
            print(f"  {sid:<20} {name}")

    if what in ("bundles", "all"):
        from capcat.core.source_system.bundle_service import get_available_bundles
        bundles = get_available_bundles()
        print("\nAvailable bundles:")
        for bundle_id, bundle_data in sorted(bundles.items()):
            sources_list = bundle_data["sources"]
            sources_str = ", ".join(sources_list[:3])
            if len(sources_list) > 3:
                sources_str += f", ... ({len(sources_list)} total)"
            desc = bundle_data.get("description", "")
            print(f"  {bundle_id:<20} {desc}")
            print(f"  {'':20} Sources: {sources_str}")


# ---------------------------------------------------------------------------
# add-source --url <url>
# ---------------------------------------------------------------------------

def _cmd_add_source(args: list[str]) -> None:
    """capcat add-source --url <feed-url>"""
    if not args or args[0] in ("-h", "--help"):
        print("Usage: capcat add-source --url <feed-url>")
        return

    url, args = _pop_value(args, "--url")
    if not url:
        print("capcat add-source: --url is required")
        raise SystemExit(1)

    from capcat.commands.add_source import add_source
    add_source(url)


# ---------------------------------------------------------------------------
# remove-source
# ---------------------------------------------------------------------------

def _cmd_remove_source(args: list[str]) -> None:
    """capcat remove-source [--dry-run] [--batch FILE] [--undo [ID]]
       [--no-backup] [--no-analytics] [--force]
    """
    if args and args[0] in ("-h", "--help"):
        print("Usage: capcat remove-source [--dry-run] [--batch FILE] "
              "[--undo [BACKUP_ID]] [--no-backup] [--no-analytics] [--force]")
        return

    import argparse
    # Build a minimal Namespace matching what legacy remove_source() expects
    dry_run, args = _pop_flag(args, "-n", "--dry-run")
    no_backup, args = _pop_flag(args, "--no-backup")
    no_analytics, args = _pop_flag(args, "--no-analytics")
    force, args = _pop_flag(args, "-f", "--force")
    batch, args = _pop_value(args, "-b", "--batch")

    # --undo can be bare (meaning 'latest') or take a value
    undo_val = None
    if "--undo" in args or "-u" in args:
        _, args = _pop_flag(args, "--undo", "-u")
        # If there's a remaining positional, treat it as backup id
        if args:
            undo_val = args.pop(0)
        else:
            undo_val = "latest"

    ns = argparse.Namespace(
        dry_run=dry_run,
        no_backup=no_backup,
        no_analytics=no_analytics,
        force=force,
        batch=batch,
        undo=undo_val,
    )

    from capcat.commands.remove_source import remove_source
    remove_source(ns)


# ---------------------------------------------------------------------------
# generate-config
# ---------------------------------------------------------------------------

def _cmd_generate_config(args: list[str]) -> None:
    """capcat generate-config [--output FILE]"""
    if args and args[0] in ("-h", "--help"):
        print("Usage: capcat generate-config [--output FILE]")
        return

    import argparse
    output, _ = _pop_value(args, "-o", "--output")
    ns = argparse.Namespace(output=output)

    from capcat.commands.generate_config import generate_config
    generate_config(ns)


# ---------------------------------------------------------------------------
# Logging setup
# ---------------------------------------------------------------------------

def _setup_logging(
    verbose: bool = False,
    quiet: bool = False,
    log_file: str | None = None,
) -> None:
    """Configure logging for the current command."""
    from capcat.core.logging_config import setup_logging
    setup_logging(verbose=verbose, quiet=quiet, log_file=log_file)
