# Falyx CLI Framework — (c) 2025 rtj.dev LLC — MIT Licensed
"""parsers.py
This module contains the argument parsers used for the Falyx CLI.
"""
from argparse import ArgumentParser, Namespace, _SubParsersAction
from dataclasses import asdict, dataclass
from typing import Any, Sequence


@dataclass
class FalyxParsers:
    """Defines the argument parsers for the Falyx CLI."""

    root: ArgumentParser
    subparsers: _SubParsersAction
    run: ArgumentParser
    run_all: ArgumentParser
    preview: ArgumentParser
    list: ArgumentParser
    version: ArgumentParser

    def parse_args(self, args: Sequence[str] | None = None) -> Namespace:
        """Parse the command line arguments."""
        return self.root.parse_args(args)

    def as_dict(self) -> dict[str, ArgumentParser]:
        """Convert the FalyxParsers instance to a dictionary."""
        return asdict(self)

    def get_parser(self, name: str) -> ArgumentParser | None:
        """Get the parser by name."""
        return self.as_dict().get(name)


def get_arg_parsers(
    prog: str | None = "falyx",
    usage: str | None = None,
    description: str | None = "Falyx CLI - Run structured async command workflows.",
    epilog: (
        str | None
    ) = "Tip: Use 'falyx run ?[COMMAND]' to preview any command from the CLI.",
    parents: Sequence[ArgumentParser] | None = None,
    prefix_chars: str = "-",
    fromfile_prefix_chars: str | None = None,
    argument_default: Any = None,
    conflict_handler: str = "error",
    add_help: bool = True,
    allow_abbrev: bool = True,
    exit_on_error: bool = True,
) -> FalyxParsers:
    """Returns the argument parser for the CLI."""
    parser = ArgumentParser(
        prog=prog,
        usage=usage,
        description=description,
        epilog=epilog,
        parents=parents if parents else [],
        prefix_chars=prefix_chars,
        fromfile_prefix_chars=fromfile_prefix_chars,
        argument_default=argument_default,
        conflict_handler=conflict_handler,
        add_help=add_help,
        allow_abbrev=allow_abbrev,
        exit_on_error=exit_on_error,
    )
    parser.add_argument(
        "--never-prompt",
        action="store_true",
        help="Run in non-interactive mode with all prompts bypassed.",
    )
    parser.add_argument(
        "-v", "--verbose", action="store_true", help="Enable debug logging for Falyx."
    )
    parser.add_argument(
        "--debug-hooks",
        action="store_true",
        help="Enable default lifecycle debug logging",
    )
    parser.add_argument("--version", action="store_true", help="Show Falyx version")
    subparsers = parser.add_subparsers(dest="command")

    run_parser = subparsers.add_parser("run", help="Run a specific command")
    run_parser.add_argument("name", help="Key, alias, or description of the command")
    run_parser.add_argument(
        "--summary",
        action="store_true",
        help="Print an execution summary after command completes",
    )
    run_parser.add_argument(
        "--retries", type=int, help="Number of retries on failure", default=0
    )
    run_parser.add_argument(
        "--retry-delay",
        type=float,
        help="Initial delay between retries in (seconds)",
        default=0,
    )
    run_parser.add_argument(
        "--retry-backoff", type=float, help="Backoff factor for retries", default=0
    )
    run_group = run_parser.add_mutually_exclusive_group(required=False)
    run_group.add_argument(
        "-c",
        "--confirm",
        dest="force_confirm",
        action="store_true",
        help="Force confirmation prompts",
    )
    run_group.add_argument(
        "-s",
        "--skip-confirm",
        dest="skip_confirm",
        action="store_true",
        help="Skip confirmation prompts",
    )

    run_all_parser = subparsers.add_parser(
        "run-all", help="Run all commands with a given tag"
    )
    run_all_parser.add_argument("-t", "--tag", required=True, help="Tag to match")
    run_all_parser.add_argument(
        "--summary",
        action="store_true",
        help="Print a summary after all tagged commands run",
    )
    run_all_parser.add_argument(
        "--retries", type=int, help="Number of retries on failure", default=0
    )
    run_all_parser.add_argument(
        "--retry-delay",
        type=float,
        help="Initial delay between retries in (seconds)",
        default=0,
    )
    run_all_parser.add_argument(
        "--retry-backoff", type=float, help="Backoff factor for retries", default=0
    )
    run_all_group = run_all_parser.add_mutually_exclusive_group(required=False)
    run_all_group.add_argument(
        "-c",
        "--confirm",
        dest="force_confirm",
        action="store_true",
        help="Force confirmation prompts",
    )
    run_all_group.add_argument(
        "-s",
        "--skip-confirm",
        dest="skip_confirm",
        action="store_true",
        help="Skip confirmation prompts",
    )

    preview_parser = subparsers.add_parser(
        "preview", help="Preview a command without running it"
    )
    preview_parser.add_argument("name", help="Key, alias, or description of the command")

    list_parser = subparsers.add_parser(
        "list", help="List all available commands with tags"
    )

    version_parser = subparsers.add_parser("version", help="Show the Falyx version")

    return FalyxParsers(
        root=parser,
        subparsers=subparsers,
        run=run_parser,
        run_all=run_all_parser,
        preview=preview_parser,
        list=list_parser,
        version=version_parser,
    )
