# Low-battery notifications — the session-side complement to the bar's
# battery colors: Waybar paints the module @warn at 25% and @bad at 10%
# (waybar.nix battery.states) but nothing *notified*. This watcher polls
# the same sysfs state the bar reads and fires exactly one notification
# per downward crossing — normal at 25%, critical at 10% (swaync keeps
# critical toasts up until dismissed) — re-arming once the charger lands.
#
# notify-send is resolved from PATH on purpose (not a runtimeInput): the
# unit (battery-notify.nix) provides libnotify; the VM check shims it to
# capture the calls.
#
# usage: nomarchy-battery-notify [poll-interval-seconds]

interval="${1:-30}"
warn=25
crit=10

# System batteries only: type Battery, and not scope=Device (how
# peripheral batteries — mice, headsets — report). Name-agnostic on
# purpose: BAT0, dual-battery BAT0+BAT1, CMB0, test_battery all match.
batteries() {
  local d
  for d in /sys/class/power_supply/*/; do
    [ "$(cat "$d/type" 2>/dev/null)" = Battery ] || continue
    [ "$(cat "$d/scope" 2>/dev/null || echo System)" = Device ] && continue
    printf '%s\n' "$d"
  done
}

# Self-gate: no battery, not a laptop — a clean no-op on desktops.
[ -n "$(batteries)" ] || exit 0

state=ok # ok → warn → crit, one notification per downward crossing
while :; do
  sum=0 n=0 discharging=
  while IFS= read -r d; do
    cap=$(cat "$d/capacity" 2>/dev/null) || continue
    sum=$((sum + cap)); n=$((n + 1))
    [ "$(cat "$d/status" 2>/dev/null)" = Discharging ] && discharging=1
  done < <(batteries)

  if [ "$n" -gt 0 ] && [ -n "$discharging" ]; then
    cap=$((sum / n))
    if [ "$cap" -le "$crit" ] && [ "$state" != crit ]; then
      notify-send -u critical -a Nomarchy "Battery critical: ${cap}%" \
        "Plug in now."
      state=crit
    elif [ "$cap" -le "$warn" ] && [ "$state" = ok ]; then
      notify-send -u normal -a Nomarchy "Battery low: ${cap}%" \
        "Consider plugging in."
      state=warn
    fi
  else
    # On the charger (or nothing readable): re-arm for the next drain.
    state=ok
  fi
  sleep "$interval"
done
