#!/usr/bin/env bash
set -Eeuo pipefail

source "$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)/core.sh"

LOG_LEVEL=DEBUG

# ============================================
# Modules
# ============================================

load_module log
load_module config
load_module ip
load_module keys
load_module peers
load_module firewall
load_module monitor

# ============================================
# Alias Map
# ============================================

declare -A CMD_ALIASES=(
  # Client
  [new]=add
  [create]=add
  [rm]=remove
  [del]=remove
  [delete]=remove
  [mv]=rename
  [ls]=list
  [show]=list
  [monitor]=watch
  [ban]=block

  # Service
  [up]=service
  [down]=service
  [reload]=service
  [stat]=service
  [log]=service
  [start]=service
  [stop]=service
  [restart]=service
  [status]=service
  [logs]=service
  [enable]=service
  [disable]=service
)

# ============================================
# Dispatch
# ============================================

function wgctl::resolve_alias() {
  local cmd="$1"
  echo "${CMD_ALIASES[$cmd]:-$cmd}"
}

function wgctl::dispatch() {
  local raw_cmd="${1:-help}"
  shift || true

  local cmd
  cmd="$(wgctl::resolve_alias "$raw_cmd")"

  case "$cmd" in
    help) wgctl::help; return ;;
  esac

  # If alias resolved to service, pass original cmd as subcommand
  if [[ "$cmd" == "service" ]]; then
    load_command service
    command::run service "$raw_cmd" "$@"
    return
  fi

  if load_command "$cmd"; then
    if command::exists "$cmd"; then
      command::run "$cmd" "$@"
    else
      log::error "Command '${cmd}' loaded but $(command::fn "$cmd" run) is not defined"
      exit 1
    fi
  else
    log::error "Unknown command: '${raw_cmd}'"
    echo "Run 'wgctl help' to see available commands."
    exit 1
  fi
}

# ============================================
# Help
# ============================================

function wgctl::help() {
  cat <<EOF

$(log::section "wgctl — WireGuard Management")

Usage: wgctl <command> [options]

Client Commands:
  add, new, create      Add a new client
  remove, rm, del       Remove a client
  list, ls, show        List all clients
  qr                    Show QR code for a client
  block, ban            Block a client or add restrictions
  unblock, unban        Restore client access

Service Commands:
  start, up             Start WireGuard
  stop, down            Stop WireGuard
  restart, reload       Restart WireGuard
  status, stat          Show WireGuard status
  logs, log             Show WireGuard logs
  enable                Enable WireGuard on boot
  disable               Disable WireGuard on boot

Preset Commands:
  preset list           List available presets
  preset add            Add a new preset
  preset remove         Remove a preset

Run 'wgctl <command> --help' for command-specific help.
EOF
}

# ============================================
# Main
# ============================================

function wgctl::main() {
  system::require_root
  wgctl::dispatch "$@"
}

wgctl::main "$@"
