function post_install() {
#!/bin/sh
set -e

INSTALL_DIR=/opt/britive-broker
CONFIG_FILE="${INSTALL_DIR}/config/broker-config.yml"

# ---------------------------------------------------------------------------
# 1. File ownership / permissions (always — fresh install + upgrade alike).
# ---------------------------------------------------------------------------
chown britivebroker:britivebroker "${INSTALL_DIR}/britive-broker"
chmod 750 "${INSTALL_DIR}/britive-broker"

if [ -d "${INSTALL_DIR}/config" ]; then
    chown root:britivebroker "${INSTALL_DIR}/config"/*
    chmod 640 "${INSTALL_DIR}/config"/*
fi

if [ -d "${INSTALL_DIR}/bootstrap" ]; then
    chown -R root:britivebroker "${INSTALL_DIR}/bootstrap/"
    chmod -R 750 "${INSTALL_DIR}/bootstrap/"
fi

if [ -d "${INSTALL_DIR}/cache" ]; then
    chown britivebroker:britivebroker "${INSTALL_DIR}/cache/"
    chmod -R 750 "${INSTALL_DIR}/cache/"
fi

# Pre-create the log files with britivebroker ownership so the service can
# write to them. systemd's `StandardOutput=append:` would create the file
# itself (as root, before dropping privileges), so this is a no-op for
# systemd. OpenRC's start-stop-daemon, however, drops privileges *before*
# opening the redirect target — without a pre-existing writable file, the
# service start fails with "Permission denied" on /var/log/britive-broker*
# because /var/log is owned root:root 0755 and britivebroker can't create
# new files there. Creating + chowning here keeps the package self-
# consistent across all four packagers.
for log in /var/log/britive-broker.log /var/log/britive-broker_error.log; do
    touch "${log}"
    chown britivebroker:britivebroker "${log}"
    chmod 0640 "${log}"
done

# ---------------------------------------------------------------------------
# 2. Detect fresh install vs upgrade.
# ---------------------------------------------------------------------------
# RPM postinstall:        $1=1 install, $1=2 upgrade
# DEB postinst:           $1=configure $2=<old-version> on upgrade ($2 empty on fresh)
# APK post-install:       no args (only fires on fresh install)
# archlinux post_install: $1=new-version (only fires on fresh install)
# APK post-upgrade and arch post_upgrade route through postupgrade.sh, not here.
is_fresh_install=1
case "$1" in
    2) is_fresh_install=0 ;;
esac
if [ "$1" = "configure" ] && [ -n "$2" ]; then
    is_fresh_install=0
fi

# ---------------------------------------------------------------------------
# 3a. Upgrade path: refresh systemd unit view + try-restart if active. No
# config substitution, no auto-enable — preserves the operator's existing
# config and service-enabled intent across upgrades.
# ---------------------------------------------------------------------------
if [ "${is_fresh_install}" = "0" ]; then
    if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
        systemctl daemon-reload >/dev/null 2>&1 || true
        systemctl try-restart britive-broker.service >/dev/null 2>&1 || true
    fi
    # OpenRC equivalent (rare here — apk upgrades go through postupgrade.sh —
    # but harmless if some future packager wires this script as the upgrade hook).
    if command -v rc-service >/dev/null 2>&1 && [ -f /etc/init.d/britive-broker ]; then
        if rc-service britive-broker status >/dev/null 2>&1; then
            rc-service britive-broker restart >/dev/null 2>&1 || true
        fi
    fi
    exit 0
fi

# ---------------------------------------------------------------------------
# 3b. Fresh install: collect tenant_subdomain + authentication_token,
# substitute into broker-config.yml, then enable+start the service. This
# script is fully non-interactive — no /dev/tty prompt, no debconf
# question. It conforms to the rpm / apk / pacman convention that
# scriptlets must not prompt, and uses env vars / a sentinel env file as
# the configuration channel uniformly across all four packagers.
#
# Value sources, in priority order:
#   1. /etc/britive-broker/install.env — sourced first if present. Lets
#      Alpine operators (where apk-tools strips the scriptlet env) and
#      anyone preferring a uniform contract supply the same
#      BRITIVE_BROKER_* keys via a 0600 KEY=value file.
#   2. Env vars BRITIVE_BROKER_TENANT_SUBDOMAIN plus either
#      BRITIVE_BROKER_AUTH_TOKEN (literal token) or
#      BRITIVE_BROKER_AUTH_TOKEN_GENERATOR (path to a script that prints
#      the broker pool token on stdout). Names match the broker's own
#      runtime config-override env vars; safe for Ansible / cloud-init /
#      Dockerfile flows. AUTH_TOKEN wins if both are set, matching the
#      runtime precedence in
#      internal/config/config.go:resolveTokenPrecedence.
#
# If neither source yields the values we need, we leave the placeholders
# in place, print a clear message telling the operator how to finish the
# setup, and exit 0. The package install still succeeds — failing the
# install would break automated deploys that intentionally configure
# post-install.
# ---------------------------------------------------------------------------

# Sentinel env file. Operators (especially on Alpine, where apk-tools v2
# strips the scriptlet environment so direct BRITIVE_BROKER_* exports do not
# reach this script) can drop a `KEY=value` file at /etc/britive-broker/install.env
# before invoking the package manager. Sourcing it here makes those values
# visible to the rest of the postinstall as if they had been exported.
#
# Single-step parity with deb / rpm / archlinux for Ansible / Puppet / Chef /
# cloud-init flows on Alpine: the recipe drops the env file, runs `apk add`,
# postinstall sources it, substitution + service start proceed identically to
# the other packagers. Also works as a uniform automation contract on the
# other packagers — operators who prefer not to plumb env vars through their
# CM tool's `environment:` block can use the file instead.
#
# Recognized keys: BRITIVE_BROKER_TENANT_SUBDOMAIN, BRITIVE_BROKER_AUTH_TOKEN,
# BRITIVE_BROKER_AUTH_TOKEN_GENERATOR. Values set here win over inherited
# environment because the file is sourced before the parameter expansions
# below — matches the /etc/default/<service> convention.
#
# Permission hygiene: warn if the file is more permissive than 0600 since it
# likely contains the broker token; we do not abort because that would be
# more disruptive than the perms risk. Operators should chmod 0600 the file
# and remove it after a successful install.
INSTALL_ENV_FILE=/etc/britive-broker/install.env
if [ -f "${INSTALL_ENV_FILE}" ]; then
    perms=$(stat -c '%a' "${INSTALL_ENV_FILE}" 2>/dev/null || true)
    if [ -n "${perms}" ] && [ "${perms}" != "600" ] && [ "${perms}" != "400" ]; then
        echo "Warning: ${INSTALL_ENV_FILE} has mode ${perms}; recommend 0600 to protect the broker token." >&2
    fi
    # shellcheck disable=SC1090,SC1091
    . "${INSTALL_ENV_FILE}"
fi

[ ! -f "${CONFIG_FILE}" ] && exit 0

tenant="${BRITIVE_BROKER_TENANT_SUBDOMAIN:-}"
token="${BRITIVE_BROKER_AUTH_TOKEN:-}"
token_generator="${BRITIVE_BROKER_AUTH_TOKEN_GENERATOR:-}"

# Mirror the broker's runtime mutual-exclusion: if both are supplied, the
# literal token wins and we discard the generator path so the config file
# ends up with a single, unambiguous bootstrap entry.
if [ -n "${token}" ]; then
    token_generator=""
fi

# Note: apk-tools v2 sanitizes the scriptlet environment, so
# BRITIVE_BROKER_TENANT_SUBDOMAIN / BRITIVE_BROKER_AUTH_TOKEN /
# BRITIVE_BROKER_AUTH_TOKEN_GENERATOR exported by the operator do NOT
# reach this script during `apk add`. dpkg, rpm, and pacman pass env
# vars through. Alpine operators have two supported automation paths:
# (a) drop /etc/britive-broker/install.env before `apk add` — the
# env-file probe above sources it into this script's environment, giving
# deb/rpm parity; or (b) install the package, edit
# /opt/britive-broker/config/broker-config.yml, then start the service
# manually.
if [ -n "${tenant}" ] && { [ -n "${token}" ] || [ -n "${token_generator}" ]; }; then
    # Escape characters that would be interpreted by sed's replacement string
    # (\, &, and the chosen delimiter #). Any of these in a token (or in a
    # token-generator path) would otherwise mangle the substitution silently.
    esc_tenant=$(printf '%s' "${tenant}" | sed 's/[\\&#]/\\&/g')
    sed -i -e "s#<tenant_subdomain>#${esc_tenant}#" "${CONFIG_FILE}"

    if [ -n "${token}" ]; then
        esc_token=$(printf '%s' "${token}" | sed 's/[\\&#]/\\&/g')
        sed -i -e "s#<authentication_token>#${esc_token}#" "${CONFIG_FILE}"
    else
        # Rewrite the `authentication_token: <authentication_token>` line into
        # an `authentication_token_generator: <path>` line. The shipped
        # broker-config.yml only carries the literal-token placeholder, so
        # replacing the whole key-value pair is what flips the bootstrap mode.
        esc_gen=$(printf '%s' "${token_generator}" | sed 's/[\\&#]/\\&/g')
        sed -i -e "s#authentication_token: <authentication_token>#authentication_token_generator: ${esc_gen}#" "${CONFIG_FILE}"
    fi

    # Re-tighten permissions on the now-secret-bearing config file. The
    # earlier blanket chmod set 0640 already, but be explicit in case the
    # file was created with different permissions on some packager.
    chown root:britivebroker "${CONFIG_FILE}"
    chmod 0640 "${CONFIG_FILE}"

    # Enable + start the service. Mirrors the Windows MSI which sets the
    # service to Automatic startup and starts it as part of install.
    if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
        systemctl daemon-reload >/dev/null 2>&1 || true
        systemctl enable --now britive-broker.service >/dev/null 2>&1 || true
    elif command -v rc-update >/dev/null 2>&1 && [ -f /etc/init.d/britive-broker ]; then
        rc-update add britive-broker default >/dev/null 2>&1 || true
        rc-service britive-broker start >/dev/null 2>&1 || true
    fi
else
    cat <<'EOF' >&2

Britive broker is installed but not yet configured.  No tenant subdomain or
broker pool authentication token was supplied to the postinstall script.

To finish setup, either:

  (a) Edit /opt/britive-broker/config/broker-config.yml and replace the
      placeholders <tenant_subdomain> and <authentication_token> with your
      tenant subdomain and broker pool authentication token, then enable
      and start the service:

        # systemd (RHEL, Debian/Ubuntu, Arch Linux):
        systemctl enable --now britive-broker.service

        # OpenRC (Alpine):
        rc-update add britive-broker default
        rc-service britive-broker start

  (b) Reinstall the package with values supplied via the environment:

        - export BRITIVE_BROKER_TENANT_SUBDOMAIN together with
          BRITIVE_BROKER_AUTH_TOKEN or BRITIVE_BROKER_AUTH_TOKEN_GENERATOR
          before invoking the package manager (works on rpm, deb, and
          archlinux); or

        - drop a KEY=value file at /etc/britive-broker/install.env (mode
          0600) containing the same variables. The postinstall script
          sources it before running. This is the supported automation
          path on Alpine, where apk-tools strips env vars from package
          scriptlets.

If you want to install the package now and configure the broker in a
later step, simply install with no BRITIVE_BROKER_* values supplied --
this is that state.

EOF
fi

exit 0

}

function post_upgrade() {
#!/bin/sh
set -e

# Post-upgrade hook for apk and archlinux. RPM/DEB run postinstall.sh on
# upgrade and detect the upgrade phase via $1, but apk and archlinux split
# install vs upgrade into separate hooks (post-install vs post-upgrade /
# post_install vs post_upgrade), so we use this dedicated script to make the
# upgrade flow unambiguous: re-apply ownership/permissions in case the new
# package version added or moved files, then try-restart the service if it
# was already running. We deliberately do NOT re-prompt for credentials, run
# placeholder substitution, or auto-enable the service — those belong to
# the fresh-install path in postinstall.sh.

INSTALL_DIR=/opt/britive-broker

chown britivebroker:britivebroker "${INSTALL_DIR}/britive-broker"
chmod 750 "${INSTALL_DIR}/britive-broker"

if [ -d "${INSTALL_DIR}/config" ]; then
    chown root:britivebroker "${INSTALL_DIR}/config"/*
    chmod 640 "${INSTALL_DIR}/config"/*
fi

if [ -d "${INSTALL_DIR}/bootstrap" ]; then
    chown -R root:britivebroker "${INSTALL_DIR}/bootstrap/"
    chmod -R 750 "${INSTALL_DIR}/bootstrap/"
fi

if [ -d "${INSTALL_DIR}/cache" ]; then
    chown britivebroker:britivebroker "${INSTALL_DIR}/cache/"
    chmod -R 750 "${INSTALL_DIR}/cache/"
fi

# systemd path (archlinux upgrades).
if [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
    systemctl daemon-reload >/dev/null 2>&1 || true
    systemctl try-restart britive-broker.service >/dev/null 2>&1 || true
fi

# OpenRC path (Alpine apk upgrades).
if command -v rc-service >/dev/null 2>&1 && [ -f /etc/init.d/britive-broker ]; then
    if rc-service britive-broker status >/dev/null 2>&1; then
        rc-service britive-broker restart >/dev/null 2>&1 || true
    fi
fi

exit 0

}

function pre_install() {
#!/bin/sh
set -e

# Create the britivebroker system user/group if it does not already exist.
# Alpine ships only BusyBox adduser/addgroup, which use a different flag set
# (-S/-D/-H, no --system/--group), so detect Alpine first and branch on it
# before the generic useradd/adduser fallbacks used by RHEL/SUSE/Arch and
# Debian/Ubuntu respectively.
if ! getent passwd britivebroker >/dev/null 2>&1; then
    if [ -f /etc/alpine-release ]; then
        addgroup -S britivebroker 2>/dev/null || true
        adduser -S -D -H -s /sbin/nologin -G britivebroker britivebroker
    elif command -v useradd >/dev/null 2>&1; then
        useradd --system --user-group --no-create-home --shell /usr/sbin/nologin britivebroker
    elif command -v adduser >/dev/null 2>&1; then
        adduser britivebroker --system --group --no-create-home
    else
        echo "No supported user-creation tool found; cannot create britivebroker user." >&2
        exit 1
    fi
fi

exit 0

}

function pre_remove() {
#!/bin/sh
set -e

# Stop the service before package files are removed. On RPM/DEB upgrades this
# script also runs (with arg=1 / "upgrade"), but in that case we deliberately
# leave the service alone — postinstall handles the restart, which avoids a
# pointless stop/start cycle and keeps in-flight broker requests from being
# interrupted twice.
#
# On apk and archlinux, this script is wired only to the real-uninstall hook
# (pre-deinstall / pre_remove) by nfpm — upgrades go through separate
# pre/post-upgrade hooks — so $1 is empty there and is_upgrade stays 0,
# which is the desired behavior on Alpine and Arch uninstall paths.

is_upgrade=0

# RPM passes "$1": 0 for true uninstall, 1 for upgrade.
case "$1" in
    1) is_upgrade=1 ;;
esac

# DEB passes a string action ("remove", "upgrade", "deconfigure", ...).
case "$1" in
    upgrade|deconfigure) is_upgrade=1 ;;
esac

if [ "${is_upgrade}" = "0" ] && [ -d /run/systemd/system ] && command -v systemctl >/dev/null 2>&1; then
    systemctl stop britive-broker.service >/dev/null 2>&1 || true
    systemctl disable britive-broker.service >/dev/null 2>&1 || true
fi

# OpenRC equivalent for Alpine apk uninstalls.
if [ "${is_upgrade}" = "0" ] && command -v rc-service >/dev/null 2>&1 && [ -f /etc/init.d/britive-broker ]; then
    rc-service britive-broker stop >/dev/null 2>&1 || true
    rc-update del britive-broker >/dev/null 2>&1 || true
fi

exit 0

}

