#!/bin/bash
set -u

TRUST_DEPTH=5
TRUST_REF="refs/remotes/origin/master"
GATE_PRECOMMIT_SRC=".dev-config/hooks/pre-commit"
GATE_REFERENCE_SRC=".dev-config/hooks/reference-transaction"
GATE_HELPER_SRC=".dev-config/bin/ipz-remote-php-gate"

# Print the blob OIDs of $1 across the last TRUST_DEPTH landed versions on TRUST_REF.
trusted_blobs_for_path() {
    local path=$1 commit blob
    git rev-list -n "$TRUST_DEPTH" "$TRUST_REF" -- "$path" 2>/dev/null |
    while read -r commit; do
        blob=$(git rev-parse -q --verify "$commit:$path" 2>/dev/null) || continue
        printf '%s\n' "$blob"
    done
}

# Installed file $1 must byte-match some landed version of source path $2.
installed_blob_is_trusted() {
    local active=$1 tracked=$2 active_oid blob matched=1
    active_oid=$(git hash-object --no-filters "$active" 2>/dev/null) || return 1
    while read -r blob; do
        [ -n "$blob" ] && [ "$active_oid" = "$blob" ] && matched=0
    done < <(trusted_blobs_for_path "$tracked")
    return "$matched"
}

fail() {
    printf 'approve-gate-change: %s\n' "$*" >&2
    exit 1
}

force=0
for arg in "$@"; do
    case "$arg" in
        --force) force=1 ;;
        --help|-h)
            printf 'Usage: %s [--force]\n' "$0"
            exit 0
            ;;
        *) fail "unknown option: $arg" ;;
    esac
done

if [ "$force" -ne 1 ] && [ ! -t 0 ]; then
    fail 'this is an owner-only action; rerun from a terminal or pass --force'
fi

if git diff --cached --quiet; then
    fail 'no staged changes to approve'
fi

tree=$(git write-tree 2>/dev/null) || fail 'unable to write the staged tree'
common_dir=$(git rev-parse --git-common-dir 2>/dev/null) || fail 'unable to determine the shared Git directory'
common=$(realpath "$common_dir" 2>/dev/null) || fail 'unable to resolve the shared Git directory'
token="$common/ipz-gate-owner-token"

rm -f "$token" || fail 'unable to replace the existing owner token'
(
    umask 077
    printf 'approve-gate-change %s\n' "$tree" > "$token"
) || fail 'unable to write the owner token'
chmod 400 "$token" || fail 'unable to secure the owner token'

printf 'Approved staged tree: %s\n' "$tree"
printf 'The owner token is single-use and will be consumed by the next successful pre-commit run.\n'
