#!/bin/bash
## Fail-closed behavior: every tampered or conflicting input is refused,
## loudly, and for its own specific reason (we check the message, not just
## the exit code, so each case stays tied to the guard it exercises).
set -euo pipefail
cd "$(dirname "$0")"
source ./lib.sh

work=$(mktemp -d)
trap 'rm -rf "$work"' EXIT

make_corpus "$work/corpus"
source "$work/corpus/FACTS"

"$PATCHETTE" export "$work/corpus/dev" "$work/pristine" "$base" topic/fancy docs-polish >/dev/null
fancy=$'topic\u00a6fancy'

## Set up a fresh tampering workspace from the pristine export.
##
## - @param $1 case name; becomes the folder name under $work
## - @state TAMPER -- path to the fresh copy
clone_layout() {
	TAMPER="$work/$1"
	cp -r "$work/pristine" "$TAMPER"
}

# A tampered patch must make verify fail.  Editing message content keeps the
# diff applying cleanly, so the only witness left is the tip comparison --
# exactly the guard this case is about.
clone_layout tampered
sed -i 's/> The hum is load-bearing./> The hum is decorative./' "$TAMPER/$fancy/teach-gizmo-to-hum.patch"
EXPECT refusal "verify fails on a tampered patch" "MISMATCH" -- \
	"$PATCHETTE" verify "$work/corpus/dev" "$TAMPER"

# Import onto an existing branch is refused (before any replay work).
git clone -q "$work/corpus/upstream" "$work/occupied"
git -C "$work/occupied" branch docs-polish main
EXPECT refusal "import onto an existing branch is refused" "already exists" -- \
	"$PATCHETTE" import "$work/occupied" "$work/pristine"

# A malformed message line is a parse error, never a guess.
clone_layout badmsg
sed -i 's/> Do not ask why./| Do not ask why./' "$TAMPER/$fancy/teach-gizmo-to-hum.patch"
EXPECT refusal "a malformed message line is a parse error" "malformed message line" -- \
	"$PATCHETTE" verify "$work/corpus/dev" "$TAMPER"

# An unknown parent reference is an error.
clone_layout badparent
sed -i '1s/.*/parents no-such-slug/' "$TAMPER/$fancy/add-sprocket-docs.patch"
EXPECT refusal "an unknown parent reference is an error" "not BASE or an earlier slug" -- \
	"$PATCHETTE" verify "$work/corpus/dev" "$TAMPER"

# A duplicate series entry is an error.
clone_layout dupseries
echo "note-to-self" >>"$TAMPER/$fancy/STACK"
EXPECT refusal "a duplicate series entry is an error" "duplicate series entry" -- \
	"$PATCHETTE" verify "$work/corpus/dev" "$TAMPER"

# An orphan patch file (nothing would ever read it) is flagged by verify.
clone_layout orphan
cp "$TAMPER/$fancy/note-to-self.patch" "$TAMPER/$fancy/stray.patch"
EXPECT refusal "an orphan patch file is flagged by verify" "orphan" -- \
	"$PATCHETTE" verify "$work/corpus/dev" "$TAMPER"

# Export never deletes a folder it didn't write.
mkdir -p "$work/notours/$fancy"
touch "$work/notours/$fancy/precious.txt"
EXPECT refusal "export into a non-patchette folder is refused" "no STACK file" -- \
	"$PATCHETTE" export "$work/corpus/dev" "$work/notours" "$base" topic/fancy
EXPECT success "export left the non-patchette folder untouched" -- \
	test -f "$work/notours/$fancy/precious.txt"

# Importing where the recorded base is absent tells the user what to do.
git init -q -b main "$work/empty"
EXPECT refusal "import without the recorded base points at fetching" "fetch from upstream first" -- \
	"$PATCHETTE" import "$work/empty" "$work/pristine"

exit "$RESULT"
