#!/bin/sh
# Copyright (c) 2026 Athan Clark. SPDX-License-Identifier: GPL-3.0-only
# First install: create the system user, the configuration, the PostgreSQL role and database
# (with pgmp), run the migration and start the server. Upgrades: leave the configuration and
# database alone, and advise on both; the server stays stopped until openchronology-migrate.
set -e
PG_MAJOR=@PG_MAJOR@
APP=/usr/lib/openchronology
CONFIG_DIR=/etc/openchronology
CONFIG=$CONFIG_DIR/openchronology.env
EXAMPLES=/usr/share/openchronology
DOCS=/usr/share/doc/openchronology-server/README.Debian

[ "$1" = configure ] || exit 0
previous=${2:-}
systemd=
[ -d /run/systemd/system ] && systemd=1

if ! getent passwd openchronology >/dev/null; then
  adduser --system --group --home /var/lib/openchronology --no-create-home \
    --comment "OpenChronology server" openchronology >/dev/null
fi
install -d -m 0750 -o openchronology -g openchronology /var/lib/openchronology
install -d -m 0750 -o root -g openchronology "$CONFIG_DIR"

# The PostgreSQL cluster this package's pgmp was built for, and its port.
cluster_port() {
  pg_lsclusters -h 2>/dev/null | awk -v v="$PG_MAJOR" '$1 == v && $2 == "main" { print $3; exit }'
}
port=$(cluster_port)
[ -n "$port" ] || port=5432

# Configuration files are created once and then belong to the administrator: upgrades never
# rewrite them (each version's templates stay in /usr/share/openchronology to compare).
new_config() {
  [ -e "$1" ] && return 0
  sed "$2" "$3" >"$1.dpkg-new"
  chown root:openchronology "$1.dpkg-new"
  chmod 0640 "$1.dpkg-new"
  mv "$1.dpkg-new" "$1"
}
key=$(od -An -tx1 -N32 /dev/urandom | tr -d ' \n')
url="postgresql:///openchronology?host=/var/run/postgresql"
[ "$port" = 5432 ] || url="$url\\&port=$port"
new_config "$CONFIG" "s|^AUTH_ENCRYPTION_KEY=\$|AUTH_ENCRYPTION_KEY=$key|; s|^DATABASE_URL=.*|DATABASE_URL=$url|" \
  "$EXAMPLES/openchronology.env.example"
new_config "$CONFIG_DIR/syslog.env" "" "$EXAMPLES/syslog.env.example"
new_config "$CONFIG_DIR/journald.env" "" "$EXAMPLES/journald.env.example"

[ -n "$systemd" ] && systemctl daemon-reload

# PostgreSQL may not be running yet (for example in a container without systemd, where its
# package could not start it).
psql_as_postgres() { runuser -u postgres -- psql -X -q -p "$port" -v ON_ERROR_STOP=1 "$@"; }
if ! psql_as_postgres -Atc 'SELECT 1' >/dev/null 2>&1; then
  [ -n "$systemd" ] && systemctl start postgresql >/dev/null 2>&1 || true
  pg_ctlcluster "$PG_MAJOR" main start >/dev/null 2>&1 || true
  for _ in $(seq 30); do
    psql_as_postgres -Atc 'SELECT 1' >/dev/null 2>&1 && break
    sleep 1
  done
fi
running=
psql_as_postgres -Atc 'SELECT 1' >/dev/null 2>&1 && running=1
# An installed database is upgraded by the administrator (openchronology-migrate); one that
# is missing (a first install, or one that could not reach PostgreSQL) is created now.
installed=
if [ -n "$previous" ]; then
  installed=1
  [ -n "$running" ] &&
    [ -z "$(psql_as_postgres -Atc "SELECT 1 FROM pg_database WHERE datname='openchronology'")" ] &&
    installed=
fi
if [ -n "$installed" ]; then
  # Settings the new template has that this installation's configuration does not.
  missing=$(sed -n 's/^\([A-Z][A-Z0-9_]*\)=.*/\1/p' "$EXAMPLES/openchronology.env.example" |
    while read -r name; do grep -q "^$name=" "$CONFIG" || echo "  $name"; done)
  cat <<EOF

OpenChronology $(dpkg-query -W -f='${Version}' openchronology-server) is installed over $previous.
Upgrades stop the server; it starts again once the database is migrated to this version:

  1. Review the configuration in $CONFIG against this version's template:
       diff -u $CONFIG $EXAMPLES/openchronology.env.example
EOF
  if [ -n "$missing" ]; then
    echo "     New settings to consider (their defaults apply until you add them):"
    echo "$missing" | sed 's/^/     /'
  fi
  cat <<EOF
  2. Back up the database:   sudo -u postgres pg_dump -p $port openchronology > openchronology.sql
  3. Migrate and restart:    sudo openchronology-migrate

See $DOCS.

EOF
  exit 0
fi

if [ -z "$running" ]; then
  cat <<EOF

OpenChronology is installed, but PostgreSQL $PG_MAJOR (cluster "main", port $port) is not
running, so the database was not created. Start it, then finish the setup:

  sudo pg_ctlcluster $PG_MAJOR main start
  sudo dpkg-reconfigure openchronology-server

See $DOCS.

EOF
  exit 0
fi
if [ -z "$(psql_as_postgres -Atc "SELECT 1 FROM pg_roles WHERE rolname='openchronology'")" ]; then
  psql_as_postgres -c 'CREATE ROLE openchronology LOGIN'
fi
if [ -z "$(psql_as_postgres -Atc "SELECT 1 FROM pg_database WHERE datname='openchronology'")" ]; then
  psql_as_postgres -c 'CREATE DATABASE openchronology OWNER openchronology'
fi
# pgmp is not a trusted extension: the superuser creates it once for the application's role.
psql_as_postgres -d openchronology -c 'CREATE EXTENSION IF NOT EXISTS pgmp'
openchronology-migrate --no-restart
if [ -n "$systemd" ]; then
  systemctl enable --quiet openchronology.service
  systemctl restart openchronology.service
fi
origin=$(sed -n 's/^APP_ORIGIN=//p' "$CONFIG")
state="ready (start it with the openchronology service)"
[ -n "$systemd" ] && state="running"
cat <<EOF

OpenChronology is installed and $state at $origin.

Next steps:
  - Set APP_ORIGIN, email, an administrator and sign-in providers in $CONFIG,
    then: sudo openchronology-migrate (creates the administrator) or
          sudo systemctl restart openchronology
  - Put an HTTPS reverse proxy in front of it for public use.
  - Back up AUTH_ENCRYPTION_KEY from $CONFIG separately from the database.

See $DOCS.

EOF
