#!/usr/bin/env bash
# Local checks for hsc-setup.sh: syntax, and the pure functions that decide
# what ends up in keys.json and in the nginx map. Everything root-only is
# stubbed; this never touches the system.
set -uo pipefail

SCRIPT="${1:?usage: hsc-setup-check.sh <path to hsc-setup.sh>}"
WORK="$(mktemp -d)"
trap 'rm -rf "$WORK"' EXIT
fail=0
check() { # check <name> <expected> <actual>
  if [ "$2" = "$3" ]; then printf '  ok   %s\n' "$1"
  else printf '  FAIL %s\n       expected: %s\n       actual:   %s\n' "$1" "$2" "$3"; fail=1; fi
}

printf '\nsyntax\n'
if bash -n "$SCRIPT"; then printf '  ok   bash -n\n'; else printf '  FAIL bash -n\n'; fail=1; fi

# Source everything above the entry point, so the functions exist but nothing runs.
sed '/^# Entry point$/,$d' "$SCRIPT" >"$WORK/lib.sh"
# shellcheck disable=SC1090
DIR="$WORK" NGINX_KEYS="$WORK/hsc-keys.conf" SERVICE_USER="$(id -un)" . "$WORK/lib.sh"
DIR="$WORK"; NGINX_KEYS="$WORK/hsc-keys.conf"; SERVICE_USER="$(id -un)"
trap 'rm -rf "$WORK"' EXIT ERR # the script installs its own ERR trap; drop it here

# `install` needs root for -o/-g; keep the last two arguments and copy.
install() { local args=("$@") n=$#; cp "${args[n-2]}" "${args[n-1]}"; }
chmod_stub() { :; }

printf '\nsites\n'
check "three sites are configured" "3" "$(site_names | wc -l | tr -d ' ')"
check "names" "elevaseo seoinsight dash-seoinsight" "$(site_names | tr '\n' ' ' | sed 's/ $//')"
check "elevaseo origins" "https://elevaseo.com https://www.elevaseo.com" "$(site_origins elevaseo)"
check "dash origins" "https://dash.seoinsight.app" "$(site_origins dash-seoinsight)"
check "unknown site has no origins" "" "$(site_origins nope)"

printf '\nkeys\n'
key="$(new_key elevaseo)"
if printf '%s' "$key" | grep -Eq '^k_elevaseo_[0-9a-f]{64}$'; then
  printf '  ok   a key is k_<site>_<64 hex> (256 bits)\n'
else
  printf '  FAIL key shape: %s\n' "$key"; fail=1
fi
check "two keys differ" "different" "$([ "$(new_key x)" != "$(new_key x)" ] && echo different || echo same)"

printf '\nnginx map round-trip\n'
k1="$(new_key elevaseo)"; k2="$(new_key seoinsight)"; k3="$(new_key dash-seoinsight)"
write_nginx_keys "elevaseo=$k1" "seoinsight=$k2" "dash-seoinsight=$k3"
check "elevaseo key reads back" "$k1" "$(existing_key elevaseo)"
check "dash-seoinsight key reads back" "$k3" "$(existing_key dash-seoinsight)"
check "an unconfigured site has no key" "" "$(existing_key client9)"
check "the map has a default" "1" "$(grep -c 'default ""' "$WORK/hsc-keys.conf")"
check "one line per site" "3" "$(grep -c '^    "Bearer k_' "$WORK/hsc-keys.conf")"
check "no key leaks into a comment" "0" "$(grep -c "^#.*$k1" "$WORK/hsc-keys.conf")"

printf '\nkeys.json\n'
write_keys_json
if bun -e 'JSON.parse(require("fs").readFileSync(process.argv[1],"utf8"))' "$WORK/keys.json" 2>/dev/null; then
  printf '  ok   valid JSON\n'
else
  printf '  FAIL keys.json is not valid JSON:\n'; cat "$WORK/keys.json"; fail=1
fi
check "elevaseo has both origins" "2" \
  "$(bun -e 'const k=JSON.parse(require("fs").readFileSync(process.argv[1],"utf8"));console.log(k.elevaseo.length)' "$WORK/keys.json" 2>/dev/null)"
check "dash has one origin" "https://dash.seoinsight.app" \
  "$(bun -e 'const k=JSON.parse(require("fs").readFileSync(process.argv[1],"utf8"));console.log(k["dash-seoinsight"][0])' "$WORK/keys.json" 2>/dev/null)"
check "no key material in keys.json" "0" "$(grep -c 'k_elevaseo_' "$WORK/keys.json")"

printf '\ncli\n'
check "help exits 0" "0" "$(bash "$SCRIPT" --help >/dev/null 2>&1; echo $?)"
check "unknown command is refused" "1" "$(bash "$SCRIPT" frobnicate >/dev/null 2>&1; echo $?)"

printf '\n'
[ $fail -eq 0 ] && printf 'all checks passed\n' || printf 'FAILURES\n'
exit $fail
