#!/usr/bin/env bash
# VWCG-1357: exact-hash, single-file patch. No SQL, frontend build or service restart.
set -euo pipefail
umask 077
root=/workspace/wwwroot/zhct_jsr/project
target="$root/application/p/logic/MealOrder.php"
old_hash=d4805ec00a7cea47131a06d6e2a1d3258bd6b28f15938e65ebb8952fd16899e1
new_hash=089df04e521f98aca802ade3bc51e9c9ab13857894a9c7558a9b73723a5a11fd
backup_dir=/workspace/wwwroot/zhct_jsr/hotfix-backups/VWCG-1357-receipt-date
backup="$backup_dir/MealOrder.php.before"
php=/usr/local/php7.3/bin/php
staged=''
changed=0
success=0
hash_file() { sha256sum "$1" | awk '{print $1}'; }
cleanup() {
    status=$?
    trap - EXIT
    if [[ "$changed" == 1 && "$success" == 0 ]]; then
        if [[ "$(hash_file "$target")" == "$new_hash" && "$(hash_file "$backup")" == "$old_hash" ]]; then
            rollback=$(mktemp "$root/application/p/logic/.MealOrder.php.VWCG-1357-rollback.XXXXXX")
            cp -p "$backup" "$rollback"
            "$php" -l "$rollback" >/dev/null
            mv -f "$rollback" "$target"
            [[ "$(hash_file "$target")" == "$old_hash" ]] || exit 92
            printf 'ROLLBACK_RESTORED %s\n' "$old_hash"
        else
            printf 'ROLLBACK_STOPPED unexpected live or backup hash\n' >&2
            exit 93
        fi
    fi
    [[ -z "$staged" || ! -e "$staged" ]] || rm -f "$staged"
    exit "$status"
}
trap cleanup EXIT
case "$(hostname)" in
    iZ2zeawufz0876gxr3k5fwZ|iZ2ze12juwl7c3y6h920e8Z) ;;
    *) printf 'Unexpected host\n' >&2; exit 10 ;;
esac
[[ "$(readlink -f "$root")" == "$root" && -f "$target" && ! -L "$target" ]]
[[ "$(readlink -f "$target")" == "$target" ]]
grep -Fq "define('BUSINESS', 'zhct_jsr');" "$root/env.php"
for command in patch flock base64 sha256sum curl; do command -v "$command" >/dev/null; done
[[ -x "$php" ]]
current=$(hash_file "$target")
[[ "$current" == "$old_hash" || "$current" == "$new_hash" ]] || { printf 'Baseline mismatch\n' >&2; exit 11; }
[[ ! -L "$backup_dir" ]]
mkdir -p "$backup_dir"
[[ "$(readlink -f "$backup_dir")" == "$backup_dir" ]]
exec 9>"$backup_dir/deploy.lock"
flock -n 9 || { printf 'Another hotfix is running\n' >&2; exit 12; }
current=$(hash_file "$target")
[[ "$current" == "$old_hash" || "$current" == "$new_hash" ]] || exit 13
if [[ "$current" == "$new_hash" ]]; then
    [[ -f "$backup" && ! -L "$backup" && "$(hash_file "$backup")" == "$old_hash" ]]
    "$php" -l "$target"
    printf 'ALREADY_APPLIED %s\n' "$new_hash"
    success=1
    exit 0
fi
if [[ -e "$backup" || -L "$backup" ]]; then
    [[ ! -L "$backup" && "$(hash_file "$backup")" == "$old_hash" ]] || exit 14
else
    cp -p "$target" "$backup"
fi
[[ "$(hash_file "$backup")" == "$old_hash" ]]
staged=$(mktemp "$root/application/p/logic/.MealOrder.php.VWCG-1357.XXXXXX")
cp -p "$target" "$staged"
base64 --decode <<'JSR_PATCH_BASE64' | patch --batch --forward --fuzz=0 --no-backup-if-mismatch --reject-file=- "$staged"
@PATCH_BASE64@
JSR_PATCH_BASE64
[[ "$(hash_file "$staged")" == "$new_hash" ]] || exit 15
"$php" -l "$staged"
[[ "$(hash_file "$target")" == "$old_hash" ]] || exit 16
# Same-directory rename keeps readers from seeing a partially written PHP file.
mv -f "$staged" "$target"
changed=1
[[ "$(hash_file "$target")" == "$new_hash" ]] || exit 17
"$php" -l "$target"
http=$(curl --max-time 8 --silent --output /dev/null --write-out '%{http_code}' -H 'Host: jsr.yyangpt.cn' http://127.0.0.1/)
# Both nodes returned 301 during preflight; 200 also represents a reachable entry.
[[ "$http" == 301 || "$http" == 200 ]] || { printf 'HTTP_CHECK_FAILED %s\n' "$http" >&2; exit 18; }
for path in /dist/ /p/mealOrder/detail; do
    code=$(curl --max-time 8 --silent --output /dev/null --write-out '%{http_code}' -H 'Host: jsr.yyangpt.cn' "http://127.0.0.1$path")
    [[ "$code" == 200 ]] || { printf 'ENTRY_CHECK_FAILED %s %s\n' "$path" "$code" >&2; exit 19; }
    printf 'ENTRY_OK %s %s\n' "$path" "$code"
done
printf 'HOTFIX_APPLIED host=%s sha256=%s http=%s\n' "$(hostname)" "$new_hash" "$http"
printf 'BACKUP_READY %s %s\n' "$backup" "$(hash_file "$backup")"
success=1
