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

runtime_env="${BEE_RUNTIME_ENV_FILE:-/opt/.env}"
worker_env="${BEE_WORKER_ENV_FILE:-/etc/razgar/bee-worker.env}"
if [[ -f "$runtime_env" ]]; then
    set -a
    source "$runtime_env"
    set +a
fi
[[ -f "$worker_env" ]] && source "$worker_env"
health_url="${BEE_PRIVATE_HEALTH_URL:-https://127.0.0.1/api/private/health.php}"
health_headers_file="${BEE_HEALTH_HEADERS_FILE:-}"
health_resolve="${BEE_PRIVATE_HEALTH_RESOLVE:-}"
worker_id="${BEE_WORKER_ID:?BEE_WORKER_ID is required}"
worker_generation="${BEE_WORKER_GENERATION:?BEE_WORKER_GENERATION is required}"
bee_manifest="${BEE_RUNTIME_MANIFEST:?BEE_RUNTIME_MANIFEST is required}"
bot_manifest="${BOT_RUNTIME_MANIFEST:?BOT_RUNTIME_MANIFEST is required}"
timing_policy_version="${TIMING_POLICY_VERSION:-1.0.0}"
minimum_free_bytes=$((1024 * 1024 * 1024))

require() { "$@" >/dev/null 2>&1 || { echo "Verification failed: $*" >&2; exit 1; }; }
[[ -f "$bot_manifest" ]] || { echo 'Bot runtime manifest is missing.' >&2; exit 1; }
[[ -f "$bee_manifest" ]] || { echo 'BEE runtime manifest is missing.' >&2; exit 1; }
[[ -f /run/razgar/bee-data-handler.ready ]] || { echo 'BEE data handler is not ready.' >&2; exit 1; }
[[ -f /run/razgar/bee-ws.ready ]] || { echo 'BEE websocket is not ready.' >&2; exit 1; }
[[ "$(df -PB1 /var/www/html | awk 'NR==2 {print $4}')" -ge "$minimum_free_bytes" ]] || { echo 'Insufficient disk space.' >&2; exit 1; }

curl_args=(
    --fail --silent --show-error
    --cert "${BEE_MTLS_CERT_FILE:?BEE_MTLS_CERT_FILE is required}"
    --key "${BEE_MTLS_KEY_FILE:?BEE_MTLS_KEY_FILE is required}"
    --cacert "${BEE_MTLS_CA_FILE:?BEE_MTLS_CA_FILE is required}"
)
[[ -n "$health_headers_file" ]] && curl_args+=(--config "$health_headers_file")
[[ -n "$health_resolve" ]] && curl_args+=(--resolve "$health_resolve")
health_timestamp="$(( $(date +%s%N) / 1000000 ))"
health_nonce="$(python3 -c 'import secrets; print(secrets.token_hex(16))')"
health_body='{}'
health_body_sha256="$(printf '%s' "$health_body" | sha256sum | awk '{print $1}')"
BEE_HEALTH_MESSAGE="$(printf '%s\n%s\nPOST\n/private/health.php\n%s\ninterface\n1' \
    "$health_timestamp" "$health_nonce" "$health_body_sha256")"
export BEE_HEALTH_MESSAGE
health_signature="$(python3 -c 'import hashlib, hmac, os; print(hmac.new(os.environ["BEE_SERVICE_HMAC_KEY"].encode(), os.environ["BEE_HEALTH_MESSAGE"].encode(), hashlib.sha256).hexdigest())')"
unset BEE_HEALTH_MESSAGE
health="$(curl "${curl_args[@]}" \
    --header 'Content-Type: application/json' \
    --header 'X-Razgar-Service: interface' \
    --header 'X-Razgar-Principal: 1' \
    --header "X-Razgar-Timestamp: $health_timestamp" \
    --header "X-Razgar-Nonce: $health_nonce" \
    --header "X-Razgar-Signature: $health_signature" \
    --request POST --data "$health_body" "$health_url")"
command -v jq >/dev/null || { echo 'jq is required for verification.' >&2; exit 1; }
bee_runtime_sha256="$(sha256sum "$bee_manifest" | awk '{print $1}')"
bot_runtime_sha256="$(sha256sum "$bot_manifest" | awk '{print $1}')"
bot_tree_sha256="$(jq -r '.tree_sha256' "$bot_manifest")"
[[ "$bot_tree_sha256" =~ ^[0-9a-f]{64}$ ]] || { echo 'Bot runtime tree digest is invalid.' >&2; exit 1; }
[[ "$(jq -r '.result.worker_id' <<<"$health")" == "$worker_id" ]] || { echo 'Worker identity does not match.' >&2; exit 1; }
[[ "$(jq -r '.result.generation' <<<"$health")" == "$worker_generation" ]] || { echo 'Worker generation does not match.' >&2; exit 1; }
[[ "$(jq -r '.result.bee_runtime_sha256' <<<"$health")" == "$bee_runtime_sha256" ]] || { echo 'BEE runtime manifest digest does not match.' >&2; exit 1; }
[[ "$(jq -r '.result.bot_runtime_sha256' <<<"$health")" == "$bot_runtime_sha256" ]] || { echo 'Bot runtime manifest digest does not match.' >&2; exit 1; }
[[ "$(jq -r '.result.bot_tree_sha256' <<<"$health")" == "$bot_tree_sha256" ]] || { echo 'Bot runtime tree digest does not match.' >&2; exit 1; }
[[ "$(jq -r '.result.timing_policy_version' <<<"$health")" == "$timing_policy_version" ]] || { echo 'Timing policy does not match.' >&2; exit 1; }
[[ "$(jq -r '.result.redis.status' <<<"$health")" == 'ok' ]] || { echo 'Redis is not healthy.' >&2; exit 1; }
[[ "$(jq -r '.result.redis.json_module_ready' <<<"$health")" == 'true' ]] || { echo 'RedisJSON is not ready.' >&2; exit 1; }
[[ "$(jq -r '.result.data_handler_status' <<<"$health")" == 'ok' ]] || { echo 'Data handler is not healthy.' >&2; exit 1; }
[[ "$(jq -r '.result.ws_status' <<<"$health")" == 'ok' ]] || { echo 'Websocket is not healthy.' >&2; exit 1; }
[[ "$(jq -r '.result.database.status' <<<"$health")" == 'ok' ]] || { echo 'Database is not healthy.' >&2; exit 1; }
[[ "$(jq -r '.result.database.active_test_count' <<<"$health")" == '0' ]] || { echo 'Unexpected active BEE tests.' >&2; exit 1; }

for _ in {1..30}; do
    if curl --silent --output /dev/null --connect-timeout 1 --max-time 1 \
        http://127.0.0.1:8001/health; then
        break
    fi
    sleep 0.2
done
curl --silent --output /dev/null --connect-timeout 1 --max-time 1 \
    http://127.0.0.1:8001/health || {
    echo 'Bot management API did not become reachable.' >&2
    exit 1
}

bot_status_timestamp="$(( $(date +%s%N) / 1000000 ))"
bot_status_nonce="$(python3 -c 'import secrets; print(secrets.token_hex(16))')"
bot_status_body='{}'
bot_status_body_sha256="$(printf '%s' "$bot_status_body" | sha256sum | awk '{print $1}')"
BOT_STATUS_MESSAGE="$(printf '%s\n%s\nPOST\n/host_status\n%s\ninterface\n1' \
    "$bot_status_timestamp" "$bot_status_nonce" "$bot_status_body_sha256")"
export BOT_STATUS_MESSAGE
bot_status_signature="$(python3 -c 'import hashlib, hmac, os; print(hmac.new(os.environ["BOT_SERVICE_HMAC_KEY"].encode(), os.environ["BOT_STATUS_MESSAGE"].encode(), hashlib.sha256).hexdigest())')"
unset BOT_STATUS_MESSAGE
bot_status="$(curl --fail --silent --show-error \
    --header 'Content-Type: application/json' \
    --header 'X-Razgar-Service: interface' \
    --header 'X-Razgar-Principal: 1' \
    --header "X-Razgar-Timestamp: $bot_status_timestamp" \
    --header "X-Razgar-Nonce: $bot_status_nonce" \
    --header "X-Razgar-Signature: $bot_status_signature" \
    --request POST --data "$bot_status_body" \
    http://127.0.0.1:8001/host_status)"
[[ "$(jq -r '.runtime_sha256' <<<"$bot_status")" == "$bot_runtime_sha256" ]] || { echo 'Bot management runtime identity does not match.' >&2; exit 1; }
[[ "$(jq -r '.tree_sha256' <<<"$bot_status")" == "$bot_tree_sha256" ]] || { echo 'Bot management tree identity does not match.' >&2; exit 1; }
[[ "$(jq -r '.timing_policy_version' <<<"$bot_status")" == "$timing_policy_version" ]] || { echo 'Bot management timing policy does not match.' >&2; exit 1; }
[[ "$(jq -r '.active_live_units' <<<"$bot_status")" == '0' ]] || { echo 'Unexpected live Bot units on BEE worker.' >&2; exit 1; }
[[ "$(jq -r '.active_bee_units' <<<"$bot_status")" == '0' ]] || { echo 'Unexpected BEE Bot units during verification.' >&2; exit 1; }
require env REDISCLI_AUTH="${REDIS_PASS:?REDIS_PASS is required}" redis-cli --raw ping
require systemctl is-active --quiet bee_data_handler.service
require systemctl is-active --quiet bee_websocket_server.service
require systemctl is-active --quiet bot_management_api.service
failed_units="$(systemctl --failed --no-legend --plain)"
[[ -z "$failed_units" ]] || {
    echo "Failed systemd units remain:" >&2
    printf '%s\n' "$failed_units" >&2
    exit 1
}
echo 'Worker verification passed; scheduler state remains provisioning.'
