#!/usr/bin/env bash
# deckctl units — link systemd user units owned by overdeck modules into
# ~/.config/systemd/user, so a fresh workstation reproduces them from the repo.
# Source of truth: modules/*/systemd/user/**  (and modules/*/*/systemd/user/**)
set -euo pipefail

UNITS_HOME="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"

units_die() { echo "deckctl: ERROR: units: $*" >&2; exit 1; }

units_sources() { # → absolute paths of every module systemd/user root
  local d
  for d in "$DECKCTL_ROOT"/modules/*/systemd/user "$DECKCTL_ROOT"/modules/*/*/systemd/user; do
    [[ -d "$d" ]] && printf '%s\n' "$d"
  done
}

units_walk() { # $1=root → "<relative path>\t<absolute source>" for every regular file
  local root="$1" f rel
  while IFS= read -r -d '' f; do
    rel="${f#"$root"/}"
    printf '%s\t%s\n' "$rel" "$f"
  done < <(find "$root" -type f -print0 | sort -z)
}

cmd_units() {
  local action="${1:-apply}" root rel src dst linked=0 skipped=0 drift=0
  case "$action" in apply|diff) ;; *) units_die "usage: deckctl units [apply|diff]" ;; esac

  mkdir -p "$UNITS_HOME"
  while IFS= read -r root; do
    while IFS=$'\t' read -r rel src; do
      dst="$UNITS_HOME/$rel"
      if [[ -L "$dst" && "$(readlink -f "$dst")" == "$(readlink -f "$src")" ]]; then
        skipped=$((skipped + 1))
        continue
      fi
      if [[ "$action" == diff ]]; then
        echo "units diff: $rel not linked to ${src#"$DECKCTL_ROOT"/}"
        drift=$((drift + 1))
        continue
      fi
      [[ -e "$dst" && ! -L "$dst" ]] && units_die "$dst exists and is not a symlink; move it aside first"
      mkdir -p "$(dirname "$dst")"
      ln -sfn "$src" "$dst"
      echo "units: linked $rel -> ${src#"$DECKCTL_ROOT"/}"
      linked=$((linked + 1))
    done < <(units_walk "$root")
  done < <(units_sources)

  if [[ "$action" == diff ]]; then
    ((drift == 0)) || units_die "$drift unit(s) not linked to the repo"
    echo "units: $skipped linked, no drift"
    return 0
  fi

  ((linked == 0)) || systemctl --user daemon-reload
  echo "units: linked=$linked already-linked=$skipped"
}
