#!/bin/bash
set -euo pipefail

# NetBox runtime setup for Cloudron:
#   1. create the persistent data dirs (media / reports / scripts — the
#      image paths are build-time symlinks into /app/data)
#   2. persist the Django SECRET_KEY (>= 50 chars; rotating it invalidates
#      sessions and encrypted values)
#   3. map the Cloudron addon + platform env onto the image's env-driven
#      configuration (netbox-docker configuration/configuration.py):
#      DB_* from postgresql, REDIS[_CACHE]_* from redis, OIDC from the
#      platform OIDC provider
#   4. background the RQ worker (gated on the web port so it only starts
#      after the entrypoint's migrations), then exec the upstream
#      entrypoint chain, which waits for the DB, migrates, and hands over
#      to Granian on :8080
#
# Authentication: SSO via the Cloudron platform OIDC provider
# (REMOTE_AUTH_BACKEND = OpenIdConnectAuth + SOCIAL_AUTH_OIDC_*). The
# local Django login stays available on /login/ for admin bootstrap;
# SSO-registered users are created WITHOUT privileges (see README).

DATA_DIR="/app/data"
SECRET_FILE="${DATA_DIR}/.secret_key"

# --- 1. persistent data directories -------------------------------------------
mkdir -p "${DATA_DIR}/media" "${DATA_DIR}/reports" "${DATA_DIR}/scripts"

# --- 2. persistent SECRET_KEY --------------------------------------------------
# hex on purpose: 64 chars, comfortably over NetBox's 50-char minimum
if [[ ! -s "${SECRET_FILE}" ]]; then
  ( umask 077; head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "${SECRET_FILE}" )
  echo "Generated new NetBox secret key"
fi
export SECRET_KEY="$(cat "${SECRET_FILE}")"

# --- 3. Cloudron -> netbox-docker environment -----------------------------------
export DB_HOST="${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1}"
export DB_PORT="${CLOUDRON_POSTGRESQL_PORT:-5432}"
export DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE:-netbox}"
export DB_USER="${CLOUDRON_POSTGRESQL_USERNAME:-netbox}"
export DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD:-}"

# one Cloudron redis instance, two logical databases (upstream convention:
# tasks on 0, caching on 1)
export REDIS_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}"
export REDIS_PORT="${CLOUDRON_REDIS_PORT:-6379}"
export REDIS_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}"
export REDIS_DATABASE=0
export REDIS_CACHE_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}"
export REDIS_CACHE_PORT="${CLOUDRON_REDIS_PORT:-6379}"
export REDIS_CACHE_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}"
export REDIS_CACHE_DATABASE=1

# hosts / CSRF: Cloudron terminates TLS at the platform proxy
export ALLOWED_HOSTS="${CLOUDRON_APP_DOMAIN:-localhost} localhost"
export CSRF_TRUSTED_ORIGINS="${CLOUDRON_APP_ORIGIN:-http://localhost}"

# first admin is created by the operator via the Cloudron terminal
# (README): the entrypoint's own superuser seeding is skipped
export SKIP_SUPERUSER=true

# operator knobs (see .env.example)
export TIME_ZONE="${NETBOX_TIME_ZONE:-UTC}"
export GRANIAN_WORKERS="${NETBOX_GRANIAN_WORKERS:-4}"
export METRICS_ENABLED="${NETBOX_METRICS_ENABLED:-false}"

# --- 3b. platform OIDC provider -> python-social-auth ---------------------------
# social-core needs the issuer base URL WITH a trailing slash for
# .well-known/openid-configuration discovery
OIDC_ISSUER="${CLOUDRON_OIDC_ISSUER:-}"
OIDC_ISSUER="${OIDC_ISSUER%/}/"
export REMOTE_AUTH_BACKEND='social_core.backends.open_id_connect.OpenIdConnectAuth'
export SOCIAL_AUTH_OIDC_OIDC_ENDPOINT="${OIDC_ISSUER}"
export SOCIAL_AUTH_OIDC_KEY="${CLOUDRON_OIDC_CLIENT_ID:-}"
export SOCIAL_AUTH_OIDC_SECRET="${CLOUDRON_OIDC_CLIENT_SECRET:-}"
export SOCIAL_AUTH_OIDC_SCOPE='openid profile email'
export LOGOUT_REDIRECT_URL="${CLOUDRON_APP_ORIGIN:-/}"

# --- 4. RQ worker + upstream entrypoint -----------------------------------------
# wait for the addons FIRST: netbox-docker's entrypoint gives up on the DB
# after only DB_WAIT_TIMEOUT=30s, which can lose the race with a cold
# Cloudron postgres addon
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"
}

wait_tcp "${DB_HOST}" "${DB_PORT}" "PostgreSQL"
wait_tcp "${REDIS_HOST}" "${REDIS_PORT}" "Redis"

# The worker must not run before the schema exists; Granian answering on
# 8080 is the signal that docker-entrypoint.sh finished migrating.
(
  until (exec 3<>/dev/tcp/127.0.0.1/8080) 2>/dev/null; do sleep 2; done
  echo "web port is up - starting RQ worker"
  exec python3 /opt/netbox/netbox/manage.py rqworker
) &

echo "Starting NetBox (migrations run automatically, then Granian binds :8080) ..."
exec /opt/netbox/docker-entrypoint.sh /opt/netbox/launch-netbox.sh
