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

ROOT="$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
ARCHIVE="${1:-${ROOT}/public/source/openq4-web-source.tar.xz}"
CHECKSUM="${ARCHIVE}.sha256"

EXPECTED_HASH_VARIABLES=(
    Q4_EXPECT_OPENQ4_DIFF_SHA256
    Q4_EXPECT_GAMELIBS_DIFF_SHA256
    Q4_EXPECT_PATCH_MANIFEST_SHA256
    Q4_EXPECT_RUNTIME_SOURCE_SHA256
    Q4_EXPECT_NATIVE_PATCH_MANIFEST_SHA256
    Q4_EXPECT_NATIVE_OPENQ4_DIFF_SHA256
    Q4_EXPECT_NATIVE_GAMELIBS_DIFF_SHA256
)
for variable in "${EXPECTED_HASH_VARIABLES[@]}"; do
    value="${!variable:-}"
    [[ "${value}" =~ ^[0-9a-f]{64}$ ]] || {
        echo "${variable} is required and must be a lowercase SHA-256 digest" >&2
        exit 64
    }
done

[[ -f "${ARCHIVE}" && -f "${CHECKSUM}" ]] || {
    echo "Source archive or checksum is missing: ${ARCHIVE}" >&2
    exit 1
}
(
    cd "$(dirname -- "${ARCHIVE}")"
    sha256sum -c "$(basename -- "${CHECKSUM}")"
)

WORK="$(mktemp -d)"
trap 'rm -rf -- "${WORK}"' EXIT
tar -xJf "${ARCHIVE}" -C "${WORK}"
SOURCE="${WORK}/q4-web-source"
if grep -REn '^diff --git a/content/baseoq4/pak[01]/' "${SOURCE}/port/native/patches"; then
    echo "Source offer contains a patch against a pruned runtime-pack file" >&2
    exit 1
fi
if grep -REn 'flame_gun_globsmall\.ase|globburn\.fx|flyburn\.fx' "${SOURCE}/port/native/patches"; then
    echo "Source offer contains removed upstream runtime declaration text" >&2
    exit 1
fi
TAMPER_TARGET="${SOURCE}/vendor/openq4/README.md"
cp -- "${TAMPER_TARGET}" "${WORK}/README.md.original"
printf '\nsource-offer tamper test\n' >>"${TAMPER_TARGET}"

set +e
tamper_output="$({
    cd "${SOURCE}"
    tools/build-wasm.sh --clean --verify-sources-only
} 2>&1)"
tamper_status=$?
set -e
if ((tamper_status == 0)); then
    echo "Tampered source snapshot unexpectedly passed verification" >&2
    exit 1
fi
grep -Fq 'OpenQ4 materialized snapshot tree mismatch' <<<"${tamper_output}" || {
    echo "Tampered source failed for the wrong reason:" >&2
    printf '%s\n' "${tamper_output}" >&2
    exit 1
}
echo "Tampered source snapshot rejected by its pinned Git tree"

cp -- "${WORK}/README.md.original" "${TAMPER_TARGET}"
verification_output="$({
    cd "${SOURCE}"
    tools/build-wasm.sh --clean --verify-sources-only
} 2>&1)"
printf '%s\n' "${verification_output}"

require_verification_hash() {
    local output_key="$1" expected_variable="$2" description="$3"
    local expected="${!expected_variable}"
    grep -Fqx "${output_key}=${expected}" <<<"${verification_output}" || {
        echo "${description} differs from the expected Git-checkout state" >&2
        exit 1
    }
}

require_verification_hash \
    openq4_patched_diff_sha256 Q4_EXPECT_OPENQ4_DIFF_SHA256 \
    "OpenQ4 patched source state"
require_verification_hash \
    gamelibs_patched_diff_sha256 Q4_EXPECT_GAMELIBS_DIFF_SHA256 \
    "OpenQ4-GameLibs patched source state"
require_verification_hash \
    patch_manifest_sha256 Q4_EXPECT_PATCH_MANIFEST_SHA256 \
    "Source patch manifest"
require_verification_hash \
    free_runtime_source_sha256 Q4_EXPECT_RUNTIME_SOURCE_SHA256 \
    "Free runtime source state"

native_verification_output="$({
    cd "${SOURCE}"
    python3 tools/native-source-identity.py --root .
} 2>&1)"
printf '%s\n' "${native_verification_output}"

require_native_verification_hash() {
    local output_key="$1" expected_variable="$2" description="$3"
    local expected="${!expected_variable}"
    grep -Fqx "${output_key}=${expected}" <<<"${native_verification_output}" || {
        echo "${description} differs from the expected Git-checkout state" >&2
        exit 1
    }
}

require_native_verification_hash \
    native_patch_manifest_sha256 Q4_EXPECT_NATIVE_PATCH_MANIFEST_SHA256 \
    "Native source patch manifest"
require_native_verification_hash \
    native_openq4_patched_diff_sha256 Q4_EXPECT_NATIVE_OPENQ4_DIFF_SHA256 \
    "Native OpenQ4 patched source state"
require_native_verification_hash \
    native_gamelibs_patched_diff_sha256 Q4_EXPECT_NATIVE_GAMELIBS_DIFF_SHA256 \
    "Native OpenQ4-GameLibs patched source state"

python3 - \
    "${SOURCE}/SOURCE_MANIFEST.json" \
    "${Q4_EXPECT_NATIVE_PATCH_MANIFEST_SHA256}" \
    "${Q4_EXPECT_NATIVE_OPENQ4_DIFF_SHA256}" \
    "${Q4_EXPECT_NATIVE_GAMELIBS_DIFF_SHA256}" <<'PY'
import json
import pathlib
import sys

manifest = json.loads(pathlib.Path(sys.argv[1]).read_text(encoding="utf-8"))
native = manifest.get("nativeSource")
if manifest.get("schema") != 2 or not isinstance(native, dict):
    raise SystemExit("source offer lacks its schema-2 native source identity")
expected = {
    "patchManifestSha256": sys.argv[2],
    "openq4PatchedDiffSha256": sys.argv[3],
    "gamelibsPatchedDiffSha256": sys.argv[4],
}
for key, value in expected.items():
    if native.get(key) != value:
        raise SystemExit(f"source offer native identity {key} mismatch")
if not any(entry.get("path", "").endswith("/0028-flush-dedicated-stdout.patch")
           for entry in native.get("patches", [])):
    raise SystemExit("source offer native identity omits stdout flush patch 0028")
PY

echo "Source-offer extraction, tamper rejection, and patch-chain verification passed"
