#!/bin/sh
# Open Continuity: unlock the vault, start the app, open the browser (charter §10, ADR-006 §1).
#
#   tools/start
#
# Server mode (CONTINUITY_REMOTE=continuity@host): the vault is unlocked on the server over
# SSH (the secret is decrypted here, with your vault code), then the app there is started.
# Local mode: the vault is unlocked on this computer, and the record index (a container)
# and the app run here until tools/stop, or until the vault locks itself when idle.
#
# By hand, without this script: START-HERE 5.7.
. "$(dirname "$0")/lib.sh"
tools=$(cd "$(dirname "$0")" && pwd)

show_code() {
    [ -n "$1" ] || return 0
    say "there is no sign-in code yet. In the browser, enter this one-time code:"
    printf '\n        %s\n\n' "$1" >&2
}

open_browser() {
    say "open $1"
    if command -v xdg-open >/dev/null 2>&1; then xdg-open "$1" >/dev/null 2>&1 || true
    elif command -v open >/dev/null 2>&1; then open "$1" || true
    fi
}

"$tools/unlock"

if [ -n "$CONTINUITY_REMOTE" ]; then
    [ -n "${CONTINUITY_URL:-}" ] || die "set CONTINUITY_URL=https://<your domain> in $CONTINUITY_CONFIG"
    # An old one-time code (the app stopped while locked) must not be shown as the new one.
    ssh "$CONTINUITY_REMOTE" "rm -f \"$CONTINUITY_REMOTE_DATA/mnt/c1/app/setup-code.txt\""
    ssh "$CONTINUITY_REMOTE" 'sudo -n systemctl start continuity.service' \
        || die "could not start the app on $CONTINUITY_REMOTE (see: journalctl -u continuity)"
    say "starting (this takes about half a minute)"
    # Ready: the port answers, and the app has either a sign-in code or a setup code in the vault.
    ssh "$CONTINUITY_REMOTE" "d=\"$CONTINUITY_REMOTE_DATA/mnt/c1/app\"; i=0
        until [ \"\$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:8437/api/session)\" != 000 ] \
              && { [ -e \"\$d/setup-code.txt\" ] || [ -e \"\$d/sign-in.json\" ]; }; do
            i=\$((i + 1)); [ \$i -lt 120 ] || exit 1; sleep 1
            systemctl is-active -q continuity.service || exit 1
        done" || die "the app did not start (see: journalctl -u continuity on the server)"
    show_code "$(ssh "$CONTINUITY_REMOTE" "cat \"$CONTINUITY_REMOTE_DATA/mnt/c1/app/setup-code.txt\" 2>/dev/null" || true)"
    open_browser "$CONTINUITY_URL"
    exit 0
fi

# Local mode.
: "${CONTINUITY_JAVA:=java}"
: "${CONTINUITY_JAR:=$HOME/continuity/continuity.jar}"
need "$CONTINUITY_JAVA" curl
[ -r "$CONTINUITY_JAR" ] || die "cannot read the app: $CONTINUITY_JAR (set CONTINUITY_JAR in $CONTINUITY_CONFIG)"
engine=${CONTINUITY_CONTAINER:-$(command -v podman || command -v docker || true)}
[ -n "$engine" ] || die "missing tool 'podman' or 'docker' (for the record index)"
run=${XDG_RUNTIME_DIR:-$CONTINUITY_DATA}/continuity
mkdir -p "$run" && chmod 0700 "$run"

if [ -f "$run/app.pid" ] && kill -0 "$(cat "$run/app.pid")" 2>/dev/null; then
    say "already running"
    open_browser http://localhost:8437
    exit 0
fi

# The index: RAM only, loopback only, a new random password every time (ADR-006 §2).
umask 077
pw=$(random_secret)
printf 'POSTGRES_PASSWORD=%s\n' "$pw" > "$run/index.pg.env"
"$engine" rm -f continuity-index >/dev/null 2>&1 || true
"$engine" run -d --rm --name continuity-index \
    -e POSTGRES_DB=continuity -e POSTGRES_USER=continuity --env-file "$run/index.pg.env" \
    -p 127.0.0.1:5437:5432 --tmpfs /var/lib/postgresql:rw,size=512m \
    "${CONTINUITY_INDEX_IMAGE:-docker.io/library/postgres:18-alpine}" >/dev/null \
    || die "could not start the record index"
rm -f "$run/index.pg.env"
i=0
until "$engine" exec continuity-index pg_isready -q -h 127.0.0.1 -U continuity; do
    i=$((i + 1)); [ $i -lt 60 ] || die "the record index did not start"; sleep 1
done

# The app. When it stops (tools/stop, or the vault locked itself), the index goes too.
(
    SPRING_DATASOURCE_PASSWORD=$pw "$CONTINUITY_JAVA" -Xmx512m -XX:-HeapDumpOnOutOfMemoryError \
        -jar "$CONTINUITY_JAR" --continuity.vault.root="$MNT" > "$run/app.log" 2>&1 &
    echo $! > "$run/app.pid"
    wait $! || true
    "$engine" rm -f continuity-index >/dev/null 2>&1 || true
    rm -f "$run/app.pid"
) </dev/null >/dev/null 2>&1 &    # detached: must not hold the caller's terminal or pipe open

say "starting (this takes about half a minute)"
i=0
until [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8437/api/session)" = 200 ]; do
    i=$((i + 1))
    # The pid file appears a moment after the start; gone later means the app stopped.
    if [ $i -ge 120 ] || { [ $i -gt 5 ] && [ ! -f "$run/app.pid" ]; }; then die "the app did not start; see $run/app.log"; fi
    sleep 1
done
show_code "$(grep -oE '[2-9A-Z]{4}-[2-9A-Z]{4}-[2-9A-Z]{4}' "$run/app.log" | head -n 1 || true)"
open_browser http://localhost:8437
