from __future__ import annotations

import argparse
from typing import Any, Dict, Tuple

from auditwalk.cli.registry import ArgSpec, CommandRegistry, OptSpec


def _dest_from_flags(flags: Tuple[str, ...]) -> str:
    long_flags = [f for f in flags if f.startswith("--")]
    base = (long_flags[0] if long_flags else flags[0]).lstrip("-")
    return base.replace("-", "_")


def _add_option(parser: argparse.ArgumentParser, opt: OptSpec) -> None:
    kwargs: Dict[str, Any] = {"help": opt.help, "dest": _dest_from_flags(opt.flags)}
    if opt.takes_value:
        kwargs["default"] = opt.default
        if opt.choices:
            kwargs["choices"] = list(opt.choices)
        parser.add_argument(*opt.flags, **kwargs)
    else:
        parser.add_argument(*opt.flags, action="store_true", **kwargs)


def _add_positional(parser: argparse.ArgumentParser, arg: ArgSpec) -> None:
    kwargs: Dict[str, Any] = {"help": arg.help}
    if arg.nargs:
        kwargs["nargs"] = arg.nargs
    elif not arg.required:
        kwargs["nargs"] = "?"
    parser.add_argument(arg.name, **kwargs)


def _noun_help(registry: CommandRegistry, noun: str) -> str:
    verbs = registry.verbs(noun)
    preview = ", ".join(verbs[:5])
    suffix = "..." if len(verbs) > 5 else ""
    return f"{noun}: {preview}{suffix}" if preview else noun


def build_argparse_app(registry: CommandRegistry) -> argparse.ArgumentParser:
    root = argparse.ArgumentParser(
        prog="auditwalk",
        description="AuditWalk - system integrity scanning and change detection.",
    )
    root.set_defaults(_aw_is_root=True)

    noun_subparsers = root.add_subparsers(dest="_aw_noun", metavar="<noun>")
    noun_subparsers.required = False

    verb_subparsers: Dict[str, argparse._SubParsersAction] = {}
    for noun in registry.nouns():
        noun_parser = noun_subparsers.add_parser(noun, help=_noun_help(registry, noun))
        noun_parser.set_defaults(_aw_noun=noun)
        vs = noun_parser.add_subparsers(dest="_aw_verb", metavar="<verb>")
        vs.required = True
        verb_subparsers[noun] = vs

    for spec in registry.all_specs():
        vs = verb_subparsers[spec.noun]
        verb_parser = vs.add_parser(spec.verb, help=spec.summary, description=spec.summary)
        verb_parser.set_defaults(_aw_noun=spec.noun, _aw_verb=spec.verb, _aw_handler=spec.handler)
        for arg in spec.args:
            _add_positional(verb_parser, arg)
        for opt in spec.opts:
            _add_option(verb_parser, opt)

    return root
