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

# 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
if [ -z "$FE_ROOT" ]; then
  log ""; rule
  log "[WARN] $ID $VERSION was staged, but no Zabbix frontend was found"
  log "[ACTION] Deploy it after the frontend is installed: /usr/libexec/initmax-widget-deploy-$SLUG"
  log "[INFO] Docs: https://www.initmax.com/wiki/$SLUG/"
  rule; exit 0
fi
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 "[WARN] Compatible module tree missing: $SRC - current deployment was left untouched"; exit 0; }

# 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"
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 "[INFO] Removed hand-installed duplicate at $d"
done


# 5. Register and enable every newly installed initMAX module. Reuse the
# migration-safe behaviour previously limited to migrate_from widgets:
# preserve an explicit admin-disabled status and all existing config.
ENABLE_RESULT="manual"
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() { 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; }
  ensure_module_row() {  # $1 = pg|my  [$2 = id] [$3 = relative_path]
    MID="${2:-$ID}"; MREL="${3:-$REL}"
    ST=$($1 "SELECT status FROM module WHERE id='$MID'"); QRC=$?
    [ "$QRC" -ne 0 ] && { ENABLE_RESULT="manual"; return; }
    if [ "$ST" = "0" ]; then
      $1 "UPDATE module SET relative_path='$MREL' WHERE id='$MID'" >/dev/null && ENABLE_RESULT="admin-disabled"
      return
    fi
    if [ -n "$ST" ]; then
      $1 "UPDATE module SET relative_path='$MREL' WHERE id='$MID'" >/dev/null && ENABLE_RESULT="already-enabled"
    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,'$MID','$MREL',1,'[]')" >/dev/null
    else
      my "INSERT INTO module (moduleid,id,relative_path,status,config) VALUES ((SELECT COALESCE(MAX(moduleid),0)+1 FROM (SELECT moduleid FROM module) m),'$MID','$MREL',1,'[]')" >/dev/null
    fi
    if [ -z "$ST" ]; then
      ST=$($1 "SELECT status FROM module WHERE id='$MID'")
      [ "$ST" = "1" ] && ENABLE_RESULT="auto-enabled" || ENABLE_RESULT="manual"
    fi
    case "$ENABLE_RESULT" in
      auto-enabled|already-enabled) for lid in $LEGACY_IDS; do $1 "DELETE FROM module WHERE id='$lid'" >/dev/null; done ;;
    esac
  }
  case "$DBTYPE" in
    POSTGRESQL) command -v psql  >/dev/null 2>&1 && ensure_module_row pg ;;
    MYSQL)      command -v mysql >/dev/null 2>&1 && ensure_module_row my ;;
  esac
fi


# 5b. Companion modules of the same product.
# ENABLE_RESULT describes the PRIMARY module in the summary below, and
# ensure_module_row writes it - so it is saved across this loop.
PRIMARY_ENABLE_RESULT="$ENABLE_RESULT"
# A companion is deployed ONLY on the Zabbix versions its own manifest
# claims. On any other version its directory is REMOVED rather than
# left behind: a widget that can never receive anything is worse than
# an absent one, because the customer can still put it on a dashboard.
for spec in $COMPANIONS; do
  CID="${spec%%:*}"; CVERS="${spec#*:}"
  CDEST="$MODULES/$CID"
  case ",$CVERS," in
    *",$ZBXVER,"*) ;;
    *) [ -d "$CDEST" ] && rm -rf "$CDEST" && log "[INFO] $CID needs Zabbix ${CVERS} - removed from this ${ZBXVER} frontend"; continue ;;
  esac
  CSRC="$STAGING/companions/$CID"
  [ -d "$CSRC" ] || { log "[WARN] companion tree missing: $CSRC"; continue; }
  rm -rf "$CDEST.imxnew"; cp -a "$CSRC" "$CDEST.imxnew"; rm -rf "$CDEST"; mv "$CDEST.imxnew" "$CDEST"
  [ -n "$OWNER" ] && chown -R "$OWNER" "$CDEST" 2>/dev/null
  command -v restorecon >/dev/null 2>&1 && restorecon -RF "$CDEST" >/dev/null 2>&1
  if [ -n "$CONF" ]; then
    case "$DBTYPE" in
      POSTGRESQL) command -v psql  >/dev/null 2>&1 && ensure_module_row pg "$CID" "modules/$CID" ;;
      MYSQL)      command -v mysql >/dev/null 2>&1 && ensure_module_row my "$CID" "modules/$CID" ;;
    esac
  fi
  log " [OK] Companion       : $CID deployed to $CDEST"
done
ENABLE_RESULT="$PRIMARY_ENABLE_RESULT"

# 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-$SLUG.path"; WATCH_RESULT="automatic"
if [ -f "/usr/lib/systemd/system/$WATCH" ]; then
  WATCH_RESULT="helper"
  if command -v systemctl >/dev/null 2>&1; then
    systemctl daemon-reload >/dev/null 2>&1 || true
    systemctl enable --now "$WATCH" >/dev/null 2>&1 && WATCH_RESULT="automatic"
  fi
fi

# 6. One compact, stable result block for apt, dnf and manual review.
log ""; rule
log " $ID $VERSION - INSTALLATION COMPLETE"
rule
log " [OK] Zabbix frontend : ${ZBXVER:-unknown} ($FE_ROOT)"
log " [OK] Module deployed : $DEST"
case "$ENABLE_RESULT" in
  auto-enabled)    log " [OK] Module status   : enabled automatically" ;;
  already-enabled) log " [OK] Module status   : already enabled; settings preserved" ;;
  admin-disabled)  log " [INFO] Module status : disabled by administrator - preserved" ;;
  *)               log " [ACTION] Module could not be enabled automatically"; log " [ACTION] Open Administration > General > Modules > Scan directory" ;;
esac
if [ "$WATCH_RESULT" = "automatic" ]; then
  log " [OK] Upgrade recovery: automatic"
else
  log " [INFO] Upgrade recovery: use the helper after a Zabbix upgrade"
fi
log ""
log " Docs     : https://www.initmax.com/wiki/$SLUG/"
log " Recovery : /usr/libexec/initmax-widget-deploy-$SLUG"
rule
exit 0
