#!/bin/bash
set -u

cwd="$(pwd)"
max_jobs=4

usage() {
  cat <<EOF
Usage: $(basename "$0") [options]

Options:
  -h, --help               Show this help message
  -c, --concurrent <num>   Maximum parallel jobs (default: 4)

Description:
  Clean node_modules directories grouped by letter (a-z) in parallel.
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    -h|--help) usage; exit 0 ;;
    -c|--concurrent) max_jobs="$2"; shift 2 ;;
    *) shift ;;
  esac
done

# colors
GREEN='\033[0;32m'
RED='\033[0;31m'
GRAY='\033[0;90m'
BLUE='\033[0;34m'
NC='\033[0m'

timestamp() {
  date "+%Y-%m-%d %H:%M:%S"
}

relative_path() {
  local path="$1"

  path="${path#"$cwd"/}"

  [[ "$path" == "$cwd" ]] && path="."

  echo "$path"
}

log() {
  local level="$1"
  shift

  local color="$NC"

  case "$level" in
    OK) color="$GREEN" ;;
    FAIL) color="$RED" ;;
    SKIP) color="$GRAY" ;;
    INFO) color="$BLUE" ;;
  esac

  echo -e "[${GRAY}$(timestamp)${NC}] [${color}${level}${NC}] $*"
}

cleanup_letter() {
  local letter="$1"

  shopt -s nullglob

  local targets=(
    "${cwd}/node_modules/${letter}"*
    "${cwd}/node_modules/@types/${letter}"*
    "${cwd}/node_modules/@${letter}"*
  )

  local removed_any=0

  for path in "${targets[@]}"; do
    local rel
    rel="$(relative_path "$path")"

    if rm -rf "$path"; then
      log OK "$rel"
      removed_any=1
    else
      log FAIL "$rel"
    fi
  done

  if (( removed_any == 0 )); then
    log SKIP "'${letter}'"
  fi
}

export -f cleanup_letter
export -f log
export -f timestamp
export -f relative_path

export cwd
export GREEN RED GRAY BLUE NC

log INFO "Cleaning $(relative_path "${cwd}/node_modules")"

running=0

for letter in $(printf "%s\n" {a..z} | shuf); do
  cleanup_letter "$letter" &

  ((running++))

  if (( running >= max_jobs )); then
    wait -n
    ((running--))
  fi
done

wait

log INFO "Removing remaining node_modules"

final_target="${cwd}/node_modules"
final_rel="$(relative_path "$final_target")"

if rm -rf "$final_target"; then
  log OK "$final_rel"
else
  log FAIL "$final_rel"
fi

log INFO "Done"