#compdef vinput

_vinput_installed_models() {
    local -a models
    models=(${(f)"$(vinput -j model list 2>/dev/null | grep -o '"id": *"[^"]*"' | cut -d'"' -f4)"})
    if (( $#models )); then
        _describe -t models 'installed model' models
    fi
}

_vinput_installed_scenes() {
    local -a scenes
    scenes=(${(f)"$(vinput -j scene list 2>/dev/null | grep -o '"id": *"[^"]*"' | cut -d'"' -f4)"})
    if (( $#scenes )); then
        _describe -t scenes 'installed scene' scenes
    fi
}

_vinput_installed_providers() {
    local -a providers
    providers=(${(f)"$(vinput -j provider list 2>/dev/null | grep -o '"id": *"[^"]*"' | cut -d'"' -f4)"})
    if (( $#providers )); then
        _describe -t providers 'installed provider' providers
    fi
}

_vinput_installed_llm_providers() {
    local -a llm_providers
    llm_providers=(${(f)"$(vinput -j llm list 2>/dev/null | grep -o '"id": *"[^"]*"' | cut -d'"' -f4)"})
    if (( $#llm_providers )); then
        _describe -t llm_providers 'configured llm provider' llm_providers
    fi
}

_vinput_installed_adapters() {
    local -a adapters
    adapters=(${(f)"$(vinput -j adapter list 2>/dev/null | grep -o '"id": *"[^"]*"' | cut -d'"' -f4)"})
    if (( $#adapters )); then
        _describe -t adapters 'configured adapter' adapters
    fi
}

_vinput_subcommands() {
    local -a subcommands
    subcommands=(
        'init:Initialize default config and directories'
        'model:Manage offline local ASR models'
        'provider:Manage cloud ASR providers'
        'llm:Manage LLM providers'
        'adapter:Manage LLM adapters'
        'hotword:Manage hotword file'
        'device:Manage audio capture devices'
        'scene:Manage recognition scenes'
        'config:Read or write configuration values'
        'daemon:Control daemon lifecycle'
        'recording:Control voice recording'
        'rec:Control voice recording (alias)'
    )
    _describe -t subcommands 'vinput subcommand' subcommands
}

_vinput_model_cmds() {
    local -a model_cmds
    model_cmds=(
        'list:List installed or remote models'
        'ls:List installed or remote models'
        'add:Download and install a model'
        'use:Set active local ASR model'
        'remove:Uninstall a local model'
        'rm:Uninstall a local model'
        'info:Show model details'
    )
    _describe -t model_cmds 'model command' model_cmds
}

_vinput_provider_cmds() {
    local -a provider_cmds
    provider_cmds=(
        'list:List configured or remote providers'
        'ls:List configured or remote providers'
        'add:Install a provider script from registry'
        'use:Set active ASR provider'
        'edit:Edit provider script in editor'
        'e:Edit provider script in editor'
        'remove:Uninstall an ASR provider'
        'rm:Uninstall an ASR provider'
    )
    _describe -t provider_cmds 'provider command' provider_cmds
}

_vinput_llm_cmds() {
    local -a llm_cmds
    llm_cmds=(
        'list:List configured LLM providers'
        'ls:List configured LLM providers'
        'add:Add an LLM provider'
        'edit:Edit an LLM provider'
        'e:Edit an LLM provider'
        'remove:Remove an LLM provider'
        'rm:Remove an LLM provider'
        'test:Test LLM provider connectivity'
    )
    _describe -t llm_cmds 'llm command' llm_cmds
}

_vinput_adapter_cmds() {
    local -a adapter_cmds
    adapter_cmds=(
        'list:List local or remote adapters'
        'ls:List local or remote adapters'
        'ps:List adapter processes and runtime status'
        'status:Show adapter status'
        'add:Install an adapter script'
        'start:Start an adapter process'
        'stop:Stop an adapter process'
        'restart:Restart an adapter process'
        'enable:Enable adapter autostart with daemon'
        'disable:Disable adapter autostart with daemon'
    )
    _describe -t adapter_cmds 'adapter command' adapter_cmds
}

_vinput_hotword_cmds() {
    local -a hotword_cmds
    hotword_cmds=(
        'get:Show configured hotword file path'
        'set:Set hotword file path'
        'clear:Clear hotword file path'
        'edit:Edit hotword file in editor'
        'e:Edit hotword file in editor'
    )
    _describe -t hotword_cmds 'hotword command' hotword_cmds
}

_vinput_device_cmds() {
    local -a device_cmds
    device_cmds=(
        'list:List available audio input devices'
        'ls:List available audio input devices'
        'use:Set active capture device'
    )
    _describe -t device_cmds 'device command' device_cmds
}

_vinput_scene_cmds() {
    local -a scene_cmds
    scene_cmds=(
        'list:List all scenes'
        'ls:List all scenes'
        'add:Add a new scene'
        'edit:Edit an existing scene'
        'e:Edit an existing scene'
        'use:Set active scene'
        'remove:Remove a scene'
        'rm:Remove a scene'
    )
    _describe -t scene_cmds 'scene command' scene_cmds
}

_vinput_config_cmds() {
    local -a config_cmds
    config_cmds=(
        'get:Get a config value by JSON Pointer'
        'set:Set a config value by JSON Pointer'
        'edit:Open config file in editor'
        'e:Open config file in editor'
    )
    _describe -t config_cmds 'config command' config_cmds
}

_vinput_daemon_cmds() {
    local -a daemon_cmds
    daemon_cmds=(
        'status:Show daemon status'
        'start:Start daemon service'
        'stop:Stop daemon service'
        'restart:Restart daemon service'
        'log:Show daemon logs'
    )
    _describe -t daemon_cmds 'daemon command' daemon_cmds
}

_vinput_rec_cmds() {
    local -a rec_cmds
    rec_cmds=(
        'start:Start voice recording'
        'stop:Stop voice recording and recognize'
        'toggle:Toggle voice recording'
    )
    _describe -t rec_cmds 'recording command' rec_cmds
}

_vinput() {
    local curcontext="$curcontext" state line
    typeset -A opt_args

    _arguments -C \
        '(-j --json)'{-j,--json}'[Output in JSON format]' \
        '(-h --help)'{-h,--help}'[Print help message and exit]' \
        '(-v --version)'{-v,--version}'[Display program version and exit]' \
        '1:subcommand:_vinput_subcommands' \
        '*::arg:->subcmd' && return 0

    case $state in
        subcmd)
            local cmd=$words[1]
            curcontext="${curcontext%:*:*}:vinput-${cmd}:"
            case $cmd in
                init)
                    _arguments \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '(-f --force)'{-f,--force}'[Overwrite existing config]'
                    ;;
                model)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_model_cmds' \
                        '*::arg:->model_args' && return 0
                    case $state in
                        model_args)
                            case $words[1] in
                                list|ls)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-a --available)'{-a,--available}'[List remote models]' ;;
                                use|remove|rm|info)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:model:_vinput_installed_models' ;;
                            esac
                            ;;
                    esac
                    ;;
                provider)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_provider_cmds' \
                        '*::arg:->provider_args' && return 0
                    case $state in
                        provider_args)
                            case $words[1] in
                                list|ls)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-a --available)'{-a,--available}'[List remote providers]' ;;
                                use|edit|e|remove|rm)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:provider:_vinput_installed_providers' ;;
                            esac
                            ;;
                    esac
                    ;;
                llm)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_llm_cmds' \
                        '*::arg:->llm_args' && return 0
                    case $state in
                        llm_args)
                            case $words[1] in
                                add)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-u --base-url)'{-u,--base-url}'[Base URL]:url:' \
                                        '(-k --api-key)'{-k,--api-key}'[API key]:key:' \
                                        '(-e --extra-body)'{-e,--extra-body}'[Extra JSON body]:json:' ;;
                                edit|e|remove|rm|test)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-u --base-url)'{-u,--base-url}'[Base URL]:url:' \
                                        '(-k --api-key)'{-k,--api-key}'[API key]:key:' \
                                        '(-e --extra-body)'{-e,--extra-body}'[Extra JSON body]:json:' \
                                        '1:provider:_vinput_installed_llm_providers' ;;
                            esac
                            ;;
                    esac
                    ;;
                adapter)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_adapter_cmds' \
                        '*::arg:->adapter_args' && return 0
                    case $state in
                        adapter_args)
                            case $words[1] in
                                list|ls)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-a --available)'{-a,--available}'[List remote adapters]' ;;
                                start|stop|restart|enable|disable|status)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:adapter:_vinput_installed_adapters' ;;
                            esac
                            ;;
                    esac
                    ;;
                hotword)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_hotword_cmds' \
                        '*::arg:->hotword_args' && return 0
                    case $state in
                        hotword_args)
                            case $words[1] in
                                set)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:file:_files' ;;
                            esac
                            ;;
                    esac
                    ;;
                device)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_device_cmds' \
                        '*::arg:->device_args' && return 0
                    ;;
                scene)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_scene_cmds' \
                        '*::arg:->scene_args' && return 0
                    case $state in
                        scene_args)
                            case $words[1] in
                                add|edit|e)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '--id[Scene ID]:id:' \
                                        '(-l --label)'{-l,--label}'[Display label]:label:' \
                                        '(-t --prompt)'{-t,--prompt}'[LLM prompt]:prompt:' \
                                        '(-p --provider)'{-p,--provider}'[LLM provider ID]:provider:_vinput_installed_llm_providers' \
                                        '(-m --model)'{-m,--model}'[LLM model ID]:model:' \
                                        '(-c --count)'{-c,--count}'[Maximum number of LLM candidates]:count:' \
                                        '--timeout[Request timeout in ms]:ms:' \
                                        '--context-lines[Context history lines]:lines:' \
                                        '1:scene:_vinput_installed_scenes' ;;
                                use|remove|rm)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:scene:_vinput_installed_scenes' ;;
                            esac
                            ;;
                    esac
                    ;;
                config)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_config_cmds' \
                        '*::arg:->config_args' && return 0
                    case $state in
                        config_args)
                            case $words[1] in
                                edit|e)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:target:(core fcitx)' ;;
                                set)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-i --stdin)'{-i,--stdin}'[Read value from stdin]' \
                                        '1:path:' \
                                        '2:value:' ;;
                                get)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '1:path:' ;;
                            esac
                            ;;
                    esac
                    ;;
                daemon)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_daemon_cmds' \
                        '*::arg:->daemon_args' && return 0
                    case $state in
                        daemon_args)
                            case $words[1] in
                                log)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-f --follow)'{-f,--follow}'[Follow log output]' \
                                        '(-n --lines)'{-n,--lines}'[Number of log lines]:lines:' ;;
                            esac
                            ;;
                    esac
                    ;;
                recording|rec)
                    _arguments -C \
                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                        '1:command:_vinput_rec_cmds' \
                        '*::arg:->rec_args' && return 0
                    case $state in
                        rec_args)
                            case $words[1] in
                                stop|toggle)
                                    _arguments \
                                        '(-h --help)'{-h,--help}'[Print help message and exit]' \
                                        '(-s --scene)'{-s,--scene}'[Scene ID]:scene:_vinput_installed_scenes' ;;
                            esac
                            ;;
                    esac
                    ;;
            esac
            ;;
    esac
}

if [[ -n "$compstate[context]" ]]; then
    _vinput "$@"
else
    compdef _vinput vinput 2>/dev/null || true
fi
