#!/usr/bin/env bash
# test.command.sh — wgctl test suite dispatcher
# Delegates to commands/test/{integration,unit,destructive,fn}.sh

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

function cmd::test::on_load() {
  flag::register --destructive
  flag::register --section
  flag::register --fn
  flag::register --function
  flag::register --unit
  flag::register --integration
  flag::register --verbose
}

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

function cmd::test::help() {
  cat <<EOF
Usage: wgctl test [options]

Run the wgctl test suite.

Options:
  --unit                    Run unit tests (pure function tests, no side effects)
  --integration             Run integration tests against the live binary (default)
  --destructive             Include destructive tests (add/remove/block state changes)
  --section <name>          Run only a specific section
  --fn <function>           Run a specific function test block
  --verbose                 Show command output on failure

Integration sections:
  list, inspect, config, rules, groups, audit, logs, fw, net, subnet, identity

Unit sections:
  subnet, identity, ip

Examples:
  wgctl test
  wgctl test --unit
  wgctl test --unit --section subnet
  wgctl test --integration --section rules
  wgctl test --destructive
  wgctl test --fn cmd::block::run
EOF
}

# ============================================
# Loader
# ============================================

function cmd::test::_load() {
  local name="${1:-}"
  local path
  path="$(ctx::commands)/test/${name}.sh"
  if [[ ! -f "$path" ]]; then
    log::error "Test file not found: ${path}"
    return 1
  fi
  source "$path"
}

# ============================================
# Run (entrypoint)
# ============================================

function cmd::test::run() {
  local unit=false integration=false destructive=false
  local section="" fn=""

  while [[ $# -gt 0 ]]; do
    case "$1" in
      --unit)          unit=true;               shift   ;;
      --integration)   integration=true;        shift   ;;
      --destructive)   destructive=true;        shift   ;;
      --section)       section="$2";            shift 2 ;;
      --fn|--function) fn="$2";                 shift 2 ;;
      --verbose|-v)    WGCTL_TEST_VERBOSE=true; shift   ;;
      --help)          cmd::test::help;         return  ;;
      *)
        log::error "Unknown flag: $1"
        return 1
        ;;
    esac
  done

  # Function test — load fn.sh + integration.sh (needs run_cmd helpers)
  if [[ -n "$fn" ]]; then
    cmd::test::_load integration || return 1
    cmd::test::_load fn          || return 1
    test::reset
    log::section "Function Test: ${fn}"
    cmd::test::_dispatch_fn "$fn"
    test::summary
    return
  fi

  # Unit tests
  if $unit; then
    cmd::test::_load unit || return 1
    test::reset
    log::section "wgctl Unit Tests"
    cmd::test::_dispatch_unit "$section"
    test::summary
    return
  fi

  # Integration tests (default, also when --integration is explicit)
  cmd::test::_load integration || return 1
  cmd::test::_load destructive || return 1
  test::reset
  log::section "wgctl Test Suite"
  cmd::test::_dispatch_integration "$section"
  $destructive && cmd::test::section_destructive
  test::summary
}

# ============================================
# Dispatch Helpers
# ============================================

function cmd::test::_dispatch_unit() {
  local section="${1:-}"
  if [[ -n "$section" ]]; then
    local fn="cmd::test::unit_${section}"
    if ! declare -f "$fn" > /dev/null 2>&1; then
      log::error "No unit section: ${section}"
      return 1
    fi
    "$fn"
  else
    cmd::test::run_all_unit_sections
  fi
}

function cmd::test::_dispatch_integration() {
  local section="${1:-}"
  if [[ -n "$section" ]]; then
    if [[ "$section" == "destructive" ]]; then
      cmd::test::section_destructive
      return
    fi
    local fn="cmd::test::section_${section}"
    if ! declare -f "$fn" > /dev/null 2>&1; then
      log::error "No integration section: ${section}"
      return 1
    fi
    "$fn"
  else
    cmd::test::run_all_integration_sections
  fi
}

function cmd::test::_dispatch_fn() {
  local fn="${1:-}"
  local namespace
  namespace=$(echo "$fn" | cut -d':' -f3)
  load_command "$namespace" 2>/dev/null || true
  cmd::test::run_function "$fn"
}