#!/usr/bin/env python3
# Copyright (C) 2026 Danilo M. <danix@danix.xyz>  GPL-2.0-only
"""Generate completions/firefly.bash from the live command registry.

    python scripts/gen_completion.py > completions/firefly.bash

No drift: groups, leaves, and per-leaf flags are read straight off the
argparse subparsers the registry builds.
"""
import argparse
import os
import sys
from collections import defaultdict

# Run from the repo, not any installed copy: prepend the repo root so
# `python scripts/gen_completion.py` imports this tree, not a stale install.
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

from firefly_cli import registry
import firefly_cli.commands  # noqa: F401  triggers registration

GROUP_ORDER = ["auth", "account", "category", "tag", "tx"]

# Static value suggestions for flags whose choices are a fixed enum, keyed on
# "<group leaf>" then flag. Account/transaction types are fixed in Firefly, so
# no API call is needed (a completion must not hit the network).
FLAG_VALUES = {
    "account list": {"--type": "asset expense revenue liability"},
    "account create": {"--type": "asset expense revenue"},
    "tx add": {"--type": "withdrawal deposit transfer"},
    "tx edit": {"--type": "withdrawal deposit transfer"},
}


def collect():
    groups = defaultdict(dict)  # group -> {leaf: [--flag, ...]}
    for c in registry.all_commands():
        g, _, leaf = c.name.partition(" ")
        p = argparse.ArgumentParser()
        if c.args:
            c.args(p)
        opts = []
        for a in p._actions:
            opts += [s for s in a.option_strings
                     if s.startswith("--") and s != "--help"]
        groups[g][leaf] = sorted(opts)
    return groups


def render(groups):
    order = [g for g in GROUP_ORDER if g in groups]
    order += [g for g in sorted(groups) if g not in GROUP_ORDER]

    leaf_cases, group_cases = [], []
    for g in order:
        leaves = " ".join(sorted(groups[g]))
        group_cases.append(f'        {g}) leaves="{leaves}";;')
        for leaf in sorted(groups[g]):
            flags = " ".join(groups[g][leaf])
            if flags:
                leaf_cases.append(
                    f'        "{g} {leaf}")'.ljust(28) + f'leaf_opts="{flags}";;')

    # Per-command flag-value cases: "<group leaf> <flag>") vals="..."
    value_cases = []
    for cmd in sorted(FLAG_VALUES):
        for flag in sorted(FLAG_VALUES[cmd]):
            vals = FLAG_VALUES[cmd][flag]
            value_cases.append(f'        "{cmd} {flag}")'.ljust(34)
                               + f'vals="{vals}";;')

    return TEMPLATE.format(
        groups=" ".join(order),
        leaf_cases="\n".join(leaf_cases),
        group_cases="\n".join(group_cases),
        value_cases="\n".join(value_cases),
    )


TEMPLATE = '''# bash completion for firefly (firefly-cli)
# Install: source this file, or drop it in /etc/bash_completion.d/ or
# /usr/share/bash-completion/completions/firefly
#
# Generated by scripts/gen_completion.py -- do not edit by hand.
# Regenerate when commands change (see CLAUDE.md):
#   python scripts/gen_completion.py > completions/firefly.bash

_firefly() {{
    local cur prev words cword
    _init_completion 2>/dev/null || {{
        cur="${{COMP_WORDS[COMP_CWORD]}}"
        prev="${{COMP_WORDS[COMP_CWORD-1]}}"
        words=("${{COMP_WORDS[@]}}")
        cword=$COMP_CWORD
    }}

    local global_opts="--human --url --token -h --help"
    local groups="{groups}"

    # Find the group and leaf among the words (skip the program name at 0).
    local group="" leaf="" i
    for ((i=1; i < cword; i++)); do
        local w="${{words[i]}}"
        case "$w" in
            -*) ;;                      # an option, skip
            --url|--token) ((i++));;    # option that takes a value
            *)
                if [[ -z $group ]]; then group="$w"
                elif [[ -z $leaf ]]; then leaf="$w"
                fi
                ;;
        esac
    done

    # Leaf-specific options.
    local leaf_opts=""
    case "$group $leaf" in
{leaf_cases}
    esac

    # Leaves per group.
    local leaves=""
    case "$group" in
{group_cases}
    esac

    # Flag values: when the previous word is a flag with a fixed value set for
    # this command, suggest those values instead of more flags.
    local vals=""
    case "$group $leaf $prev" in
{value_cases}
    esac
    if [[ -n $vals ]]; then
        COMPREPLY=($(compgen -W "$vals" -- "$cur"))
        return
    fi

    if [[ -z $group ]]; then
        COMPREPLY=($(compgen -W "$groups $global_opts" -- "$cur"))
    elif [[ -z $leaf ]]; then
        COMPREPLY=($(compgen -W "$leaves" -- "$cur"))
    else
        COMPREPLY=($(compgen -W "$leaf_opts --help" -- "$cur"))
    fi
}}
complete -F _firefly firefly
'''


if __name__ == "__main__":
    print(render(collect()), end="")
