#!/usr/bin/env bash
# One-shot, host-aware dotfile linker for Linux & macOS.
#
#   home_root/*    ->  ~/<name>           (e.g. ~/.zshrc)       via `stow home_root`
#   home_config/*  ->  ~/.config/<name>   (e.g. ~/.config/nvim) via `stow home_config`
#
# Ensures GNU stow is present first (Homebrew on macOS; apt/dnf/pacman on Linux),
# so a fresh box needs nothing pre-installed. Re-running is safe — stow is
# idempotent and refuses to clobber unrelated real files.
#
# Windows / PowerShell: run ./link-dotfiles.ps1 instead (stow has no native
# Windows port; the .ps1 mirrors this with junctions + symlinks).
#
# `--check`: report drift and change nothing. Two kinds are caught. (1) A tracked
# file whose live copy is no longer a link into this repo: stow would refuse to
# stow over it, so the repo copy has silently gone stale. `sed -i` and any other
# write-temp-then-rename editor does this, and so can an app that rewrites its
# own config atomically. (2) A link into this repo whose target has been removed.
# Exits 1 on drift.
set -euo pipefail

repo="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$repo"

if [ "${1:-}" = "--check" ]; then
  command -v stow >/dev/null 2>&1 || { echo "error: GNU stow not installed; run ./link-dotfiles once first." >&2; exit 2; }
  drift=0
  for spec in "home_root:$HOME" "home_config:$HOME/.config"; do
    pkg="${spec%%:*}"; target="${spec#*:}"
    out="$(stow -n -v --target="$target" "$pkg" 2>&1 | grep -v 'simulation mode' || true)"
    if [ -n "$out" ]; then
      drift=1
      echo "✗ $pkg -> $target is not fully linked:"
      printf '%s\n' "$out" | sed 's/^/    /'
    fi
  done
  dangling="$(find "$HOME" "$HOME/.config" "$HOME/.claude" "$HOME/.claude/bin" "$HOME/.claude/skills" "$HOME/.local/bin" \
    -maxdepth 1 -xtype l -lname "*dotfiles/*" 2>/dev/null || true)"
  if [ -n "$dangling" ]; then
    drift=1
    echo "✗ links into dotfiles whose target is gone:"
    printf '%s\n' "$dangling" | sed 's/^/    /'
  fi
  [ "$drift" -eq 0 ] && echo "✓ no drift: every tracked file is linked, and no dotfiles link dangles."
  exit "$drift"
fi

# `--apps`: install all host CLI tools first, then link. Without it, this only
# links (fast + idempotent). App install is delegated to the host-aware
# lk-installers/install-apps.
if [ "${1:-}" = "--apps" ]; then
  echo "Installing apps first (--apps)…"
  "$repo/lk-installers/install-apps"
fi

ensure_stow() {
  command -v stow >/dev/null 2>&1 && return

  echo "GNU stow not found — installing it…"
  case "$(uname -s)" in
    Darwin)
      if ! command -v brew >/dev/null 2>&1; then
        echo "error: Homebrew is required on macOS. Run ./lk-installers/install-apps (or ./link-dotfiles --apps) first." >&2
        exit 1
      fi
      brew install stow
      ;;
    Linux)
      if   command -v apt    >/dev/null 2>&1; then sudo apt update && sudo apt install -y stow
      elif command -v dnf    >/dev/null 2>&1; then sudo dnf install -y stow
      elif command -v pacman >/dev/null 2>&1; then sudo pacman -S --noconfirm stow
      else
        echo "error: no supported package manager (apt/dnf/pacman). Install GNU stow manually." >&2
        exit 1
      fi
      ;;
    *)
      echo "error: unsupported OS '$(uname -s)'. On Windows run ./link-dotfiles.ps1 instead." >&2
      exit 1
      ;;
  esac
}

ensure_stow

echo "Linking home_root  -> ~"
stow -v home_root
echo "Linking home_config -> ~/.config"
stow -v --target="$HOME/.config" home_config

echo "Done."
