#!/bin/bash
# test/probe_stow.sh
#
# Verifies that each package the Makefile stows actually resolves and that
# stow can create all symlinks into the target without conflicts.
#
# This is a DRY RUN: it uses `stow --simulate` and creates no real symlinks.
# It catches bugs like `stow nvim` for a non-existent `nvim/` package.
#
# Usage:
#   bash test/probe_stow.sh            # probe every stow-able package
#   bash test/probe_stow.sh <pkg>...   # probe specific packages

set -uo pipefail

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO_ROOT" || exit 1

# A stow-able package is any tracked top-level directory that contains a
# dot-prefixed config subtree (or a dot-prefixed top-level file/dir).
tracked_basenames() {
    git ls-files | awk -F/ 'NF>1 {print $1}' | sort -u
}

is_stowable() {
    local pkg="$1"
    [[ -d "$REPO_ROOT/$pkg" ]] || return 1
    # stow needs at least one dot-prefixed entry at the package root
    git ls-files "$pkg/" | grep -qE "^$pkg/\." || return 1
}

# Determine which packages to probe.
PACKAGES=()
if [[ $# -eq 0 ]]; then
    while IFS= read -r b; do
        [[ -z "$b" ]] && continue
        is_stowable "$b" && PACKAGES+=("$b")
    done < <(tracked_basenames)
else
    PACKAGES=("$@")
fi

if [[ ${#PACKAGES[@]} -eq 0 ]]; then
    echo "probe_stow.sh: no stow-able packages found" >&2
    exit 1
fi

echo "== Probing stow packages: ${PACKAGES[*]} =="

FAIL=0
ERR_LOG="$(mktemp -t probe_stow.XXXXXX)"

cleanup() { rm -f "$ERR_LOG"; }
trap cleanup EXIT

for pkg in "${PACKAGES[@]}"; do
    echo "--- stow --simulate: $pkg ---"
    if stow --simulate --verbose=1 --dir="$REPO_ROOT" --target="$REPO_ROOT" "$pkg" >/dev/null 2>"$ERR_LOG"; then
        echo "ok: stow --simulate '$pkg' resolved without conflicts"
    else
        echo "FAIL: stow --simulate '$pkg'"
        sed 's/^/    /' "$ERR_LOG"
        FAIL=$((FAIL+1))
    fi
done

# Cross-check: does the Makefile stow anything that is NOT in our package set?
echo "== Checking Makefile stow targets against stow-able packages =="
make_pkgs="$(grep -P '^\t' Makefile | grep -oE 'stow [A-Za-z0-9_-]+' | awk '{print $2}' | sort -u)"
for mp in $make_pkgs; do
    if is_stowable "$mp"; then
        echo "ok: Makefile 'stow $mp' matches a stow-able package"
    else
        echo "FAIL: Makefile 'stow $mp' does not match a stow-able package"
        FAIL=$((FAIL+1))
    fi
done

echo
echo "=============================================="
echo "probe_stow.sh: $(( ${#PACKAGES[@]} + $(printf '%s\n' $make_pkgs | grep -c . || true) )) checks, $FAIL failed"
echo "=============================================="
[[ $FAIL -eq 0 ]]
