#!/usr/bin/env bash
# shellcheck disable=SC2030,SC2031 # Provider arms isolate PATH/credentials in subshells.
# The commit whose CI was guarded must be the commit the provider atomically merges.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
WORK_DIR="${MOSAIC_TEST_WORK_DIR:-$PWD/.mosaic-test-work/pr-merge-head-pin}"
SHA=0123456789abcdef0123456789abcdef01234567

make_fixture() {
    local name="$1" remote="$2"
    local root="$WORK_DIR/$name"
    local tools="$root/tools/git"
    mkdir -p "$tools" "$root/repo"
    cp "$SCRIPT_DIR/pr-merge.sh" "$tools/pr-merge.sh"
    cp "$SCRIPT_DIR/detect-platform.sh" "$tools/detect-platform.sh"
    git -C "$root/repo" init -q
    git -C "$root/repo" remote add origin "$remote"
    local base_branch="${3:-main}"
    cat > "$tools/pr-metadata.sh" <<SH
#!/usr/bin/env bash
printf '%s\n' '{"baseRefName":"$base_branch","headRefName":"fix/pinned","headRefOid":"$SHA","headRepository":"contributor/widgets-fork"}'
SH
    cat > "$tools/ci-queue-wait.sh" <<'SH'
#!/usr/bin/env bash
exit 0
SH
    chmod +x "$tools"/*.sh
}

rm -rf "$WORK_DIR"
make_fixture gitea https://git.example.test/acme/widgets.git next
make_fixture github https://github.com/acme/widgets.git main

cat > "$WORK_DIR/gitea/curl" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
payload=""
out_file=""
while [[ $# -gt 0 ]]; do
    case "$1" in
        -d|--data|--data-binary)
            payload="$2"
            [[ "$payload" == @* ]] && payload=$(<"${payload#@}")
            shift 2
            ;;
        -o)
            out_file="$2"
            shift 2
            ;;
        -K|--config)
            [[ "$2" == "-" ]] && cat >/dev/null
            shift 2
            ;;
        -w|-X|-H)
            shift 2
            ;;
        *) shift ;;
    esac
done
printf '%s' "$payload" > "${MOSAIC_MERGE_PAYLOAD_LOG:?}"
[[ -n "$out_file" ]] && printf '{}' > "$out_file"
printf '200'
SH
chmod +x "$WORK_DIR/gitea/curl"

set +e
(
    cd "$WORK_DIR/gitea/repo"
    export PATH="$WORK_DIR/gitea:$PATH"
    export GITEA_TOKEN=stub-token
    export GITEA_URL=https://git.example.test
    export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json"
    export MOSAIC_MERGE_PAYLOAD_LOG="$WORK_DIR/gitea-payload.json"
    env -u MOSAIC_GIT_IDENTITY "$WORK_DIR/gitea/tools/git/pr-merge.sh" -n 123
) >"$WORK_DIR/gitea.out" 2>&1
gitea_rc=$?
set -e
if [[ "$gitea_rc" -ne 0 ]]; then
    echo "FAIL gitea-pin: merge fixture returned $gitea_rc" >&2
    cat "$WORK_DIR/gitea.out" >&2
    exit 1
fi
python3 - "$WORK_DIR/gitea-payload.json" "$SHA" <<'PY'
import json
import sys
payload = json.load(open(sys.argv[1], encoding="utf-8"))
assert set(payload) <= {"Do", "head_commit_id", "delete_branch_after_merge"}, payload
assert payload.get("Do") == "squash", payload
assert payload.get("head_commit_id") == sys.argv[2], payload
PY

# A merge-gate verdict is commit-bound. A stale expected head must fail before merge.
wrong_sha=ffffffffffffffffffffffffffffffffffffffff
rm -f "$WORK_DIR/gitea-payload-stale.json"
set +e
(
    cd "$WORK_DIR/gitea/repo"
    export PATH="$WORK_DIR/gitea:$PATH"
    export GITEA_TOKEN=stub-token
    export GITEA_URL=https://git.example.test
    export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json"
    export MOSAIC_MERGE_PAYLOAD_LOG="$WORK_DIR/gitea-payload-stale.json"
    env -u MOSAIC_GIT_IDENTITY "$WORK_DIR/gitea/tools/git/pr-merge.sh" -n 123 --expect-head "$wrong_sha"
) >"$WORK_DIR/gitea-stale.out" 2>&1
stale_rc=$?
set -e
if [[ "$stale_rc" -eq 0 ]] || [[ -e "$WORK_DIR/gitea-payload-stale.json" ]]; then
    echo "FAIL stale-verdict: moved head was not refused before provider merge" >&2
    exit 1
fi

# A merge-capable path cannot bypass the mandatory queue guard. The legacy
# --skip-queue-guard option must be rejected before any provider merge call.
cat > "$WORK_DIR/gitea/tools/git/ci-queue-wait.sh" <<'SH'
#!/usr/bin/env bash
exit 99
SH
chmod +x "$WORK_DIR/gitea/tools/git/ci-queue-wait.sh"
rm -f "$WORK_DIR/gitea-payload-bypass.json"
set +e
(
    cd "$WORK_DIR/gitea/repo"
    export PATH="$WORK_DIR/gitea:$PATH"
    export GITEA_TOKEN=stub-token
    export GITEA_URL=https://git.example.test
    export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json"
    export MOSAIC_MERGE_PAYLOAD_LOG="$WORK_DIR/gitea-payload-bypass.json"
    env -u MOSAIC_GIT_IDENTITY "$WORK_DIR/gitea/tools/git/pr-merge.sh" -n 123 --skip-queue-guard
) >"$WORK_DIR/gitea-bypass.out" 2>&1
bypass_rc=$?
set -e
if [[ "$bypass_rc" -eq 0 ]] || [[ -e "$WORK_DIR/gitea-payload-bypass.json" ]]; then
    echo "FAIL merge-bypass: --skip-queue-guard reached the provider merge path" >&2
    exit 1
fi

# Dry-run is the only path that may omit the guard because it exits before the
# provider merge dispatch. Prove the exit and absence of a merge payload.
rm -f "$WORK_DIR/gitea-payload-dry-run.json"
(
    cd "$WORK_DIR/gitea/repo"
    export PATH="$WORK_DIR/gitea:$PATH"
    export GITEA_TOKEN=stub-token
    export GITEA_URL=https://git.example.test
    export MOSAIC_CREDENTIALS_FILE="$WORK_DIR/no-credentials.json"
    export MOSAIC_MERGE_PAYLOAD_LOG="$WORK_DIR/gitea-payload-dry-run.json"
    env -u MOSAIC_GIT_IDENTITY "$WORK_DIR/gitea/tools/git/pr-merge.sh" -n 123 --dry-run
) >"$WORK_DIR/gitea-dry-run.out" 2>&1
if [[ -e "$WORK_DIR/gitea-payload-dry-run.json" ]]; then
    echo "FAIL dry-run: non-merging preflight reached the provider merge path" >&2
    exit 1
fi

cat > "$WORK_DIR/github/gh" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
printf '%s\n' "$*" > "${MOSAIC_GH_MERGE_LOG:?}"
SH
chmod +x "$WORK_DIR/github/gh"
(
    cd "$WORK_DIR/github/repo"
    export PATH="$WORK_DIR/github:$PATH"
    export MOSAIC_GH_MERGE_LOG="$WORK_DIR/github-call.log"
    "$WORK_DIR/github/tools/git/pr-merge.sh" -n 123
) >"$WORK_DIR/github.out" 2>&1
if ! grep -q -- "--match-head-commit $SHA" "$WORK_DIR/github-call.log"; then
    echo "FAIL github-pin: merge command omitted --match-head-commit $SHA" >&2
    cat "$WORK_DIR/github-call.log" >&2
    exit 1
fi

echo "PR merge exact-head pin regression passed (Gitea + GitHub)"
