#!/usr/bin/env bash
# audit_packages.sh — Audit package managers on macOS
# Output: JSON lines to stdout, one per finding
set -euo pipefail

json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g; s/\t/\\t/g' | tr '\n' ' '; }

json_finding() {
  local severity="$1" finding action details
  finding=$(json_escape "$2")
  action=$(json_escape "$3")
  details=$(json_escape "$4")
  printf '{"module":"packages","severity":"%s","finding":"%s","action":"%s","details":"%s"}\n' \
    "$severity" "$finding" "$action" "$details"
}

# --- Homebrew ---
if command -v brew &>/dev/null; then
  echo '{"module":"packages","severity":"info","finding":"Homebrew detected","action":"none","details":"'$(brew --version | head -1)'"}'

  # brew update
  brew update --quiet 2>/dev/null || true

  # outdated formulae
  outdated=$(brew outdated --json=v2 2>/dev/null || echo '{}')
  formula_count=$(echo "$outdated" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('formulae',[])))" 2>/dev/null || echo 0)
  cask_count=$(echo "$outdated" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('casks',[])))" 2>/dev/null || echo 0)

  if [ "$formula_count" -gt 0 ] 2>/dev/null; then
    formula_list=$(echo "$outdated" | python3 -c "
import sys,json
d=json.load(sys.stdin)
names=[f['name'] for f in d.get('formulae',[])]
print(', '.join(names[:10]))
if len(names)>10: print(f'... and {len(names)-10} more')
" 2>/dev/null || echo "")
    json_finding "warning" "${formula_count} Homebrew formulae outdated" "brew upgrade" "$formula_list"
  fi

  if [ "$cask_count" -gt 0 ] 2>/dev/null; then
    json_finding "warning" "${cask_count} Homebrew casks outdated" "brew upgrade --cask" ""
  fi

  if [ "$formula_count" -eq 0 ] && [ "$cask_count" -eq 0 ] 2>/dev/null; then
    json_finding "info" "All Homebrew packages up to date" "none" ""
  fi

  # brew doctor
  doctor_output=$(brew doctor 2>&1 || true)
  doctor_warnings=$(echo "$doctor_output" | grep -c "Warning:" 2>/dev/null || echo 0)
  if [ "$doctor_warnings" -gt 0 ] 2>/dev/null; then
    json_finding "warning" "brew doctor found ${doctor_warnings} warning(s)" "brew doctor" "Run brew doctor for details"
  fi

  # autoremove candidates
  autoremove_output=$(brew autoremove --dry-run 2>/dev/null || echo "")
  orphan_count=$(echo "$autoremove_output" | grep -c "^=" 2>/dev/null || echo 0)
  if echo "$autoremove_output" | grep -q "would remove" 2>/dev/null; then
    json_finding "info" "Orphaned Homebrew dependencies found" "brew autoremove" "$autoremove_output"
  fi
else
  json_finding "info" "Homebrew not installed" "none" "Consider installing from https://brew.sh"
fi

# --- npm / nvm ---
if command -v nvm &>/dev/null || [ -d "$HOME/.nvm" ]; then
  # Source nvm if available
  export NVM_DIR="${NVM_DIR:-$HOME/.nvm}"
  [ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh" 2>/dev/null

  if command -v nvm &>/dev/null; then
    node_versions=$(nvm ls --no-colors 2>/dev/null | grep -c "v[0-9]" || echo 0)
    current_node=$(nvm current 2>/dev/null || echo "none")
    json_finding "info" "nvm detected: ${node_versions} version(s), current: ${current_node}" "none" ""
  fi
fi

if command -v npm &>/dev/null; then
  json_finding "info" "npm detected" "none" "$(npm --version 2>/dev/null)"

  npm_outdated=$(npm outdated -g --json 2>/dev/null || echo '{}')
  npm_outdated_count=$(echo "$npm_outdated" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null || echo 0)

  if [ "$npm_outdated_count" -gt 0 ] 2>/dev/null; then
    json_finding "warning" "${npm_outdated_count} global npm packages outdated" "npm update -g" ""
  fi
else
  json_finding "info" "npm not installed" "none" ""
fi

# --- Python / pyenv ---
if command -v pyenv &>/dev/null; then
  pyenv_versions=$(pyenv versions --bare 2>/dev/null | wc -l | tr -d ' ')
  current_python=$(pyenv version-name 2>/dev/null || echo "system")
  json_finding "info" "pyenv detected: ${pyenv_versions} version(s), current: ${current_python}" "none" ""

  # Check pip outdated for current environment
  if command -v pip &>/dev/null || command -v pip3 &>/dev/null; then
    pip_cmd=$(command -v pip3 || command -v pip)
    pip_outdated=$($pip_cmd list --outdated --format=json 2>/dev/null || echo '[]')
    pip_count=$(echo "$pip_outdated" | python3 -c "import sys,json; print(len(json.load(sys.stdin)))" 2>/dev/null || echo 0)

    if [ "$pip_count" -gt 0 ] 2>/dev/null; then
      json_finding "warning" "${pip_count} pip packages outdated in current env" "pip install --upgrade" ""
    fi
  fi
elif command -v python3 &>/dev/null; then
  py_version=$(python3 --version 2>/dev/null || echo "unknown")
  json_finding "info" "System Python: ${py_version} (no pyenv)" "none" ""
fi

# --- Other package managers (presence detection only) ---
for mgr in yarn pnpm cargo go gem composer; do
  if command -v "$mgr" &>/dev/null; then
    version=$($mgr --version 2>/dev/null | head -1 || echo "unknown")
    json_finding "info" "${mgr} detected: ${version}" "none" "Presence check only"
  fi
done
