#!/usr/bin/env bash
set -Eeuo pipefail

ROOT="${1:-$(mktemp -d)}"
KEEP="${KEEP_FIXTURE:-false}"
LIB="/opt/router-ops/lib/machine-git-count-contract.sh"
FACTS="/opt/router-ops/bin/router-machine-git-facts"
GUARD="/opt/router-ops/bin/router-step-machine-git-guard"
cleanup() { [ "$KEEP" = true ] || rm -rf "$ROOT"; }
trap cleanup EXIT

mkdir -p "$ROOT/wt/root" "$ROOT/wt/etc" "$ROOT/wt/usr" "$ROOT/samples"
printf a > "$ROOT/wt/root/file-1"
printf b > "$ROOT/wt/root/file-2"
printf c > "$ROOT/wt/etc/file-3"
printf d > "$ROOT/wt/usr/file-4"
git init --bare -q "$ROOT/gitdir"
git --git-dir="$ROOT/gitdir" config core.bare false
git --git-dir="$ROOT/gitdir" config core.worktree "$ROOT/wt"
git --git-dir="$ROOT/gitdir" config user.name regression
git --git-dir="$ROOT/gitdir" config user.email regression@example.invalid
git --git-dir="$ROOT/gitdir" --work-tree="$ROOT/wt" add -A
git --git-dir="$ROOT/gitdir" --work-tree="$ROOT/wt" commit -qm fixture
HEAD="$(git --git-dir="$ROOT/gitdir" rev-parse HEAD)"

# This line intentionally reproduces the historical bug. LEGACY_FIXTURE_ONLY
LEGACY_COUNT="$(cd "$ROOT/wt/root" && git --git-dir="$ROOT/gitdir" ls-tree -r --name-only "$HEAD" | wc -l | tr -d ' ')"

# shellcheck source=/opt/router-ops/lib/machine-git-count-contract.sh
. "$LIB"
ROOT_COUNT="$(cd "$ROOT/wt" && router_machine_git_tree_file_count "$ROOT/gitdir" "$ROOT/wt" "$HEAD")"
SUBDIR_COUNT="$(cd "$ROOT/wt/root" && router_machine_git_tree_file_count "$ROOT/gitdir" "$ROOT/wt" "$HEAD")"
TMP_COUNT="$(cd /tmp && router_machine_git_tree_file_count "$ROOT/gitdir" "$ROOT/wt" "$HEAD")"
ARCHIVE_COUNT="$(router_machine_git_archive_file_count "$ROOT/gitdir" "$ROOT/wt" "$HEAD")"
[ "$LEGACY_COUNT" = 2 ]
[ "$ROOT_COUNT" = 4 ]
[ "$SUBDIR_COUNT" = 4 ]
[ "$TMP_COUNT" = 4 ]
[ "$ARCHIVE_COUNT" = 4 ]

cat > "$ROOT/samples/bad-step.sh" <<'BAD'
COUNT="$(git --git-dir="$GIT_DIR" ls-tree -r --name-only "$HEAD" | wc -l)"
BAD
cat > "$ROOT/samples/good-step.sh" <<'GOOD'
COUNT="$(git --git-dir="$GIT_DIR" --work-tree=/ ls-tree -r --full-tree --name-only "$HEAD" | wc -l)"
GOOD
cat > "$ROOT/samples/old-facts.json" <<'OLD'
{"machine_git":{"tracked_file_count":21,"changed_files":["root/a"]}}
OLD
cat > "$ROOT/samples/published-facts.json" <<'PUB'
{"file_count":4}
PUB
cat > "$ROOT/samples/corrected-facts.json" <<'NEW'
{"machine_git":{"git_tree_file_count":4,"published_archive_file_count":4,"changed_file_count":1,"changed_files":["root/a"]}}
NEW

set +e
"$GUARD" --step-code "$ROOT/samples/bad-step.sh" > "$ROOT/bad-code.log" 2>&1
BAD_RC=$?
"$GUARD" --facts-json "$ROOT/samples/old-facts.json" > "$ROOT/old-facts.log" 2>&1
OLD_RC=$?
set -e
[ "$BAD_RC" -ne 0 ]
[ "$OLD_RC" -ne 0 ]
"$GUARD" --step-code "$ROOT/samples/good-step.sh" > "$ROOT/good-code.log"
"$GUARD" --facts-json "$ROOT/samples/corrected-facts.json" --published-facts-json "$ROOT/samples/published-facts.json" > "$ROOT/corrected-facts.log"
"$FACTS" --git-dir "$ROOT/gitdir" --work-tree "$ROOT/wt" --commit "$HEAD" --json > "$ROOT/facts.json"

printf 'LEGACY_FIXTURE_COUNT=%s\n' "$LEGACY_COUNT"
printf 'CANONICAL_ROOT_COUNT=%s\n' "$ROOT_COUNT"
printf 'CANONICAL_SUBDIR_COUNT=%s\n' "$SUBDIR_COUNT"
printf 'CANONICAL_TMP_COUNT=%s\n' "$TMP_COUNT"
printf 'ARCHIVE_FIXTURE_COUNT=%s\n' "$ARCHIVE_COUNT"
printf 'BAD_CODE_REJECTED=true\n'
printf 'GOOD_CODE_ACCEPTED=true\n'
printf 'OLD_FACTS_REJECTED=true\n'
printf 'CORRECTED_FACTS_ACCEPTED=true\n'
printf 'CWD_INDEPENDENCE=true\n'
printf 'REGRESSION_PASS=true\n'
