#!/usr/bin/env bash
# Reset the astra mt instance to its seeded state.
#
# astra runs the write-enabled mt: reachable over the tailnet only, logged into
# with real MNW accounts, and driven by the browser axis of an audit run through
# thread create, reply, flag and moderation. That is a surface that accumulates
# junk by design, so it needs a way back to a known state, and this is it.
#
# Hard reset, not incremental: drop every schema, let the binary re-migrate and
# re-seed. Nobody is looking at this instance, so there is nothing to preserve
# and no reason to make the reset clever. Two audit runs a week apart should see
# the same forum.
#
# What it does NOT reset is the MNW side. The accounts the harness logs in as
# live on testnot and are recreated by testnot's own reseed
# (`sando/deploy/mnw-testnot-seed.sh`, harness phase). The two are deliberately
# independent: mt's state is disposable, the identities behind it are not.
#
# Usage:
#   deploy/reset-astra.sh            # stop, wipe, migrate, seed, start, verify
#
# Env:
#   MT_ASTRA_SSH   ssh target (default: astra)
#   MT_ASTRA_DB    database name (default: multithreaded)
set -euo pipefail

SSH_TARGET="${MT_ASTRA_SSH:-astra}"
DB="${MT_ASTRA_DB:-multithreaded}"
SERVICE="multithreaded.service"
APP_DIR="/opt/multithreaded"
BIN="$APP_DIR/multithreaded"
ENV_FILE="$APP_DIR/.env"
APP_USER="multithreaded"
PORT="${MT_ASTRA_PORT:-3400}"

log() { echo "[$(date -u +%H:%M:%S)] $*"; }
on_astra() { ssh "$SSH_TARGET" "$@"; }

log "stopping $SERVICE on $SSH_TARGET"
on_astra "sudo systemctl stop $SERVICE"

# Drop every non-system schema rather than just `public`: tower-sessions creates
# its own, and a surviving session table would carry logins across a reset that
# is supposed to have removed the users they point at. Recreate `public` OWNED BY
# the app role, because on PG15+ a postgres-owned public grants the app no
# CREATE and the boot migrations fail with "no schema has been selected".
log "resetting schema in $DB"
on_astra "sudo -u postgres psql -v ON_ERROR_STOP=1 -d $DB" <<SQL
DO \$\$
DECLARE s text;
BEGIN
    FOR s IN
        SELECT nspname FROM pg_namespace
        WHERE nspname NOT LIKE 'pg_%' AND nspname <> 'information_schema'
    LOOP
        EXECUTE format('DROP SCHEMA IF EXISTS %I CASCADE', s);
    END LOOP;
    EXECUTE 'CREATE SCHEMA public AUTHORIZATION $APP_USER';
END \$\$;
SQL

# `--seed` migrates the empty schema, seeds, and exits before binding a port, so
# it is safe with the service stopped. systemd-run with the service's own
# EnvironmentFile rather than sourcing it in a shell: systemd parses KEY=value
# literally, so a secret containing shell metacharacters survives.
log "migrating + seeding"
on_astra "sudo systemd-run --pipe --wait --collect --service-type=exec \
    -p EnvironmentFile=$ENV_FILE -p WorkingDirectory=$APP_DIR -p User=$APP_USER \
    $BIN --seed"

log "starting $SERVICE"
on_astra "sudo systemctl start $SERVICE"

healthy=0
for _ in $(seq 1 20); do
    code=$(on_astra "curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:$PORT/api/health" || echo 000)
    [ "$code" = "200" ] && { log "health OK"; healthy=1; break; }
    sleep 3
done
if [ "$healthy" -ne 1 ]; then
    echo "mt did not return healthy after the reset" >&2
    exit 1
fi

# Healthy is not the same as usable. A browser run that logs in and finds no
# membership fails at the first write with a 403, which reads like a permissions
# bug in mt rather than a seed that did not finish. Assert the harness
# preconditions here so the reset and its verification cannot drift apart:
# the three accounts exist, and the owner account really is Owner somewhere.
log "verifying harness preconditions"
counts=$(on_astra "sudo -u postgres psql -v ON_ERROR_STOP=1 -At -d $DB" <<'SQL'
SELECT count(*) FROM users
 WHERE mnw_account_id IN (
   '00000000-0000-0000-0000-00000000f001',
   '00000000-0000-0000-0000-00000000f002',
   '00000000-0000-0000-0000-00000000f003');
SELECT count(*) FROM memberships
 WHERE user_id = '00000000-0000-0000-0000-00000000f003' AND role = 'owner';
SELECT count(*) FROM threads;
SQL
)
accounts=$(sed -n 1p <<<"$counts")
owner_rows=$(sed -n 2p <<<"$counts")
threads=$(sed -n 3p <<<"$counts")

[ "$accounts" = "3" ] || { echo "expected 3 harness accounts, found ${accounts:-none}" >&2; exit 1; }
[ "${owner_rows:-0}" -ge 1 ] || { echo "harness owner holds no owner membership" >&2; exit 1; }
[ "${threads:-0}" -gt 0 ] || { echo "no threads seeded" >&2; exit 1; }
log "harness OK: 3 accounts, owner membership present, $threads threads"

log "done"
