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

# ubuntu-disk-monitor.sh
#
# Purpose:
#   Provide a practical, read-only disk usage triage script for Ubuntu hosts.
#   It checks filesystem usage, inode pressure, top-level directory growth,
#   and optionally deleted-but-open files that may be holding space.
#
# Safe defaults:
#   - No destructive actions
#   - Read-only inspection only
#   - Uses sudo only when needed and available
#
# Usage:
#   ./ubuntu-disk-monitor.sh [mount_path] [max_depth]
#
# Examples:
#   ./ubuntu-disk-monitor.sh
#   ./ubuntu-disk-monitor.sh /var 1
#   ./ubuntu-disk-monitor.sh / 2
#
# Notes:
#   - The script expects standard tools: df, du, sort, awk, sed, lsof
#   - lsof is optional; the script will skip that check if unavailable

MOUNT_PATH="${1:-/var}"
MAX_DEPTH="${2:-1}"

log() {
  printf '[%s] %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*"
}

warn() {
  printf '[%s] WARNING: %s\n' "$(date +'%Y-%m-%d %H:%M:%S')" "$*" >&2
}

require_cmd() {
  local cmd="$1"
  if ! command -v "$cmd" >/dev/null 2>&1; then
    warn "Required command not found: $cmd"
    return 1
  fi
}

have_sudo() {
  command -v sudo >/dev/null 2>&1 && sudo -n true >/dev/null 2>&1
}

run_maybe_sudo() {
  if [[ "$EUID" -eq 0 ]]; then
    "$@"
  elif have_sudo; then
    sudo "$@"
  else
    "$@"
  fi
}

validate_inputs() {
  if [[ ! "$MAX_DEPTH" =~ ^[0-9]+$ ]]; then
    warn "max_depth must be a non-negative integer"
    exit 1
  fi

  if [[ ! -e "$MOUNT_PATH" ]]; then
    warn "Path does not exist: $MOUNT_PATH"
    exit 1
  fi
}

show_filesystem_usage() {
  log "Filesystem usage for path: $MOUNT_PATH"
  df -hT "$MOUNT_PATH"
  echo
  log "Inode usage for path: $MOUNT_PATH"
  df -ih "$MOUNT_PATH"
  echo
}

show_directory_usage() {
  log "Top-level directory usage for: $MOUNT_PATH"
  if command -v sudo >/dev/null 2>&1; then
    sudo du -xh --max-depth="$MAX_DEPTH" "$MOUNT_PATH" 2>/dev/null | sort -h
  else
    du -xh --max-depth="$MAX_DEPTH" "$MOUNT_PATH" 2>/dev/null | sort -h
  fi
  echo
}

show_large_trees_hint() {
  cat <<'EOF'
Next steps:
  - If one directory dominates, run the script again against that directory.
  - Compare du totals with df output for the same filesystem.
  - Check /var/log, /var/lib, /tmp, and /var/tmp for common growth sources.
EOF
  echo
}

show_deleted_open_files() {
  if ! command -v lsof >/dev/null 2>&1; then
    warn "lsof not installed; skipping deleted-but-open file check"
    return 0
  fi

  log "Deleted-but-open files (may be holding disk space):"
  if run_maybe_sudo lsof +L1; then
    true
  else
    warn "lsof check did not complete successfully"
  fi
  echo
}

main() {
  validate_inputs

  require_cmd df
  require_cmd du
  require_cmd sort
  require_cmd awk

  show_filesystem_usage
  show_directory_usage
  show_deleted_open_files
  show_large_trees_hint

  log "Done. No changes were made."
}

main "$@"