#!/bin/bash
set -euo pipefail

# ConsulDemocracy runtime setup for Cloudron:
#   1. generate config/database.yml + config/secrets.yml under /app/data
#      (config/* are symlinks; addon creds rotate on restore/migration, so
#      both files are rewritten on EVERY start)
#   2. start memcached (production cache_store is mem_cache_store/dalli)
#   3. wait for the postgresql addon, then create/migrate/seed the DB once
#      (marker file) or just migrate on later boots
#   4. background the delayed_job worker (gated on the web port, so the
#      schema exists first), then exec the Rails server on :3000
#
# Authentication: OIDC via the Cloudron platform provider, mapped into
# secrets.yml (oidc_client_id/secret/issuer). The seeds create a local
# admin (admin@consul.dev / 12345678) - CHANGE ITS PASSWORD on first
# login (see README).

DATA_DIR="/app/data"
SECRET_FILE="${DATA_DIR}/.secret_key_base"
MARKER="${DATA_DIR}/.db_seeded"

cd /var/www/consul

# --- 1. runtime configs (regenerated every boot) -------------------------------
wait_tcp() {
  local host="$1" port="$2" name="$3"
  echo "Waiting for ${name} at ${host}:${port} ..."
  until (exec 3<>"/dev/tcp/${host}/${port}") 2>/dev/null; do
    echo "${name} is unavailable - sleeping"
    sleep 2
  done
  echo "${name} is up"
}

yml_escape() { printf '%s' "$1" | sed -e 's/\\/\\\\/g' -e "s/'/\\\\'/g"; }

if [[ ! -s "${SECRET_FILE}" ]]; then
  ( umask 077; openssl rand -hex 32 > "${SECRET_FILE}" )
  echo "Generated new secret_key_base"
fi
SECRET_KEY_BASE="$(cat "${SECRET_FILE}")"

DB_HOST="${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1}"
DB_PORT="${CLOUDRON_POSTGRESQL_PORT:-5432}"
DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE:-consul}"
DB_USER="${CLOUDRON_POSTGRESQL_USERNAME:-consul}"
DB_PASS="${CLOUDRON_POSTGRESQL_PASSWORD:-}"

cat > "${DATA_DIR}/database.yml" <<EOF
default: &default
  adapter: postgresql
  encoding: unicode
  host: ${DB_HOST}
  port: ${DB_PORT}
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  schema_search_path: "public,shared_extensions"
  username: ${DB_USER}
  password: <%= ENV["PGPASSWORD"] %>

production:
  <<: *default
  database: ${DB_NAME}
EOF
export PGPASSWORD="${DB_PASS}"

OIDC_CLIENT_ID="$(yml_escape "${CLOUDRON_OIDC_CLIENT_ID:-}")"
OIDC_CLIENT_SECRET="$(yml_escape "${CLOUDRON_OIDC_CLIENT_SECRET:-}")"
OIDC_ISSUER="$(yml_escape "${CLOUDRON_OIDC_ISSUER:-}")"
SERVER_NAME="$(yml_escape "${CLOUDRON_APP_DOMAIN:-localhost}")"

cat > "${DATA_DIR}/secrets.yml" <<EOF
# Generated by start.sh on every boot - manual edits will be lost.
shared:
  map_tiles_provider: "//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
  map_tiles_provider_attribution: "OpenStreetMap contributors"

production:
  secret_key_base: ${SECRET_KEY_BASE}
  server_name: ${SERVER_NAME}
  force_ssl: false
  delay_jobs: true
  multitenancy: false
  http_basic_username: ""
  http_basic_password: ""
  authentication_logs: false
  devise_lockable: false
  oidc_client_id: "${OIDC_CLIENT_ID}"
  oidc_client_secret: "${OIDC_CLIENT_SECRET}"
  oidc_issuer: "${OIDC_ISSUER}"
EOF
chmod 600 "${DATA_DIR}/secrets.yml"

# --- 2. memcached (localhost, as upstream's image intends) ----------------------
memcached -d -p 11211 -u consul -m 64

# --- 3. database lifecycle -------------------------------------------------------
wait_tcp "${DB_HOST}" "${DB_PORT}" "PostgreSQL"

# seed decision: the marker alone is not trusted - a marker left by a
# previous database (restore, migration, fresh test DB) must not skip
# seeding an empty one (observed: seed chain exits 0 yet persists
# nothing when re-run in the same first-boot process; a standalone
# re-seed lands fine, so verify + retry instead of debugging ghosts)
SEED_COUNT="$(bundle exec rails runner 'print Setting.count' 2>/dev/null || echo 0)"
if [[ ! -f "${MARKER}" || "${SEED_COUNT}" = "0" ]]; then
  echo "First boot (or empty database): creating + migrating + seeding ..."
  bundle exec rails db:create db:migrate db:seed
  SEED_COUNT="$(bundle exec rails runner 'print Setting.count' 2>/dev/null || echo 0)"
  if [[ "${SEED_COUNT}" = "0" ]]; then
    echo "seed pass 1 did not persist - retrying standalone seed"
    bundle exec rails db:seed
  fi
  touch "${MARKER}"
  echo "Database seeded (local admin: admin@consul.dev - change the password!)"

  # first-boot only: expose the SSO button when the platform provider is
  # wired (feature.oidc_login defaults to false; operators can toggle it
  # later in Admin > Settings > Features without us re-enabling it)
  if [[ -n "${CLOUDRON_OIDC_CLIENT_ID:-}" ]]; then
    bundle exec rails runner 'Setting["feature.oidc_login"] = true' || true
    echo "OIDC login enabled (admin panel can toggle it)"
  fi
else
  bundle exec rails db:migrate
fi

# assets:precompile needs the booted environment (DB-dependent
# initializers), so it runs here - after the PG wait, every boot
# (idempotent: fast no-op when the manifests are current)
bundle exec rails assets:precompile

# --- 4. delayed_job worker + web server ------------------------------------------
# gate on the web port (migrations done) so the worker never races the schema
(
  until (exec 3<>/dev/tcp/127.0.0.1/3000) 2>/dev/null; do sleep 2; done
  echo "web port is up - starting delayed_job worker"
  exec bundle exec rake jobs:work
) &

echo "Starting ConsulDemocracy on :3000 ..."
exec bundle exec rails server -b 0.0.0.0 -p 3000
