#!/usr/bin/env bash
# core/command_mixins.sh
# Mixin infrastructure — loads mixin files and provides command::mixin

# ============================================
# Active mixin tracking (per-process)
# ============================================

declare -a _ACTIVE_MIXINS=()

# ============================================
# Auto-load all mixin files
# ============================================

function command::_load_mixins() {
  local mixin_file
  local -a mixin_paths=(
    "${WGCTL_DIR}/core/mixins/"*.mixin.sh
    "${WGCTL_DIR}/commands/mixins/"*.mixin.sh
  )
  for mixin_file in "${mixin_paths[@]:-}"; do
    [[ -f "$mixin_file" ]] && source "$mixin_file"
  done
}

# ============================================
# command::mixin <name>
# Called from cmd::<name>::on_load to opt into a mixin
# ============================================

function command::mixin() {
  local name="${1:-}"
  [[ -z "$name" ]] && log::error "command::mixin: missing name" && return 1

  local register_fn="command::mixin::${name}::register"
  if declare -f "$register_fn" >/dev/null 2>&1; then
    # Track for reset/process — avoid duplicates
    local m already=false
    for m in "${_ACTIVE_MIXINS[@]:-}"; do
      [[ "$m" == "$name" ]] && already=true && break
    done
    $already || _ACTIVE_MIXINS+=("$name")
    "$register_fn"
  else
    log::error "Unknown mixin: ${name} (no command::mixin::${name}::register found)"
    return 1
  fi
}

# ============================================
# command::_reset_mixins
# Called by command::run before each invocation
# ============================================

function command::_reset_mixin_state() {
  # Reset values but keep _ACTIVE_MIXINS populated
  local m
  for m in "${_ACTIVE_MIXINS[@]:-}"; do
    local reset_fn="command::mixin::${m}::reset"
    declare -f "$reset_fn" >/dev/null 2>&1 && "$reset_fn"
  done
}

function command::_reset_mixins() {
  _ACTIVE_MIXINS=()
  local reset_fn mixin_file
  # Reset all known mixins regardless of active state
  for mixin_file in \
    "${WGCTL_DIR}/core/mixins/"*.mixin.sh \
    "${WGCTL_DIR}/commands/mixins/"*.mixin.sh; do
    [[ -f "$mixin_file" ]] || continue
    local mixin_name
    mixin_name=$(basename "$mixin_file" .mixin.sh)
    reset_fn="command::mixin::${mixin_name}::reset"
    declare -f "$reset_fn" >/dev/null 2>&1 && "$reset_fn"
  done
}

# ============================================
# command::_preprocess_flags <args_nameref>
# Called by command::run — strips mixin flags from args
# ============================================

function command::_preprocess_flags() {
  local -n _args_ref="$1"
  local -a _filtered=()

  if [[ ${#_args_ref[@]} -eq 0 ]]; then
    return 0  # nothing to process
  fi

  for _arg in "${_args_ref[@]}"; do
    local _consumed=false
    for _mixin in "${_ACTIVE_MIXINS[@]:-}"; do
      local _process_fn="command::mixin::${_mixin}::process"
      if declare -f "$_process_fn" >/dev/null 2>&1; then
        if "$_process_fn" "$_arg"; then
          _consumed=true
          break
        fi
      fi
    done
    $_consumed || _filtered+=("$_arg")
  done

  if [[ ${#_filtered[@]} -gt 0 ]]; then
    _args_ref=("${_filtered[@]}")
  else
    _args_ref=()
  fi
}