#!/usr/bin/env bash
# Authoritative deterministic QA for the desfoto.de static site.
#
#   ./qa  ->  build the site, prove the build is reproducible, validate the
#             nginx configuration, and run the structural test suite.
#
# Exit code 0 means the repository is releasable as-is.
set -euo pipefail

cd "$(dirname "$0")/.."
root="$(pwd)"
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT

step() { printf '\n== %s\n' "$1"; }

step "build"
python3 scripts/build-site.py

step "build is reproducible"
# sitemap.xml and .well-known/security.txt embed the build date on purpose and
# are therefore excluded from the byte-for-byte comparison.
hash_tree() {
  (cd "$root/site" && find . -type f \
      ! -name sitemap.xml ! -path './.well-known/*' -print0 |
    sort -z | xargs -0 sha256sum)
}
hash_tree >"$tmp/before.txt"
python3 scripts/build-site.py >/dev/null
hash_tree >"$tmp/after.txt"
if ! diff -u "$tmp/before.txt" "$tmp/after.txt"; then
  echo "FAIL: the build output is not reproducible" >&2
  exit 1
fi
echo "rebuild produced byte-identical output for $(wc -l <"$tmp/after.txt") files"

step "nginx configuration"
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
  docker run --rm \
    -v "$root/nginx.conf:/etc/nginx/conf.d/default.conf:ro" \
    -v "$root/site:/usr/share/nginx/html:ro" \
    nginx:1.28-alpine nginx -t
else
  echo "SKIP: no usable docker daemon; nginx -t cannot be verified here" >&2
  exit 1
fi

step "compose configuration"
if docker compose version >/dev/null 2>&1; then
  DESFOTO_CHECK_ONLY=1 docker compose -f compose.yml -f compose.vps.yml config --quiet
  echo "compose.yml + compose.vps.yml are valid"
fi

step "structural tests"
python3 -m unittest discover -s tests -p 'test_*.py' -v

step "shellcheck"
if command -v shellcheck >/dev/null 2>&1; then
  mapfile -t scripts < <(git ls-files '*.sh' '.ocauto/*')
  if [ "${#scripts[@]}" -gt 0 ]; then
    shellcheck "${scripts[@]}"
  fi
fi

printf '\nQA PASS\n'
