#!/usr/bin/env bash
# audit_cleanup.sh — Scan caches, logs, and clutter on macOS, report sizes
# 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":"cleanup","severity":"%s","finding":"%s","action":"%s","details":"%s"}\n' \
    "$severity" "$finding" "$action" "$details"
}

# Get directory size in human-readable and bytes
dir_size() {
  local path="$1"
  if [ -d "$path" ]; then
    local bytes=$(du -sk "$path" 2>/dev/null | awk '{print $1}')
    local human=$(du -sh "$path" 2>/dev/null | awk '{print $1}')
    echo "${bytes:-0}|${human:-0B}"
  else
    echo "0|0B"
  fi
}

classify_size() {
  local kb="$1"
  if [ "$kb" -gt 1048576 ] 2>/dev/null; then  # > 1GB
    echo "warning"
  else
    echo "info"
  fi
}

total_reclaimable_kb=0

# --- User logs ---
result=$(dir_size "$HOME/Library/Logs")
IFS='|' read -r kb human <<< "$result"
total_reclaimable_kb=$((total_reclaimable_kb + kb))
severity=$(classify_size "$kb")
json_finding "$severity" "User logs: ${human}" "clean" "~/Library/Logs/ [safe, no sudo]"

# --- System logs ---
result=$(dir_size "/var/log" 2>/dev/null || echo "0|0B")
IFS='|' read -r kb human <<< "$result"
if [ "$kb" -gt 0 ] 2>/dev/null; then
  severity=$(classify_size "$kb")
  json_finding "$severity" "System logs: ${human}" "clean" "/var/log/ [moderate, requires sudo]"
fi

# --- User caches ---
result=$(dir_size "$HOME/Library/Caches")
IFS='|' read -r kb human <<< "$result"
total_reclaimable_kb=$((total_reclaimable_kb + kb))
severity=$(classify_size "$kb")
json_finding "$severity" "User caches: ${human}" "clean" "~/Library/Caches/ [safe, per-app]"

# --- Homebrew cache ---
if command -v brew &>/dev/null; then
  brew_cache=$(brew --cache 2>/dev/null || echo "")
  if [ -n "$brew_cache" ] && [ -d "$brew_cache" ]; then
    result=$(dir_size "$brew_cache")
    IFS='|' read -r kb human <<< "$result"
    total_reclaimable_kb=$((total_reclaimable_kb + kb))
    severity=$(classify_size "$kb")
    json_finding "$severity" "Homebrew cache: ${human}" "brew cleanup" "$brew_cache [safe]"
  fi
fi

# --- npm cache ---
npm_cache="$HOME/.npm/_cacache"
if [ -d "$npm_cache" ]; then
  result=$(dir_size "$npm_cache")
  IFS='|' read -r kb human <<< "$result"
  total_reclaimable_kb=$((total_reclaimable_kb + kb))
  severity=$(classify_size "$kb")
  json_finding "$severity" "npm cache: ${human}" "npm cache clean --force" "$npm_cache [safe]"
fi

# --- pip cache ---
pip_cache="$HOME/Library/Caches/pip"
if [ -d "$pip_cache" ]; then
  result=$(dir_size "$pip_cache")
  IFS='|' read -r kb human <<< "$result"
  total_reclaimable_kb=$((total_reclaimable_kb + kb))
  severity=$(classify_size "$kb")
  json_finding "$severity" "pip cache: ${human}" "pip cache purge" "$pip_cache [safe]"
fi

# --- Xcode derived data ---
xcode_derived="$HOME/Library/Developer/Xcode/DerivedData"
if [ -d "$xcode_derived" ]; then
  result=$(dir_size "$xcode_derived")
  IFS='|' read -r kb human <<< "$result"
  total_reclaimable_kb=$((total_reclaimable_kb + kb))
  severity=$(classify_size "$kb")
  json_finding "$severity" "Xcode DerivedData: ${human}" "clean" "$xcode_derived [safe]"
fi

# --- Xcode archives ---
xcode_archives="$HOME/Library/Developer/Xcode/Archives"
if [ -d "$xcode_archives" ]; then
  result=$(dir_size "$xcode_archives")
  IFS='|' read -r kb human <<< "$result"
  total_reclaimable_kb=$((total_reclaimable_kb + kb))
  severity=$(classify_size "$kb")
  json_finding "$severity" "Xcode Archives: ${human}" "clean" "$xcode_archives [moderate - check before deleting]"
fi

# --- iOS Device Support ---
ios_support="$HOME/Library/Developer/Xcode/iOS DeviceSupport"
if [ -d "$ios_support" ]; then
  result=$(dir_size "$ios_support")
  IFS='|' read -r kb human <<< "$result"
  total_reclaimable_kb=$((total_reclaimable_kb + kb))
  severity=$(classify_size "$kb")
  json_finding "$severity" "iOS DeviceSupport: ${human}" "clean" "$ios_support [safe]"
fi

# --- Docker ---
if command -v docker &>/dev/null; then
  docker_df=$(docker system df 2>/dev/null || echo "")
  if [ -n "$docker_df" ]; then
    reclaimable=$(echo "$docker_df" | grep -i "reclaimable" | head -1 || echo "")
    json_finding "info" "Docker space usage detected" "docker system prune" "Run docker system df for details [use docker system prune to clean]"
  fi
else
  # Skip silently if docker not installed
  true
fi

# --- Trash ---
trash_dir="$HOME/.Trash"
if [ -d "$trash_dir" ]; then
  result=$(dir_size "$trash_dir")
  IFS='|' read -r kb human <<< "$result"
  total_reclaimable_kb=$((total_reclaimable_kb + kb))
  if [ "$kb" -gt 0 ] 2>/dev/null; then
    severity=$(classify_size "$kb")
    json_finding "$severity" "Trash: ${human}" "empty trash" "$trash_dir [safe]"
  fi
fi

# --- Old downloads (report only) ---
if [ -d "$HOME/Downloads" ]; then
  old_files=$(find "$HOME/Downloads" -maxdepth 1 -mtime +90 -type f 2>/dev/null | wc -l | tr -d ' ')
  if [ "$old_files" -gt 0 ] 2>/dev/null; then
    old_size=$(find "$HOME/Downloads" -maxdepth 1 -mtime +90 -type f -exec du -ck {} + 2>/dev/null | tail -1 | awk '{print $1}')
    old_human=$(echo "$old_size" | awk '{printf "%.1fM", $1/1024}')
    json_finding "info" "${old_files} files in Downloads older than 90 days (${old_human})" "review" "Info only - review manually"
  fi
fi

# --- Total summary ---
total_human=$(echo "$total_reclaimable_kb" | awk '{if($1>1048576) printf "%.1fG",$1/1048576; else if($1>1024) printf "%.1fM",$1/1024; else printf "%dK",$1}')
json_finding "info" "Total scannable space: ${total_human}" "review" "Approx reclaimable across all categories"
