#!/bin/bash
#
# Update convoro.co.
#
# This is docs/deploy/production.md turned into the script it asks for at the
# bottom: *"Everything above is six commands that never vary; the reason they
# are a document rather than a script is only that the release was going out
# the same afternoon."*
#
# 🚨 It is a GIT pull, not an rsync. Production is a checkout whose origin is
# `file:///var/www/convoro-dev` — the dev checkout on the same box, which
# itself pulls from GitHub every minute on a timer. So the chain is
#
#     GitHub  ->  dev (automatic)  ->  production (this script)
#
# and production is never more than a `git reset` behind something that has
# already proved it boots. An rsync from a laptop would fight that checkout and
# lose the property that makes it safe.
#
#   tools/deploy-prod            check only: what is live, what is waiting
#   tools/deploy-prod --yes      back up, pull, migrate, verify
#   tools/deploy-prod --rollback go back to the commit that was live before
#
set -euo pipefail

HOST=${CONVORO_PROD_HOST:-root@103.195.100.103}
DIR=${CONVORO_PROD_DIR:-/var/www/convoro2}
DEV=${CONVORO_DEV_DIR:-/var/www/convoro-dev}
SITE=${CONVORO_PROD_URL:-https://convoro.co}

# Where the commit that was live gets written, so --rollback has something to
# go back TO. A rollback that has to be reconstructed from memory at the moment
# it is needed is not a rollback.
WAS=/root/convoro2-was.txt

# ---- rollback ----------------------------------------------------------

if [ "${1:-}" = "--rollback" ]; then
    ssh "$HOST" bash -s -- "$DIR" "$WAS" <<'REMOTE'
set -euo pipefail
dir=$1; was=$2
test -s "$was" || { echo "No recorded previous commit at $was. Nothing to roll back to."; exit 1; }
cd "$dir"
echo "→ back to $(cat "$was")"
git reset --hard "$(cat "$was")"
sudo -u www-data php tools/convoro cache:clear
REMOTE
    echo
    echo "🚨 The DATABASE was not touched. If the deploy ran migrations, restore"
    echo "   the dump it took — migrations are the only part a git reset cannot undo."
    exit 0
fi

# ---- what is live, and what is waiting ---------------------------------

echo "→ ${SITE}  (${HOST}:${DIR})"

ssh "$HOST" bash -s -- "$DIR" "$DEV" <<'REMOTE'
set -euo pipefail
dir=$1; dev=$2

live=$(cd "$dir" && git log --format=%h -1)
livev=$(grep -m1 'VERSION = ' "$dir/engine/Convoro.php" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')
devc=$(cd "$dev" && git log --format=%h -1)
devv=$(grep -m1 'VERSION = ' "$dev/engine/Convoro.php" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')

echo "   live        ${livev}  ${live}"
echo "   dev has     ${devv}  ${devc}"

if [ "$live" = "$devc" ]; then
    echo "   nothing to do — production is already on what dev has."
fi
REMOTE

if [ "${1:-}" != "--yes" ]; then
    echo
    echo "→ Nothing changed. Pass --yes to deploy."
    echo
    echo "  🚨 Check the dev commit above is the one you mean. Production pulls"
    echo "     from the dev checkout, and dev takes up to a minute to see a push."
    exit 0
fi

# ---- do it -------------------------------------------------------------

ssh "$HOST" bash -s -- "$DIR" "$WAS" <<'REMOTE'
set -euo pipefail
dir=$1; was=$2
cd "$dir"

#
# 1. Back it up, and VERIFY the backup is readable.
#
# 🚨 `gzip -t`, not just "the file exists". Migrations are the only part of a
# deploy that pulling the old commit back cannot undo, so this dump is the only
# way out of a bad one — and a corrupt dump discovered at that moment is the
# same as no dump. Verified here, while there is still nothing wrong.
#
# 🚨 DB_PASS, not DB_PASSWORD. That is what this install's .env uses; guessing
# the other name yields an empty password and a dump that is 0 bytes, which is
# why the size check below is not decoration.
#
pass=$(grep -E '^DB_PASS=' .env | cut -d= -f2-)
out=/root/convoro_live-pre-$(date +%Y%m%d-%H%M).sql.gz

echo "→ backing up convoro_live"
mysqldump --single-transaction --quick -u convoro_live -p"$pass" convoro_live | gzip > "$out"
gzip -t "$out"
echo "   $(ls -lh "$out" | awk '{print $5}')  $out"

# 2. Remember where we were, before moving.
git log --format=%H -1 > "$was"
echo "→ was $(git log --format=%h -1), keeping that in $was"

# 3. Take the code.
echo "→ pulling"
git fetch origin
git reset --hard origin/master
echo "   now $(git log --format=%h -1)  $(grep -m1 'VERSION = ' engine/Convoro.php | grep -oE '[0-9]+\.[0-9]+\.[0-9]+')"

# 🚨 git runs as root here, so every file it rewrites comes back root-owned —
# and the in-admin updater runs as www-data. CoreUpdater::copyOver() then dies
# on the first file it cannot write, part way through, having already taken its
# backup. That is exactly how the 1.3.10 update failed on 2026-08-14: it looked
# like a broken updater and was a broken deploy.
#
# The whole tree, not just storage and content. The updater overwrites code.
chown -R www-data:www-data "$dir"

# 4. 🚨 The cron script, which the deploy did NOT keep in step and should have.
#
# `tools/deploy/convoro-cron` calls itself the source of truth and is copied to
# /usr/local/bin by hand, so the two drifted — and the drift was invisible,
# because a cron that is missing a line does not fail, it just never does that
# thing. Two jobs had never run on production: the per-module schedule
# (so no extension could run anything on a timer) and tracker:sprint-day
# (so no sprint burndown had ever recorded a day).
#
# Copied on every deploy, with the previous one kept beside it.
if ! cmp -s /usr/local/bin/convoro-cron tools/deploy/convoro-cron 2>/dev/null; then
    echo "→ updating the cron script"
    cp -a /usr/local/bin/convoro-cron "/root/convoro-cron.before-$(date +%Y%m%d-%H%M%S)" 2>/dev/null || true
    install -m 755 tools/deploy/convoro-cron /usr/local/bin/convoro-cron
fi

# 5. As www-data, or you leave root-owned cache files the site cannot replace —
#    which fails later, and somewhere else.
echo "→ migrating"
sudo -u www-data php tools/convoro migrate
sudo -u www-data php tools/convoro cache:clear
REMOTE

# ---- "the deploy finished" and "the site works" are different claims ----

echo "→ checking"

FAILED=""

for p in / /forums /downloads /clubs; do
    code=$(curl -s -o /dev/null -w '%{http_code}' "${SITE}${p}")
    printf '   %-14s %s\n' "$p" "$code"
    [ "$code" = "200" ] || FAILED="yes"
done

if [ -n "$FAILED" ]; then
    echo
    echo "   ✗ the site is not answering. Roll back now:"
    echo "       tools/deploy-prod --rollback"
    exit 1
fi

echo "→ convoro.co is up."
echo
echo "   Roll back with: tools/deploy-prod --rollback"
echo "   Releases are separate — see docs/deploy/production.md for release:publish."
