#!/usr/bin/env bash

# ============================================
# Private helpers
# ============================================

function cmd::shell::_prompt() {
  local user host dir
  user=$(whoami)
  host=$(hostname -s)
  dir=$(basename "$PWD")
  printf "\033[1;32m%s@%s\033[0m:\033[0;36m%s\033[0m \033[1;34mwgctl\033[0m> " \
    "$user" "$host" "$dir"
}

function cmd::shell::_is_wgctl_command() {
  local cmd="$1"
  # Check against known wgctl commands
  local known=(
    list add remove rm inspect block unblock
    rule group audit logs watch fw config qr
    rename keys ip service shell help
  )
  local c
  for c in "${known[@]}"; do
    [[ "$c" == "$cmd" ]] && return 0
  done
  return 1
}

function cmd::shell::_handle_builtin() {
  local input="$1"
  local first="${input%% *}"
  
  case "$first" in
    cd)
      local dir="${input#cd }"
      [[ "$dir" == "$input" ]] && dir="$HOME"
      cd "$dir" 2>/dev/null || log::error "cd: $dir: No such file or directory"
      return 0
      ;;
    cd*) eval "$input" ;;  # eval preserves shell state for cd
    export|unset|source|.)
      eval "$input"
      return 0
      ;;
  esac
  return 1  # not a builtin
}

function cmd::shell::_execute() {
  local input="$1"
  local first="${input%% *}"
  local rest="${input#"$first"}"
  rest="${rest# }"

  # Handle shell builtins first
  cmd::shell::_handle_builtin "$input" && return 0

  # Try as wgctl command via dispatcher
  if cmd::shell::_is_wgctl_command "$first"; then
    if [[ -n "$rest" ]]; then
      wgctl::dispatch "$first" $rest || true # never exit REPL on failure
    else
      wgctl::dispatch "$first" || true
    fi
    return 0 # Always 0 to keep REPL running
  fi

  # Fall back to bash
  bash -c "$input" || true # same for bash commands
}

function cmd::shell::_setup_history() {
  HISTFILE="${HOME}/.wgctl_history"
  HISTSIZE=1000
  HISTFILESIZE=2000
  history -r 2>/dev/null || true
}

function cmd::shell::_save_history() {
  history -w 2>/dev/null || true
}

function cmd::shell::_banner() {
  ui::section "wgctl shell"
  printf "\n"
  printf "  Type wgctl commands directly, or any bash command.\n"
  printf "  Type \033[1mexit\033[0m or \033[1mquit\033[0m to leave.\n"
  printf "  Type \033[1mhelp\033[0m for wgctl commands.\n"
  printf "\n"
}

# ============================================
# Run
# ============================================

function cmd::shell::on_load() {
  : # no flags needed
}

function cmd::shell::help() {
  cat <<EOF
Usage: wgctl shell

Start an interactive wgctl shell. Supports all wgctl commands
directly (no 'wgctl' prefix needed), plus any bash command.

Builtins handled: cd, export, unset, source
Everything else: passed to bash

Examples:
  wgctl shell
  wgctl> list
  wgctl> inspect --name phone-nuno
  wgctl> ls /etc/wireguard
  wgctl> exit
EOF
}

function cmd::shell::run() {
  cmd::shell::_banner
  cmd::shell::_setup_history

  while true; do
    local input
    # Read with readline support (-e) and custom prompt
    IFS= read -r -e -p "$(cmd::shell::_prompt)" input || break

    # Handle empty input
    [[ -z "${input// }" ]] && continue

    # Add to history
    history -s "$input"

    # Handle exit
    case "${input%% *}" in
      exit|quit) break ;;
    esac

    # Execute
    cmd::shell::_execute "$input"
  done

  cmd::shell::_save_history
  printf "\n  Goodbye!\n\n"
}

# ============================================
# Tab completion (loaded when shell starts)
# ============================================

function cmd::shell::_setup_completion() {
  local commands="list add remove inspect block unblock rule group audit logs watch fw config qr rename shell help"
  
  function _wgctl_shell_complete() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
  }
  
  # Bind completion to the read prompt
  bind 'set show-all-if-ambiguous on' 2>/dev/null || true
  bind 'set completion-ignore-case on' 2>/dev/null || true
}