#!/bin/sh
# initMAX zero-touch post-install for headermax 2.6.0. POSIX sh.
set +e
ID="headermax"; LEGACY_IDS="header"; STAGING="/usr/share/initmax/zabbix-modules/headermax"
log(){ echo "initMAX: $*" >&2; }

# 1. active frontend root (defines.inc.php marker)
FE_ROOT=""
for r in "${ZABBIX_FRONTEND_DIR:-}" /usr/share/zabbix/ui /usr/share/zabbix /usr/share/zabbix/php /srv/www/htdocs/zabbix; do
  [ -n "$r" ] && [ -f "$r/include/defines.inc.php" ] && { FE_ROOT="$r"; break; }
done
[ -z "$FE_ROOT" ] && { log "Zabbix frontend not found - staged in $STAGING, deploy manually."; exit 0; }
MODULES="$FE_ROOT/modules"; DEST="$MODULES/$ID"
ZBXVER=$(grep -oE "'ZABBIX_VERSION'[[:space:]]*,[[:space:]]*'[0-9.]+'" "$FE_ROOT/include/defines.inc.php" 2>/dev/null | grep -oE "[0-9]+\.[0-9]+" | head -1)

# 2. pick module tree for this Zabbix (v1 = 6.0/6.2, v2 = 6.4+) + relative_path
case "$ZBXVER" in
  6.0|6.2) SRC="$STAGING/legacy"; REL="$ID" ;;
  *)       SRC="$STAGING/modern"; REL="modules/$ID" ;;
esac
# Never replace a working tree with an incompatible fallback. The build
# refuses to package a declared 6.0/6.2 target without legacy/, but this
# runtime guard also protects a damaged or manually altered installation.
[ -d "$SRC" ] || { log "compatible module tree missing: $SRC - keeping the current deployment untouched"; exit 0; }
log "Zabbix ${ZBXVER:-?} frontend $FE_ROOT, tree $SRC, relative_path=$REL"

# deploy the chosen tree to the real path (atomic, no symlink)
if [ "$SRC" != "$DEST" ]; then
  mkdir -p "$MODULES"; rm -rf "$DEST.imxnew"; cp -a "$SRC" "$DEST.imxnew"; rm -rf "$DEST"; mv "$DEST.imxnew" "$DEST"
  log "deployed to $DEST"
fi

# 3. ownership + SELinux
OWNER=$(stat -c '%U:%G' "$FE_ROOT/include/defines.inc.php" 2>/dev/null)
[ -n "$OWNER" ] && chown -R "$OWNER" "$DEST" 2>/dev/null
command -v restorecon >/dev/null 2>&1 && restorecon -RF "$DEST" >/dev/null 2>&1

# 3b. Retire a HAND-INSTALLED copy of this very module.
# Before the packages existed, the docs told customers to git-clone the
# widget into modules/, which yields a DIFFERENTLY NAMED directory (e.g.
# modules/zabbix-<id>-widget/) holding the SAME manifest id. The package
# deploys to modules/<id>/, so that clone would survive and Zabbix would
# then list the widget TWICE after a directory scan. Match strictly on the
# manifest id and skip anything the PACKAGE owns:
#   - $DEST                 the copy we just deployed
# Package payloads are outside $MODULES, so only $DEST is exempt here.
for d in "$MODULES"/*/; do
  d="${d%/}"
  [ -d "$d" ] || continue
  case "$d" in
    "$DEST") continue ;;
  esac
  [ -f "$d/manifest.json" ] || continue
  grep -q "\"id\"[[:space:]]*:[[:space:]]*\"$ID\"" "$d/manifest.json" 2>/dev/null || continue
  rm -rf "$d" && log "removed hand-installed duplicate of $ID at $d"
done

# 4. Keep an EXISTING Zabbix module row pointed at the selected tree.
# This preserves status/config while crossing the v1/v2 relative_path
# boundary (v1: id, v2: modules/id) during a frontend major upgrade.
CONF=""
for c in "$FE_ROOT/conf/zabbix.conf.php" /etc/zabbix/web/zabbix.conf.php "$FE_ROOT/../conf/zabbix.conf.php"; do [ -f "$c" ] && { CONF="$c"; break; }; done
if [ -n "$CONF" ]; then
  val() { grep -oE "DB\\['$1'\\][[:space:]]*=[[:space:]]*'[^']*'" "$CONF" 2>/dev/null | sed "s/.*'\\([^']*\\)'.*/\\1/" | head -1; }
  DBTYPE=$(val TYPE); DBHOST=$(val SERVER); DBPORT=$(val PORT); DBNAME=$(val DATABASE); DBUSER=$(val USER); DBPASS=$(val PASSWORD)
  [ -z "$DBHOST" ] && DBHOST="localhost"
  pg_path() { export PGPASSWORD="$DBPASS"; PA=""; [ -n "$DBPORT" ] && [ "$DBPORT" != "0" ] && PA="-p $DBPORT"; psql -h "$DBHOST" $PA -U "$DBUSER" -d "$DBNAME" -tAqc "$1" 2>/dev/null; }
  my_path() { mysql -h "$DBHOST" ${DBPORT:+-P $DBPORT} -u "$DBUSER" -p"$DBPASS" -N -s "$DBNAME" -e "$1" 2>/dev/null; }
  sync_path() { ST=$($1 "SELECT status FROM module WHERE id='$ID'"); [ -n "$ST" ] && { $1 "UPDATE module SET relative_path='$REL' WHERE id='$ID'" && log "updated module row relative_path=$REL (status preserved)"; }; }
  case "$DBTYPE" in
    POSTGRESQL) command -v psql  >/dev/null 2>&1 && sync_path pg_path ;;
    MYSQL)      command -v mysql >/dev/null 2>&1 && sync_path my_path ;;
  esac
fi

# 5-6. MIGRATION MODE - this widget supersedes $LEGACY_IDS (opt-in via
# features.yaml packaging.migrate_from). Self-enable so the in-module
# migrator runs, and clean up each superseded legacy module.
# remove superseded legacy dirs (root+SELinux can; web-user cannot)
for lid in $LEGACY_IDS; do
  LD="$MODULES/$lid"
  [ -d "$LD" ] && grep -q "\"id\"[[:space:]]*:[[:space:]]*\"$lid\"" "$LD/manifest.json" 2>/dev/null && { rm -rf "$LD" && log "removed legacy dir $LD"; }
done
# self-enable this module row + delete legacy rows (parse zabbix.conf.php creds)
CONF=""
for c in "$FE_ROOT/conf/zabbix.conf.php" /etc/zabbix/web/zabbix.conf.php "$FE_ROOT/../conf/zabbix.conf.php"; do [ -f "$c" ] && { CONF="$c"; break; }; done
[ -z "$CONF" ] && { log "config not found - enable $ID in Administration > Modules."; exit 0; }
val() { grep -oE "DB\\['$1'\\][[:space:]]*=[[:space:]]*'[^']*'" "$CONF" 2>/dev/null | sed "s/.*'\\([^']*\\)'.*/\\1/" | head -1; }
DBTYPE=$(val TYPE); DBHOST=$(val SERVER); DBPORT=$(val PORT); DBNAME=$(val DATABASE); DBUSER=$(val USER); DBPASS=$(val PASSWORD)
[ -z "$DBHOST" ] && DBHOST="localhost"
pg() { export PGPASSWORD="$DBPASS"; PA=""; [ -n "$DBPORT" ] && [ "$DBPORT" != "0" ] && PA="-p $DBPORT"; psql -h "$DBHOST" $PA -U "$DBUSER" -d "$DBNAME" -tAqc "$1" 2>/dev/null; }
my() { mysql -h "$DBHOST" ${DBPORT:+-P $DBPORT} -u "$DBUSER" -p"$DBPASS" -N -s "$DBNAME" -e "$1" 2>/dev/null; }
enable_row() {  # $1 = pg|my
  ST=$($1 "SELECT status FROM module WHERE id='$ID'")
  if [ "$ST" = "0" ]; then log "module present but admin-disabled - leaving as is."; return; fi
  if [ -n "$ST" ]; then $1 "UPDATE module SET status=1 WHERE id='$ID'"
  elif [ "$1" = "pg" ]; then M=$(pg "SELECT COALESCE(MAX(moduleid),0)+1 FROM module"); [ -z "$M" ] && M=1; pg "INSERT INTO module (moduleid,id,relative_path,status,config) VALUES ($M,'$ID','$REL',1,'[]')"
  else my "INSERT INTO module (moduleid,id,relative_path,status,config) VALUES ((SELECT COALESCE(MAX(moduleid),0)+1 FROM (SELECT moduleid FROM module) m),'$ID','$REL',1,'[]')"; fi
  for lid in $LEGACY_IDS; do $1 "DELETE FROM module WHERE id='$lid'"; done
}
case "$DBTYPE" in
  POSTGRESQL) command -v psql  >/dev/null 2>&1 && enable_row pg || log "psql not found - enable $ID in Administration > Modules." ;;
  MYSQL)      command -v mysql >/dev/null 2>&1 && enable_row my || log "mysql client not found - enable $ID in Administration > Modules." ;;
  *)          log "unknown DB type - enable $ID in Administration > Modules." ;;
esac

log "headermax 2.6.0 installed. Exactly one module path is deployed: modules/headermax. Scan/enable only that entry; never activate a second copy. Zabbix upgrades are watched automatically; recovery helper: /usr/libexec/initmax-widget-deploy-headermax. Docs: https://www.initmax.com/wiki/headermax/"

# RPM has no nFPM file-trigger field. Its package therefore ships a
# systemd.path watcher which invokes this selector when a Zabbix frontend
# replaces defines.inc.php. Debian uses its native dpkg pathname trigger.
WATCH="initmax-widget-deploy-headermax.path"
if command -v systemctl >/dev/null 2>&1 && [ -f "/usr/lib/systemd/system/$WATCH" ]; then
  systemctl daemon-reload >/dev/null 2>&1 || true
  systemctl enable --now "$WATCH" >/dev/null 2>&1 || log "could not start $WATCH; run the deploy helper after a Zabbix upgrade"
fi
exit 0
