#!/usr/bin/env bash
# Production uptime check, run from the dev server every five minutes (cron, rian).
# From outside the droplet: /api/health must answer 200 with "ok", the sign-in page 200.
# Every check is logged; a failure is written to the incident log with the headers.
# Alarm: after two consecutive failures an email goes to rian through Resend (the key is
# read from the project's own .app.env, never copied anywhere else; the sender domain
# dutyfreeprofessor.com is verified in Resend), and one more email when it recovers.
# A state file keeps it to one email per outage, not one per five minutes.
set -uo pipefail
BASE='https://dutyfreeprofessor.com'
UA='srv-monitor/1.0 (+rian.ca uptime check)'
ROOT='/srv/apps/dutyfreeprofessor'
LOG="$ROOT/.logs/runs/uptime.log"
INCIDENTS="$ROOT/.logs/runs/uptime-incidents.log"
STATE="$ROOT/.logs/runs/.uptime.state"      # "up" or "down:<n>"; created on first run
ALERT_TO='rian@rian.ca'
ALERT_FROM='Duty Free Professor monitor <monitor@dutyfreeprofessor.com>'
TIMEOUT=30
touch "$LOG" "$INCIDENTS"
ts=$(date -u +%Y-%m-%dT%H:%M:%SZ)
hdr=$(mktemp); trap 'rm -f "$hdr"' EXIT

health=$(curl -s -A "$UA" --max-time "$TIMEOUT" -w '|%{http_code}|%{time_total}' "$BASE/api/health" 2>/dev/null)
body=${health%%|*}; rest=${health#*|}; hcode=${rest%%|*}; htime=${rest##*|}
lcode=$(curl -s -o /dev/null -D "$hdr" -A "$UA" --max-time "$TIMEOUT" -w '%{http_code}' "$BASE/login" 2>/dev/null)

ok=1
case "$body" in *'"status":"ok"'*) ;; *) ok=0 ;; esac
[ "${hcode:-000}" = "200" ] || ok=0
[ "${lcode:-000}" = "200" ] || ok=0
printf '%s health=%s %ss login=%s ok=%s\n' "$ts" "${hcode:-000}" "${htime:-0}" "${lcode:-000}" "$ok" >> "$LOG"

send_mail() {  # subject, text
  local key; key=$(sed -n 's/^RESEND_API_KEY=//p' "$ROOT/.app.env" | tr -d '\r\n')
  [ -n "$key" ] || { echo "$ts no RESEND_API_KEY in .app.env; alert not sent" >> "$INCIDENTS"; return; }
  python3 - "$1" "$2" "$ALERT_TO" "$ALERT_FROM" "$key" << 'PY'
import json, sys, urllib.request
subject, text, to, sender, key = sys.argv[1:6]
req = urllib.request.Request("https://api.resend.com/emails", method="POST",
    data=json.dumps({"from": sender, "to": [to], "subject": subject, "text": text}).encode(),
    headers={"Authorization": "Bearer " + key, "Content-Type": "application/json", "User-Agent": "dfp-uptime/1.0"})
try:
    with urllib.request.urlopen(req, timeout=20) as r: print("alert sent", r.status)
except Exception as e: print("alert failed", e)
PY
}

prev=$(cat "$STATE" 2>/dev/null || echo up)
if [ "$ok" = 0 ]; then
  { printf '%s INCIDENT health=%s login=%s body=%s\n' "$ts" "${hcode:-000}" "${lcode:-000}" "${body:0:120}"; cat "$hdr"; echo '---'; } >> "$INCIDENTS"
  case "$prev" in
    up)      echo "down:1" > "$STATE" ;;
    down:1)  echo "down:2" > "$STATE"
             send_mail "dutyfreeprofessor.com is DOWN" "Two checks in a row failed at $ts (UTC). health=${hcode:-000} login=${lcode:-000}. Incident log: $INCIDENTS on mosiah. Droplet: ssh deploy@bwlive; RUNBOOK 'Production'." >> "$INCIDENTS" ;;
    *)       ;;   # already alerted; stay quiet until it recovers
  esac
else
  case "$prev" in
    down:2*) send_mail "dutyfreeprofessor.com is back" "Recovered at $ts (UTC): health=${hcode} in ${htime}s, login=${lcode}." >> "$INCIDENTS" ;;
  esac
  echo up > "$STATE"
fi
exit 0
