#!/usr/bin/env bash

_MCM_CMD="mx-connect-mgmt"

__mcm_join_quoted() { printf '%q ' "$@"; }

__mcm_update_ifaces() {
    # if [[ -n "${__MCM_IF_CACHE_LOADED:-}" ]]; then
    #     return 0
    # fi

    local -a out=()

    if command -v jq >/dev/null 2>&1; then
        while IFS= read -r name; do
            [[ -n "$name" ]] && out+=("$name")
        done < <("$_MCM_CMD" ls -J 2>/dev/null | jq -r '.[].interfaceName // empty')
    else
        local line name
        while IFS= read -r line; do
            case "$line" in
            *\"interfaceName\"*)
                name="${line#*\"interfaceName\": \"}"
                name="${name%%\"*}"
                [[ -n "$name" ]] && out+=("$name")
                ;;
            esac
        done < <("$_MCM_CMD" ls -J 2>/dev/null)
    fi

    __MCM_IF_CACHE_ALL=("${out[@]}")
    # __MCM_IF_CACHE_LOADED=1
}

# ------------ Filter output by prefix (no prefix = return all) ------------
# Usage:
#   __mcm_ifaces                 # all
#   __mcm_ifaces Cellular        # only entries starting with "Cellular"
#   __mcm_ifaces WiFi            # only entries starting with "WiFi"
#   __mcm_ifaces "Cellular,WiFi" # comma-separated
__mcm_ifaces() {
    __mcm_update_ifaces

    local joined="$*"
    joined="${joined//,/ }"

    local -a want=()
    if [[ -n "$joined" ]]; then
        want=($joined)
    fi

    if ((${#want[@]} == 0)); then
        printf '%s\n' "${__MCM_IF_CACHE_ALL[@]}"
        return 0
    fi

    local name pfx
    for name in "${__MCM_IF_CACHE_ALL[@]}"; do
        for pfx in "${want[@]}"; do
            [[ "$name" == "$pfx"* ]] && {
                printf '%s\n' "$name"
                break
            }
        done
    done
}

__mcm_conf_files() {
    {
        __mcm_ifaces
        printf '%s\n' MoxaConnectionManager
    }
}

__mcm_dyn_conf_sections() {
    local iface=$1
    LC_ALL=C mx-connect-mgmt dyn_conf list "$iface" 2>/dev/null |
        awk -F'[][]' '
        { sub(/\r$/,"") }                      # Remove trailing CR to avoid CRLF matching issues
        /^\[[^]]+\][[:space:]]*$/ { print $2 } # On each [section] header, print its name
    '
}

# Return keys under a given [section] until the next [section]
__mcm_dyn_conf_keys_in_section() {
    local iface=$1 section=$2
    LC_ALL=C mx-connect-mgmt dyn_conf list "$iface" 2>/dev/null |
        awk -v s="$section" '
        # Strip trailing CR (handle CRLF) and trailing spaces/tabs
        { sub(/\r$/, ""); sub(/[ \t]+$/, "") }

        # Enter target section
        $0 == "[" s "]" { hit=1; next }

        # Reaching any next section header -> stop if we were collecting
        /^\[[^]]+\][[:space:]]*$/ { if (hit) exit; next }

        # While in the target section, collect keys of the form: key = value
        hit {
            # Skip blank and full-line comments
            if ($0 ~ /^[[:space:]]*$/) next
            if ($0 ~ /^[[:space:]]*[#;]/) next

            # Take the first "=" as delimiter; left part is the key
            pos = index($0, "=")
            if (pos > 0) {
                key = substr($0, 1, pos - 1)
                sub(/^[ \t]+/, "", key) # trim left
                sub(/[ \t]+$/, "", key) # trim right
                if (key != "") print key
            }
        }
    '
}

_mcm_complete() {
    local cur
    if type _init_completion >/dev/null 2>&1; then
        _init_completion || {
            COMPREPLY=()
            return 0
        }
    else
        cur="${COMP_WORDS[COMP_CWORD]}"
    fi

    local cmd_idx=$COMP_CWORD
    while [[ $cmd_idx -gt 0 && "${COMP_WORDS[cmd_idx]}" != "$_MCM_CMD" ]]; do
        cmd_idx=$((cmd_idx - 1))
    done

    if [[ $COMP_CWORD -eq $((cmd_idx + 1)) ]]; then
        local sub="GPS configure datausage debug default dyn_conf help ls modem nwk_info reload start stop timesync unlock_pin unlock_puk wifi"
        COMPREPLY=($(compgen -W "$sub" -- "${cur:-}"))
        return 0
    fi

    local subcmd="${COMP_WORDS[cmd_idx + 1]}"

    case "$subcmd" in
    configure | default | help | ls | reload | start | stop)
        COMPREPLY=()
        ;;
    GPS)
        if ((COMP_CWORD == cmd_idx + 2)); then
            mapfile -t COMPREPLY < <(
                compgen -W "$(__mcm_ifaces Cellular)" -- "${cur:-}"
            )
            return 0
        fi

        if ((COMP_CWORD == cmd_idx + 3)); then
            COMPREPLY=($(compgen -W "on off get_state get_capability" -- "${cur:-}"))
            return 0
        fi

        COMPREPLY=()
        ;;
    debug)
        if ((COMP_CWORD == cmd_idx + 2)); then
            COMPREPLY=($(compgen -W "diag help listen" -- "${cur:-}"))
            return 0
        fi

        if ((COMP_CWORD == cmd_idx + 3)); then
            local action="${COMP_WORDS[cmd_idx + 2]}"

            case "$action" in
            diag)
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_ifaces Cellular)" -- "${cur:-}"
                )
                return 0
                ;;
            listen)
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_ifaces)" -- "${cur:-}"
                )
                return 0
                ;;
            *)
                COMPREPLY=()
                return 0
                ;;
            esac
        fi

        COMPREPLY=()
        ;;
    dyn_conf)
        if ((COMP_CWORD == cmd_idx + 2)); then
            COMPREPLY=($(compgen -W "help list modify profile save" -- "${cur:-}"))
            return 0
        fi

        local action="${COMP_WORDS[cmd_idx + 2]}"
        case "$action" in
        list)
            if ((COMP_CWORD == cmd_idx + 3)); then
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_conf_files)" -- "${cur:-}"
                )
                return 0
            fi
            ;;
        modify)
            # <conf>
            if ((COMP_CWORD == cmd_idx + 3)); then
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_conf_files)" -- "${cur:-}"
                )
                return 0
            fi

            # <group>
            if ((COMP_CWORD == cmd_idx + 4)); then
                local iface="${words[cmd_idx + 3]}"
                local -a _secs=()
                readarray -t _secs < <(__mcm_dyn_conf_sections "$iface")
                ((${#_secs[@]})) || {
                    COMPREPLY=()
                    return 0
                }

                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_join_quoted "${_secs[@]}")" -- "${cur:-}"
                )
                return 0
            fi

            # <key>
            if ((COMP_CWORD == cmd_idx + 5)); then
                local iface="${words[cmd_idx + 3]}"
                local section="${words[cmd_idx + 4]}"
                local -a _keys=()
                readarray -t _keys < <(__mcm_dyn_conf_keys_in_section "$iface" "$section")
                ((${#_keys[@]})) || {
                    COMPREPLY=()
                    return 0
                }

                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_join_quoted "${_keys[@]}")" -- "${cur:-}"
                )
                return 0
            fi
            ;;

        profile)
            if ((COMP_CWORD == cmd_idx + 3)); then
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_ifaces)" -- "${cur:-}"
                )
                return 0
            fi

            if ((COMP_CWORD == cmd_idx + 4)); then
                COMPREPLY=($(compgen -W "add del" -- "${cur:-}"))
                return 0
            fi
            ;;
        help | save)
            if ((COMP_CWORD == cmd_idx + 3)); then
                COMPREPLY=()
                return 0
            fi
            ;;
        *)
            COMPREPLY=()
            return 0
            ;;
        esac

        COMPREPLY=()
        ;;
    modem)
        if ((COMP_CWORD == cmd_idx + 2)); then
            COMPREPLY=($(compgen -W "help upgrade" -- "${cur:-}"))
            return 0
        fi

        if ((COMP_CWORD == cmd_idx + 3)); then
            local action="${COMP_WORDS[cmd_idx + 2]}"

            case "$action" in
            upgrade)
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_ifaces Cellular)" -- "${cur:-}"
                )
                return 0
                ;;
            *)
                COMPREPLY=()
                return 0
                ;;
            esac
        fi

        COMPREPLY=()
        ;;
    nwk_info | datausage)
        if ((COMP_CWORD == cmd_idx + 2)); then
            mapfile -t COMPREPLY < <(
                compgen -W "$(__mcm_ifaces)" -- "${cur:-}"
            )
            return 0
        fi

        COMPREPLY=()
        ;;
    timesync)
        if ((COMP_CWORD == cmd_idx + 2)); then
            COMPREPLY=($(compgen -W "Disabled Chrony GPS Cellular" -- "${cur:-}"))
            return 0
        fi

        if ((COMP_CWORD == cmd_idx + 3)); then
            local action="${COMP_WORDS[cmd_idx + 2]}"

            case "$action" in
            GPS | Cellular)
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_ifaces Cellular)" -- "${cur:-}"
                )
                return 0
                ;;
            *)
                COMPREPLY=()
                return 0
                ;;
            esac
        fi

        COMPREPLY=()
        ;;
    unlock_pin | unlock_puk)
        if ((COMP_CWORD == cmd_idx + 2)); then
            mapfile -t COMPREPLY < <(
                compgen -W "$(__mcm_ifaces Cellular)" -- "${cur:-}"
            )
            return 0
        fi

        COMPREPLY=()
        ;;
    wifi)
        if ((COMP_CWORD == cmd_idx + 2)); then
            COMPREPLY=($(compgen -W "ap_list help rescan" -- "${cur:-}"))
            return 0
        fi

        if ((COMP_CWORD == cmd_idx + 3)); then
            local action="${COMP_WORDS[cmd_idx + 2]}"

            case "$action" in
            ap_list | rescan)
                mapfile -t COMPREPLY < <(
                    compgen -W "$(__mcm_ifaces WiFi)" -- "${cur:-}"
                )
                return 0
                ;;
            *)
                COMPREPLY=()
                return 0
                ;;
            esac
        fi

        COMPREPLY=()
        ;;
    *)
        COMPREPLY=()
        ;;
    esac
}

complete -F _mcm_complete "$_MCM_CMD"
