#!/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:-}"
  local known=(
    list add remove rm inspect block unblock
    rule group audit logs watch fw config qr
    rename keys ip net service shell help test
    peer hosts identity subnet policy activity
  )
  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
      ;;
    export|unset|source|.)
      eval "$input"
      return 0
      ;;
  esac
  return 1
}

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

  cmd::shell::_handle_builtin "$input" && return 0

  if cmd::shell::_is_wgctl_command "$first"; then
    if [[ -n "$rest" ]]; then
      wgctl::dispatch "$first" $rest || true
    else
      wgctl::dispatch "$first" || true
    fi
    return 0
  fi

  bash -c "$input" || true
}

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 (no 'wgctl' prefix).\n"
  printf "  Bash commands work too: ls, cat, systemctl, vim...\n\n"
  printf "  \033[1;37mPeer management:\033[0m\n"
  printf "    list                              List all peers\n"
  printf "    list --blocked                    Show blocked peers\n"
  printf "    list --rule user                  Filter by rule\n"
  printf "    inspect --name <peer>             Full peer details\n"
  printf "    add --identity <id> --type phone  Add a peer\n"
  printf "    block --name <peer>               Block a peer\n"
  printf "    unblock --name <peer>             Restore access\n"
  printf "    peer update-dns --all             Update DNS on all peers\n"
  printf "    peer update-tunnel --name <p> --mode split\n\n"
  printf "  \033[1;37mRules & access:\033[0m\n"
  printf "    rule list                         Show firewall rules\n"
  printf "    rule list --tree                  Show with inheritance\n"
  printf "    rule assign --name <r> --peer <p> Assign rule to peer\n"
  printf "    identity list                     Show identities\n"
  printf "    identity show --name <id>         Identity details + rule tree\n"
  printf "    identity rule assign --name <id> --rule <r>\n\n"
  printf "  \033[1;37mNetwork & services:\033[0m\n"
  printf "    net list                          Show network services\n"
  printf "    net list --detailed               Show with ports\n"
  printf "    hosts list                        Show host annotations\n"
  printf "    subnet list                       Show subnets\n"
  printf "    group list                        Show groups\n"
  printf "    group block --name <group>        Block all in group\n\n"
  printf "  \033[1;37mMonitoring:\033[0m\n"
  printf "    logs                              Activity logs\n"
  printf "    logs --since 2h                   Logs from last 2h\n"
  printf "    logs --fw --service pihole        FW drops to service\n"
  printf "    logs --wg --event handshake       WG handshake events\n"
  printf "    logs --resolved                   Show resolved names only\n"
  printf "    logs --follow                     Live activity log\n"
  printf "    logs clean                        Remove keepalive entries\n"
  printf "    logs rotate                       Clean old log entries\n"
  printf "    watch                             Live WG + firewall monitor\n"
  printf "    activity                          Transfer + drop summary\n"
  printf "    fw list                           Show iptables rules\n"
  printf "    audit                             Verify firewall state\n"
  printf "    audit --fix                       Auto-repair firewall\n\n"
  printf "  \033[1mexit\033[0m or \033[1mquit\033[0m to leave  ·  \033[1mhelp\033[0m for full command list\n\n"
}

# ============================================
# Lifecycle
# ============================================

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

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

Start an interactive wgctl shell.
All wgctl commands work directly (no 'wgctl' prefix needed).
Bash commands (ls, cat, systemctl, vim, etc.) also work.

Shell builtins handled natively: cd, export, unset, source
History saved to: ~/.wgctl_history

Examples:
  wgctl shell
  wgctl> list --blocked
  wgctl> inspect --name phone-nuno
  wgctl> rule list --tree
  wgctl> group block --name family
  wgctl> logs --follow
  wgctl> ls /etc/wireguard/.wgctl/rules/
  wgctl> exit
EOF
}

# ============================================
# Tab completion
# ============================================

function cmd::shell::_setup_completion() {
  local commands="list add remove rm inspect block unblock rule group audit \
logs watch fw config qr rename service shell help test \
peer hosts identity subnet policy activity"
 
  function _wgctl_shell_complete() {
    local cur="${COMP_WORDS[COMP_CWORD]}"
    COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
  }
 
  bind 'set show-all-if-ambiguous on' 2>/dev/null || true
  bind 'set completion-ignore-case on' 2>/dev/null || true
}

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

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

  while true; do
    local input
    IFS= read -r -e -p "$(cmd::shell::_prompt)" input || break

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

    history -s "$input"

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

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

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