#!/bin/bash
# vexor-setup-postgres-bootstrap.sh
#
# Idempotent helper sourced/inserted into /usr/sbin/vexor-setup before the
# Keycloak realm seeding. Ensures:
#   1. PostgreSQL 16 is installed + initialized
#   2. 'keycloak' DB + role exist with a strong random password
#   3. /etc/vexor/keycloak.env carries KC_DB_* env vars (mode 0640 root:keycloak)
#   4. /opt/keycloak/conf/keycloak.conf has the matching db= settings
#   5. /opt/keycloak gets a postgres-aware `kc.sh build`
#
# Safe to re-run: skips any step that's already done.

set -e

say()  { echo -e "\033[0;32m[vexor-setup-pg]\033[0m $*"; }
warn() { echo -e "\033[0;33m[warn]\033[0m $*" >&2; }

# --- 1. Install + init postgres ---
if ! rpm -q postgresql-server >/dev/null 2>&1; then
  say "Installing postgresql-server"
  dnf install -y postgresql-server postgresql-contrib >/dev/null
fi

if [ ! -f /var/lib/pgsql/data/PG_VERSION ]; then
  say "Initializing PostgreSQL data directory"
  postgresql-setup --initdb >/dev/null
fi

# --- 2. pg_hba: add keycloak rules (only once) ---
PG_HBA=/var/lib/pgsql/data/pg_hba.conf
if [ -f "$PG_HBA" ] && ! grep -q "vexor: keycloak local socket" "$PG_HBA"; then
  say "Configuring pg_hba.conf for keycloak"
  cp -n "$PG_HBA" "$PG_HBA.orig"
  {
    echo "# vexor: keycloak local socket access (peer auth)"
    echo "local   keycloak        keycloak                                peer"
    echo "# vexor: keycloak loopback TCP fallback (scram)"
    echo "host    keycloak        keycloak        127.0.0.1/32            scram-sha-256"
    echo "host    keycloak        keycloak        ::1/128                 scram-sha-256"
    cat "$PG_HBA.orig"
  } > "$PG_HBA.new"
  mv "$PG_HBA.new" "$PG_HBA"
  chown postgres:postgres "$PG_HBA"
  chmod 0600 "$PG_HBA"
fi

# --- 3. Enable + start ---
systemctl enable --now postgresql >/dev/null
# Wait for it to be ready
for i in $(seq 1 30); do
  sudo -u postgres psql -tAc "SELECT 1" >/dev/null 2>&1 && break
  sleep 1
done

# --- 4. Create role + DB if missing ---
ROLE_EXISTS=$(sudo -u postgres psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='keycloak'" 2>/dev/null || echo "")
DB_EXISTS=$(sudo -u postgres psql -tAc "SELECT 1 FROM pg_database WHERE datname='keycloak'" 2>/dev/null || echo "")

KC_DB_PW=""
if [ -z "$ROLE_EXISTS" ]; then
  KC_DB_PW=$(openssl rand -base64 30 | tr -d "/+=" | head -c 32)
  say "Creating keycloak role + DB"
  sudo -u postgres psql >/dev/null <<SQL
CREATE USER keycloak WITH PASSWORD '$KC_DB_PW';
SQL
elif [ -z "$DB_EXISTS" ] || ! grep -q "^KC_DB_PASSWORD=" /etc/vexor/keycloak.env 2>/dev/null; then
  # role exists but we have no recorded password -> rotate
  KC_DB_PW=$(openssl rand -base64 30 | tr -d "/+=" | head -c 32)
  say "Rotating keycloak role password (no password on file)"
  sudo -u postgres psql >/dev/null <<SQL
ALTER USER keycloak WITH PASSWORD '$KC_DB_PW';
SQL
else
  KC_DB_PW=$(grep "^KC_DB_PASSWORD=" /etc/vexor/keycloak.env | cut -d= -f2-)
fi

if [ -z "$DB_EXISTS" ]; then
  sudo -u postgres psql >/dev/null <<SQL
CREATE DATABASE keycloak OWNER keycloak ENCODING 'UTF8' TEMPLATE template0;
GRANT ALL PRIVILEGES ON DATABASE keycloak TO keycloak;
SQL
fi

# --- 5. Write KC_DB_* vars to /etc/vexor/keycloak.env ---
KCENV=/etc/vexor/keycloak.env
touch "$KCENV"
# Strip any existing KC_DB_* lines, then append fresh values
grep -v "^KC_DB" "$KCENV" > "$KCENV.tmp" 2>/dev/null || true
cat >> "$KCENV.tmp" <<EOF
KC_DB=postgres
KC_DB_URL=jdbc:postgresql://127.0.0.1:5432/keycloak
KC_DB_USERNAME=keycloak
KC_DB_PASSWORD=$KC_DB_PW
EOF
mv "$KCENV.tmp" "$KCENV"
chown root:keycloak "$KCENV" 2>/dev/null || true
chmod 0640 "$KCENV"

# --- 6. Write /opt/keycloak/conf/keycloak.conf ---
KC_CONF=/opt/keycloak/conf/keycloak.conf
if [ -d /opt/keycloak/conf ]; then
  cat > "$KC_CONF" <<EOF
# Managed by vexor-setup; edits will be overwritten on next run.
db=postgres
db-url=jdbc:postgresql://127.0.0.1:5432/keycloak
db-username=keycloak
db-password=$KC_DB_PW
http-relative-path=/auth
http-enabled=true
http-port=8180
hostname-strict=false
proxy-headers=xforwarded
EOF
  chown root:keycloak "$KC_CONF" 2>/dev/null || true
  chmod 0640 "$KC_CONF"
fi

# --- 7. Run kc.sh build so the postgres driver is baked in ---
if [ -x /opt/keycloak/bin/kc.sh ]; then
  # The build needs write access under /opt/keycloak/lib; easiest to run as root
  CURRENT_DB=$(/opt/keycloak/bin/kc.sh show-config 2>/dev/null | grep "kc.db =" | awk '{print $3}')
  if [ "$CURRENT_DB" != "postgres" ]; then
    say "Building Keycloak with postgres backend"
    (cd /opt/keycloak && bin/kc.sh build 2>&1 | tail -3)
    chown -R keycloak:keycloak /opt/keycloak
  fi
fi

say "Postgres bootstrap done (DB=keycloak, role=keycloak)"
