#!/usr/bin/env bash

autocomplete() {
  local CURRENT=${COMP_WORDS[${COMP_CWORD}]}
  local SEARCH="${COMP_WORDS[*]:1}"
  local CURSOR=$((COMP_CWORD - 1))

  local SUGGESTIONS
  local SUGGESTIONS
  local FIRST_CHAR="${SEARCH:0:1}"
  # Fast path for addon commands (start with a-z): read autocomplete.json cache directly, no kernel startup
  # Set AUTOCOMPLETE_NO_CACHE=true to disable
  if [[ "${FIRST_CHAR}" =~ ^[a-z]$ ]] && [[ "${AUTOCOMPLETE_NO_CACHE}" != "true" ]]; then
    SUGGESTIONS=($(${WEX_DIR_ROOT}bin/autocomplete-addon -s "${SEARCH}" -c "${CURSOR}" 2>/dev/null))
  fi
  # Fall back to kernel for empty search, app/user/service commands, or missing cache
  if [[ -z "${SUGGESTIONS[*]}" ]]; then
    SUGGESTIONS=($(wex core::autocomplete/suggest -s "${SEARCH}" -c "${CURSOR}" 2>/dev/null))
  fi

  # "::" is a word separator in bash — clear CURRENT to allow suggestions through
  if [ "${CURRENT}" == "::" ]; then
    CURRENT=""
  fi

  # "@" may be treated as a word separator in bash — restore it for service commands
  if [[ "${SEARCH}" =~ ^@ ]] && [[ "${CURRENT}" != "@" ]] && [[ "${CURSOR}" -eq 1 ]]; then
    CURRENT="@${CURRENT}"
  fi

  COMPREPLY=($(compgen -W "${SUGGESTIONS[*]}" -- "${CURRENT}"))

  # Add trailing space when there is a single unambiguous complete command
  if [[ "${COMPREPLY[*]}" != "" ]] && ! [[ "${COMPREPLY[*]}" =~ [[:space:]] ]]; then
    local MATCH="${COMPREPLY[0]}"
    local ARGS_CURSOR=0

    if [[ "${MATCH}" =~ ^@ ]]; then
      # service: @service::group/command — don't add space on partials ending with ":"
      if [[ "${MATCH}" != *":" ]]; then
        ARGS_CURSOR=4
      fi
    elif [[ "${MATCH}" =~ ^'~' ]]; then
      # user: ~group/command
      ARGS_CURSOR=1
    elif [[ " ${COMPREPLY[*]}" = *"::"* ]] || [[ " ${COMPREPLY[*]}" = *"/"* ]]; then
      # addon: addon::group/command — don't add space on partials ending with ":"
      if [[ " ${COMPREPLY[*]}" != *":" ]]; then
        ARGS_CURSOR=3
      fi
    else
      local TRIMMED
      TRIMMED=$(echo "${COMPREPLY[*]}" | xargs)
      # At cursor 0, a plain word is an addon name prefix — no space (user still needs to type :: or /)
      # At cursor > 0, it is a complete subcommand or argument — add space
      if [[ "${TRIMMED}" =~ ^[a-z\-]+$ ]] && [[ "${CURSOR}" -gt 0 ]]; then
        ARGS_CURSOR=1
      fi
    fi

    if [[ "${ARGS_CURSOR}" -gt 0 ]]; then
      COMPREPLY+=" "
    fi
  fi

  if [[ "${AUTOCOMPLETE_DEBUG}" = "true" ]]; then
    echo "____________"
    echo "COMP_WORDS   : ${COMP_WORDS[*]@Q}"
    echo "COMP_CWORD   : ${COMP_CWORD}"
    echo "WORDBREAKS   : ${COMP_WORDBREAKS@Q}"
    echo "CURSOR       : ${CURSOR}"
    echo "SEARCH       : ${SEARCH}"
    echo "SUGGESTIONS  : ${SUGGESTIONS[*]}"
    echo "CURRENT      : ${CURRENT}"
    echo "COMPREPLY    : ${COMPREPLY[*]}"
  fi
}

autocomplete
