#!/usr/bin/env bash
# Post-release verification for desfoto.de.
#
#   .ocauto/verify <release-sha>
#
# Proves that (a) the live desfoto.de serves the released build and assets,
# (b) the security posture matches the promises on /datenschutz/, and
# (c) the neighbouring sites (dennyschulz.de, dennyapp.de) are untouched.
set -euo pipefail

cd "$(dirname "$0")/.."
root="$(pwd)"
release_sha="${1:-unknown}"
remote="${DESFOTO_REMOTE:-prod-main}"
base="https://desfoto.de"

failures=0
pass() { printf '  ok   %s\n' "$1"; }
fail() { printf '  FAIL %s\n' "$1" >&2; failures=$((failures + 1)); }

check_status() {
  local url="$1" want="$2" got
  got="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 30 "$url" || echo 000)"
  if [ "$got" = "$want" ]; then pass "$url -> $got"; else fail "$url -> $got (want $want)"; fi
}

check_contains() {
  local url="$1" needle="$2" body
  body="$(curl -sS --max-time 30 "$url" || true)"
  if printf '%s' "$body" | grep -qF -- "$needle"; then
    pass "$url contains '$needle'"
  else
    fail "$url does not contain '$needle'"
  fi
}

check_header() {
  local url="$1" header="$2" headers
  headers="$(curl -sSI --max-time 30 "$url" || true)"
  if printf '%s' "$headers" | grep -qi "^$header:"; then
    pass "$url sends $header"
  else
    fail "$url is missing the $header header"
  fi
}

printf '\n== release identity\n'
if [ "$release_sha" != "unknown" ] && git -C "$root" rev-parse --verify --quiet "$release_sha" >/dev/null; then
  local_hash="$(cd "$root/site" && find . -type f ! -name sitemap.xml ! -path './.well-known/*' -print0 |
    sort -z | xargs -0 sha256sum | sha256sum | cut -d' ' -f1)"
  remote_hash="$(ssh "$remote" "sudo sh -c 'cd /home/denny/stacks/desfoto/site && find . -type f ! -name sitemap.xml ! -path ./.well-known/\* -print0 | sort -z | xargs -0 sha256sum | sha256sum'" | cut -d' ' -f1)"
  if [ "$local_hash" = "$remote_hash" ]; then
    pass "deployed site tree matches the release ($local_hash)"
  else
    fail "deployed site tree differs from the release ($local_hash != $remote_hash)"
  fi
  remote_release="$(ssh "$remote" 'sudo cat /home/denny/stacks/desfoto/RELEASE' | tr -d '\r\n')"
  if [ "$remote_release" = "$release_sha" ]; then
    pass "release marker is $release_sha"
  else
    fail "release marker is '$remote_release' (want $release_sha)"
  fi
fi

printf '\n== routes\n'
for route in / /fotografie/ /businessfotografie/ /portrait-und-model/ /familien-und-paare/ \
  /minishootings/ /video/ /social-media/ /projekte/ /ueber/ /kontakt/ /impressum/ /datenschutz/; do
  check_status "$base$route" 200
done

printf '\n== canonical host and redirects\n'
www_status="$(curl -sS -o /dev/null -w '%{http_code}' --max-time 30 https://www.desfoto.de/ || echo 000)"
www_target="$(curl -sS -o /dev/null -w '%{redirect_url}' --max-time 30 https://www.desfoto.de/ || true)"
if [ "$www_status" = "301" ] && [ "$www_target" = "https://desfoto.de/" ]; then
  pass "www.desfoto.de -> https://desfoto.de/ (301)"
else
  fail "www.desfoto.de -> $www_status $www_target"
fi
http_target="$(curl -sS -o /dev/null -w '%{redirect_url}' --max-time 30 http://desfoto.de/ || true)"
case "$http_target" in
  https://desfoto.de/*) pass "http://desfoto.de/ -> $http_target" ;;
  *) fail "http://desfoto.de/ redirects to '$http_target'" ;;
esac

printf '\n== content\n'
check_contains "$base/" "Bilder und Filme, die nicht beliebig aussehen"
check_contains "$base/impressum/" "§ 5 DDG"
check_contains "$base/impressum/" "DE462149560"
check_contains "$base/datenschutz/" "keine Zugriffsprotokolle"
check_contains "$base/datenschutz/" "youtube-nocookie.com"
check_contains "$base/video/" "NWWFTf7l8g0"
check_contains "$base/sitemap.xml" "<loc>https://desfoto.de/video/</loc>"

printf '\n== error handling and metadata\n'
check_status "$base/diese-seite-gibt-es-nicht/" 404
check_contains "$base/diese-seite-gibt-es-nicht/" "Diese Seite gibt es nicht"
check_status "$base/.well-known/security.txt" 200
check_status "$base/robots.txt" 200

printf '\n== assets\n'
check_status "$base/assets/img/hero-studio-1200.webp" 200
check_status "$base/assets/img/favicon-32.png" 200
check_status "$base/assets/site.css" 200
check_status "$base/assets/fonts/fraunces-latin.woff2" 200
check_status "$base/assets/img/og-desfoto.jpg" 200

printf '\n== privacy promises and headers\n'
check_header "$base/" "Strict-Transport-Security"
check_header "$base/" "Content-Security-Policy"
check_header "$base/" "X-Content-Type-Options"
check_header "$base/" "Referrer-Policy"
if curl -sSI --max-time 30 "$base/" | grep -qi '^set-cookie:'; then
  fail "a cookie is set on the homepage"
else
  pass "no Set-Cookie on the homepage"
fi

printf '\n== neighbouring sites untouched\n'
check_status "https://www.dennyschulz.de/" 200
check_contains "https://www.dennyschulz.de/impressum" "Denny Schulz"
check_status "https://dennyapp.de/" 200

printf '\n== TLS\n'
if command -v openssl >/dev/null 2>&1; then
  if echo | openssl s_client -servername desfoto.de -connect desfoto.de:443 2>/dev/null |
    openssl x509 -noout -checkend 604800 -subject 2>/dev/null; then
    pass "certificate for desfoto.de is valid for at least 7 more days"
  else
    fail "certificate for desfoto.de is missing or expires within 7 days"
  fi
fi

if [ "$failures" -ne 0 ]; then
  printf '\nVERIFY FAIL (%d problem(s)) release=%s\n' "$failures" "$release_sha" >&2
  exit 1
fi
printf '\nVERIFY PASS release=%s\n' "$release_sha"
