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

usage() {
  cat <<'EOF'
Usage:
  cleanup-node-releases --domain DOMAIN [--keep N] [--prune] [--verbose]
  cleanup-node-releases --help

Default mode is dry-run: it only prints which releases would be removed.
Use --prune to actually delete old releases.
EOF
}

domain=""
keep=5
prune=0
verbose=0

while [[ $# -gt 0 ]]; do
  case "$1" in
    --domain) domain="${2:-}"; shift 2 ;;
    --keep) keep="${2:-}"; shift 2 ;;
    --prune) prune=1; shift ;;
    --verbose) verbose=1; shift ;;
    --help|-h) usage; exit 0 ;;
    *) echo "Unknown argument: $1" >&2; usage; exit 2 ;;
  esac
done

[[ -n "$domain" ]] || { usage; exit 2; }
[[ "$keep" =~ ^[0-9]+$ ]] || { echo '--keep must be an integer' >&2; exit 2; }
(( keep >= 1 )) || { echo '--keep must be >= 1' >&2; exit 2; }
[[ $(id -u) -eq 0 ]] || { echo 'Run as root' >&2; exit 1; }

env_file="/etc/node-sites/$domain.env"
[[ -f "$env_file" ]] || { echo "Node site env not found: $env_file" >&2; exit 1; }
# shellcheck disable=SC1090
source "$env_file"

: "${SITE_ROOT:?SITE_ROOT is required}"
releases_dir="$SITE_ROOT/releases"
current_link="$SITE_ROOT/current"
[[ -d "$releases_dir" ]] || { echo "Releases dir not found: $releases_dir" >&2; exit 1; }
[[ -L "$current_link" ]] || { echo "Current symlink missing: $current_link" >&2; exit 1; }

current_target="$(readlink -f "$current_link")"
mapfile -t releases < <(find "$releases_dir" -mindepth 1 -maxdepth 1 -type d | sort)
total=${#releases[@]}

if (( total <= keep )); then
  echo "No cleanup needed for $domain"
  echo "Current -> $current_target"
  echo "Total releases: $total (keep=$keep)"
  exit 0
fi

keep_set=()
start=$(( total - keep ))
for (( i=start; i<total; i++ )); do
  keep_set+=("$(readlink -f "${releases[$i]}")")
done

remove_list=()
for rel in "${releases[@]}"; do
  rel_real="$(readlink -f "$rel")"
  if [[ "$rel_real" == "$current_target" ]]; then
    continue
  fi
  keep_it=0
  for k in "${keep_set[@]}"; do
    if [[ "$rel_real" == "$k" ]]; then
      keep_it=1
      break
    fi
  done
  if (( keep_it == 0 )); then
    remove_list+=("$rel_real")
  fi
done

echo "Domain: $domain"
echo "Current -> $current_target"
echo "Total releases: $total"
echo "Keep newest: $keep"
if (( ${#remove_list[@]} == 0 )); then
  echo "No removable releases found"
  exit 0
fi

echo "Releases to remove:"
for rel in "${remove_list[@]}"; do
  echo "- $rel"
done

if (( verbose == 1 )); then
  echo "Kept releases:"
  for rel in "${releases[@]}"; do
    rel_real="$(readlink -f "$rel")"
    skip=0
    for doomed in "${remove_list[@]}"; do
      if [[ "$rel_real" == "$doomed" ]]; then
        skip=1
        break
      fi
    done
    if (( skip == 0 )); then
      echo "+ $rel_real"
    fi
  done
fi

if (( prune == 0 )); then
  echo "Dry-run only. Re-run with --prune to delete these releases."
  exit 0
fi

for rel in "${remove_list[@]}"; do
  rm -rf -- "$rel"
done

echo "Removed ${#remove_list[@]} old releases for $domain"
restorecon -RF "$SITE_ROOT" >/dev/null 2>&1 || true
