#!/usr/bin/env bash

# Every directory under config/dot is claimed by exactly one of
# link-dotfiles' three lists -- universal (both roles), desktop, or handled
# (linked or consumed some other way in that script). The failure this
# prevents is quiet: a new dot directory added to the repo but classified
# nowhere links on no server, or on every server, depending on which list the
# author forgot -- and nothing says so until a machine is missing its config.
#
# The lists are lifted from the script itself rather than restated here, so
# renaming them fails loudly instead of freezing a stale copy.

set -uo pipefail

repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
link_dotfiles="$repo_dir/setup/scripts/link-dotfiles"
dot_dir="$repo_dir/config/dot"

findings=()
note() { findings+=("$1"); }

lists="$(sed -n '/^universal_dirs=(/,/^handled_dirs=(.*)$/p' "$link_dotfiles")"
if [[ -z "$lists" ]]; then
    printf 'dotfile classification contract: link-dotfiles no longer defines the three lists\n' >&2
    exit 1
fi
eval "$lists"

claimed=("${universal_dirs[@]}" "${desktop_dirs[@]}" "${handled_dirs[@]}")

for dir in "$dot_dir"/*/; do
    name="$(basename "$dir")"
    hits=0
    for entry in "${claimed[@]}"; do
        [[ "$entry" == "$name" ]] && hits=$((hits + 1))
    done
    if (( hits == 0 )); then
        note "config/dot/$name is claimed by no list, so servers silently skip or acquire it"
    elif (( hits > 1 )); then
        note "config/dot/$name is claimed by $hits lists"
    fi
done

for entry in "${claimed[@]}"; do
    [[ -d "$dot_dir/$entry" ]] \
        || note "link-dotfiles classifies '$entry', which config/dot does not contain"
done

if (( ${#findings[@]} > 0 )); then
    mapfile -t findings < <(printf '%s\n' "${findings[@]}" | sort -u)
    printf 'dotfile classification contract: %d finding(s)\n' "${#findings[@]}" >&2
    printf '  - %s\n' "${findings[@]}" >&2
    exit 1
fi

printf 'dotfile classification contract: PASS (%d directories classified)\n' "${#claimed[@]}"
