#!/usr/bin/env bash
# install-stow.sh: Stow dotfile packages into $HOME with per-package prompts.
# Packages that are already fully stowed are skipped automatically.
# Run after install-deps.sh.

set -euo pipefail

DOTFILES_DIR="$(cd "$(dirname "$0")" && pwd)"

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

ok()     { echo "  ✓ $*"; }
info()   { echo "  → $*"; }
warn()   { echo "  ⚠ $*"; }
header() { echo ""; echo "==> $*"; }

# Ask yes/no. Returns 0 for yes, 1 for no.
ask_yn() {
  local prompt="$1"
  while true; do
    read -r -p "$prompt [y/N] " answer
    case "${answer,,}" in
      y|yes) return 0 ;;
      n|no|"") return 1 ;;
      *) echo "    Please answer y or n." ;;
    esac
  done
}

# ---------------------------------------------------------------------------
# Check if a package is already fully stowed
# (every file in the package has a correct symlink in $HOME)
# ---------------------------------------------------------------------------

is_stowed() {
  local pkg="$1"
  local pkg_dir="$DOTFILES_DIR/$pkg"
  local all_ok=true

  while IFS= read -r -d '' src; do
    local rel="${src#$pkg_dir/}"
    local target="$HOME/$rel"
    # Must exist as a symlink pointing at this exact source
    if [[ ! -L "$target" ]] || [[ "$(readlink -f "$target")" != "$(readlink -f "$src")" ]]; then
      all_ok=false
      break
    fi
  done < <(find "$pkg_dir" -type f -print0 2>/dev/null)

  $all_ok
}

# List any real files (non-symlinks) that would be overwritten by stowing
conflicts_for() {
  local pkg="$1"
  local pkg_dir="$DOTFILES_DIR/$pkg"
  local conflicts=()

  while IFS= read -r -d '' src; do
    local rel="${src#$pkg_dir/}"
    local target="$HOME/$rel"
    if [[ -e "$target" ]] && [[ ! -L "$target" ]]; then
      conflicts+=("$target")
    fi
  done < <(find "$pkg_dir" -type f -print0 2>/dev/null)

  printf '%s\n' "${conflicts[@]}"
}

# ---------------------------------------------------------------------------
# Collect packages (top-level dirs, skip hidden)
# ---------------------------------------------------------------------------

header "Stowing dotfile packages"

PACKAGES=()
for d in "$DOTFILES_DIR"/*/; do
  pkg="$(basename "$d")"
  [[ "$pkg" == .* ]] && continue
  PACKAGES+=("$pkg")
done

STOWED=()
SKIPPED=()

for pkg in "${PACKAGES[@]}"; do
  echo ""
  echo "Package: $pkg"

  if is_stowed "$pkg"; then
    ok "already stowed — skipping"
    STOWED+=("$pkg (already)")
    continue
  fi

  # Show conflicts, if any
  mapfile -t conflicts < <(conflicts_for "$pkg")
  if [[ ${#conflicts[@]} -gt 0 ]]; then
    warn "Stowing would overwrite these real files:"
    for f in "${conflicts[@]}"; do
      echo "      $f"
    done
    echo "    Back them up or delete them first, then re-run."
  fi

  if ask_yn "  Stow '$pkg'?"; then
    stow --dir="$DOTFILES_DIR" --target="$HOME" --restow "$pkg"
    ok "stowed"
    STOWED+=("$pkg")
  else
    info "skipped"
    SKIPPED+=("$pkg")
  fi
done

# ---------------------------------------------------------------------------
# Configure shell (after stowing zshrc)
# ---------------------------------------------------------------------------

header "Shell configuration"

if [[ ! -f "$HOME/.zshrc" ]]; then
  touch "$HOME/.zshrc"
fi

if ! grep -q 'eval "$(starship init zsh)"' "$HOME/.zshrc"; then
  echo 'eval "$(starship init zsh)"' >> "$HOME/.zshrc"
  ok "Added starship init to ~/.zshrc"
else
  ok "Starship already configured in ~/.zshrc"
fi

# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------

header "Summary"

if [[ ${#STOWED[@]} -gt 0 ]]; then
  echo "  Stowed:  ${STOWED[*]}"
fi
if [[ ${#SKIPPED[@]} -gt 0 ]]; then
  echo "  Skipped: ${SKIPPED[*]}"
fi

echo ""
echo "Done."
