#!/usr/bin/env bash
# Backend lifecycle evidence remains complete when late checks degrade a successful deploy.
set -uo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
SCRIPT="$ROOT/packaging/deploy-local.sh"
TESTROOT="${XDG_CACHE_HOME:-$HOME/.cache}/overdeck/tests/deploy-degraded-lifecycle/run-$$-$RANDOM"
DEPLOY="$TESTROOT/deploy"
FUNCTIONS="$TESTROOT/functions.sh"
REPORT="$TESTROOT/backend-releases.json"
mkdir -p "$DEPLOY/packaging"
trap 'rm -rf "$TESTROOT"' EXIT

fails=0
check() {
  if (( $1 == 0 )); then printf 'ok - %s\n' "$2"
  else printf 'FAIL - %s\n' "$2"; fails=$((fails + 1)); fi
}

bash -n "$SCRIPT"
check "$?" 'deploy-local.sh parses'

sed -n '/^mark_degraded() {/,/^}/p' "$SCRIPT" >"$FUNCTIONS"
sed -n '/^degraded_summary() {/,/^}/p' "$SCRIPT" >>"$FUNCTIONS"
sed -n '/^publish_backend_release_report() {/,/^}/p' "$SCRIPT" >>"$FUNCTIONS"
# shellcheck source=/dev/null
source "$FUNCTIONS"

cat >"$DEPLOY/packaging/backend-release.sh" <<'SH'
#!/usr/bin/env bash
command=$1
component=$2
case "$command" in
  prune)
    printf '{"component":"%s","status":"pruned","removed":0,"retained":2,"skipped":0}\n' "$component"
    [[ "${FIXTURE_DEGRADED:-0}:$component" != 1:controller ]]
    ;;
  inspect)
    service=$3
    expected=$4
    state=healthy
    [[ "$expected" == inactive ]] && state=dark
    [[ "${FIXTURE_DEGRADED:-0}:$component" == 1:botmaster-proxy ]] && state=degraded
    printf '{"component":"%s","service":"%s","expected":"%s","state":"%s","rollback_ready":true}\n' \
      "$component" "$service" "$expected" "$state"
    [[ "$state" != degraded ]]
    ;;
esac
SH
chmod +x "$DEPLOY/packaging/backend-release.sh"

BACKEND_RELEASE_ROOT="$TESTROOT/backend"
BACKEND_RELEASE_REPORT="$REPORT"
BACKEND_RELEASE_MINIMUM_AGE=86400
ACTIONS_GATEWAY_SERVICE=actions-gateway.service
gateway_enabled=0
deployment_sha=$(printf 'a%.0s' {1..40})
DEGRADED_REASONS=()
publish_backend_release_report >"$TESTROOT/prune.out" 2>"$TESTROOT/prune.err"
python3 - "$REPORT" "$deployment_sha" <<'PY'
import json
import sys

report = json.load(open(sys.argv[1], encoding="utf-8"))
assert report["deployed_sha"] == sys.argv[2]
assert [item["component"] for item in report["components"]] == [
    "collector", "controller", "botmaster-proxy", "actions-gateway"
]
gateway = report["components"][-1]
assert gateway["expected"] == "inactive"
assert gateway["state"] == "dark"
PY
check "$?" 'one report consolidates all backend identities and the honest dark Gateway state'
if (( ${#DEGRADED_REASONS[@]} == 0 )); then rc=0; else rc=1; fi
check "$rc" 'healthy pruning and inspection leave deployment status healthy'

DEGRADED_REASONS=()
FIXTURE_DEGRADED=1
export FIXTURE_DEGRADED
publish_backend_release_report >"$TESTROOT/degraded.out" 2>"$TESTROOT/degraded.err"
unset FIXTURE_DEGRADED
summary=$(degraded_summary)
if [[ "$summary" == *backend-prune-controller* && "$summary" == *backend-inspection-botmaster-proxy* \
  && "$(<"$TESTROOT/degraded.err")" == *'"status":"degraded"'* ]]; then rc=0; else rc=1; fi
check "$rc" 'late lifecycle tripwires accumulate degraded reasons without failing deployment'

if grep -q 'mark_degraded live-report-refresh-failed' "$SCRIPT" \
  && grep -q 'mark_degraded sandbox-image-drift' "$SCRIPT" \
  && grep -q 'terminal_status=deployed-degraded' "$SCRIPT" \
  && ! grep -q 'fail sandbox-image-drift' "$SCRIPT" \
  && ! grep -q 'fail live-report-refresh-failed' "$SCRIPT"; then rc=0; else rc=1; fi
check "$rc" 'observability and parity tripwires terminate as deployed-degraded, not failed'

(( fails == 0 )) || { printf '%s check(s) failed\n' "$fails" >&2; exit 1; }
printf 'deploy-degraded-lifecycle: all checks passed\n'
