from __future__ import annotations

"""
Public CLI interface for the tool.

This module exposes a simple command-line wrapper around the pipeline,
allowing users to clean a Dartdoc HTML directory and produce a ZIP archive.

Manual execution example:
    python -m dartdoc_advanced.cli.cli INPUT_DIR OUTPUT_ZIP [options]
"""

from pathlib import Path
import argparse

from dartdoc_advanced.pipeline.runner import run_pipeline


DEFAULT_MIN_CHARS = 350
DEFAULT_TINY_CHARS = 150


def _parse_args() -> argparse.Namespace:
    """
    Parse command-line arguments and return a populated Namespace object.

    The CLI accepts two positional arguments:
        input_dir:    Path to the root of the Dartdoc HTML directory (usually doc/api).
        output_zip:   Destination ZIP path (with or without the .zip extension).

    Additionally, it supports two optional parameters controlling stub detection:
        --min-chars:   Threshold for sidebar and library-related HTML files.
        --tiny-chars:  Threshold for general tiny stub pages.

    These thresholds allow users to tune how aggressively the tool identifies
    and removes small HTML files.
    """
    parser = argparse.ArgumentParser(
        prog="dartdoc-advanced",
        description=(
            "Clean dartdoc HTML output (remove stubs, fix links) "
            "and produce a single ZIP archive."
        ),
    )

    parser.add_argument(
        "input_dir",
        type=Path,
        help="Path to the doc/api directory generated by Dartdoc.",
    )

    parser.add_argument(
        "output_zip",
        type=Path,
        help=(
            "Destination path for the resulting ZIP file. "
            "You may provide a name with or without the '.zip' extension, e.g.: "
            "`output/MyApiDocs` or `output/MyApiDocs.zip`."
        ),
    )

    parser.add_argument(
        "--min-chars",
        type=int,
        default=DEFAULT_MIN_CHARS,
        help=(
            "Minimum text length required for *-sidebar.html and *-library.html "
            f"files to avoid being treated as stubs. Default: {DEFAULT_MIN_CHARS}."
        ),
    )

    parser.add_argument(
        "--tiny-chars",
        type=int,
        default=DEFAULT_TINY_CHARS,
        help=(
            "Minimum text length required for other small stub files. "
            f"Default: {DEFAULT_TINY_CHARS}."
        ),
    )

    return parser.parse_args()


def _normalize_zip_base(output_zip: Path) -> Path:
    """
    Normalize the user-provided ZIP path so that run_pipeline receives
    a base path without the '.zip' extension.

    Users may supply:
        - a path without .zip extension (e.g., output/MyDocs)
        - a path with .zip extension (e.g., output/MyDocs.zip)

    Regardless of the format, the pipeline expects the base path
    without any extension because it creates the ZIP itself by appending ".zip".
    """
    output_zip = output_zip.expanduser().resolve()
    if output_zip.suffix == ".zip":
        return output_zip.with_suffix("")
    return output_zip


def main() -> None:
    """
    Entry point for running the cleaner and packager from the command line.

    Steps:
        1. Parse CLI arguments.
        2. Validate that the input directory exists.
        3. Normalize the ZIP base path (remove .zip suffix if present).
        4. Invoke the pipeline to clean the documentation and produce a ZIP.
        5. Print the final ZIP file location for the user.

    This function is intentionally minimal, delegating all heavy logic
    to `run_pipeline` in the pipeline module.
    """
    args = _parse_args()

    src = args.input_dir.expanduser().resolve()
    if not src.exists():
        raise FileNotFoundError(f"Input directory not found: {src}")

    zip_base = _normalize_zip_base(args.output_zip)

    zip_path = run_pipeline(
        src=src,
        zip_base=zip_base,
        min_chars=args.min_chars,
        tiny_chars=args.tiny_chars,
    )

    print(f"ZIP created at: {zip_path}")


if __name__ == "__main__":
    main()
