#!/usr/bin/env bash
# ansipa-install-modules.sh — apply setup modules to this host based on
# FreeIPA host group membership.
#
# Host groups follow the naming convention:
#   ansipa-module-<name>   e.g. ansipa-module-docker, ansipa-module-ollama
#
# When this host is a member of such a group, the corresponding module
# script in /usr/local/lib/ansipa-modules/<name>.sh is executed (once,
# stamped in /var/lib/ansipa-modules/).
#
# Configuration: /etc/ansipa-modules.conf
#   ANSIPA_USER=<username>   non-root user for AUR helper (yay)
#   MODULES_DIR=/usr/local/lib/ansipa-modules
#   STATE_DIR=/var/lib/ansipa-modules

set -euo pipefail

CONFIG=/etc/ansipa-modules.conf
[[ -f "$CONFIG" ]] && source "$CONFIG"

ANSIPA_USER="${ANSIPA_USER:-}"
MODULES_DIR="${MODULES_DIR:-/usr/local/lib/ansipa-modules}"
STATE_DIR="${STATE_DIR:-/var/lib/ansipa-modules}"
PREFIX="ansipa-module-"
LOG_TAG="ansipa-modules"

log()  { echo "[$LOG_TAG] $*"; logger -t "$LOG_TAG" "$*" 2>/dev/null || true; }
warn() { echo "[$LOG_TAG][WARN] $*" >&2; logger -t "$LOG_TAG" "WARN: $*" 2>/dev/null || true; }

# ── Resolve ANSIPA_USER ───────────────────────────────────────────────────────
if [[ -z "$ANSIPA_USER" ]]; then
    # Use the first non-root, non-system user with a login shell
    ANSIPA_USER=$(awk -F: '($3>=1000 && $7!~/nologin|false/) {print $1; exit}' /etc/passwd)
fi
if [[ -z "$ANSIPA_USER" ]]; then
    warn "Cannot determine ANSIPA_USER. Set it in $CONFIG."
    exit 1
fi

log "Running as root, AUR helper delegated to user: $ANSIPA_USER"
mkdir -p "$STATE_DIR"

# ── Create a yay wrapper so module scripts can call 'yay' as non-root ────────
YAY_BIN=$(command -v yay 2>/dev/null || true)
WRAP_DIR=$(mktemp -d /tmp/ansipa-wrap.XXXXXX)
trap 'rm -rf "$WRAP_DIR"' EXIT

if [[ -n "$YAY_BIN" ]]; then
    cat > "$WRAP_DIR/yay" <<EOF
#!/bin/bash
exec sudo -u "$ANSIPA_USER" "$YAY_BIN" "\$@"
EOF
    chmod +x "$WRAP_DIR/yay"
fi

# ── Discover which ansipa-module-* host groups this host belongs to ───────────
HOST_FQDN=$(hostname -f 2>/dev/null || hostname)

if ! command -v ipa &>/dev/null; then
    warn "ipa command not found — host not enrolled in FreeIPA. Exiting."
    exit 0
fi

# kinit with host keytab so IPA commands work from the service context
kinit -k "host/$HOST_FQDN" &>/dev/null || true

RAW_GROUPS=$(ipa host-show "$HOST_FQDN" --all 2>/dev/null \
    | grep -i "Member of host-groups:" | sed 's/.*: //' || true)

if [[ -z "$RAW_GROUPS" ]]; then
    log "Host '$HOST_FQDN' is not a member of any host groups — nothing to do."
    exit 0
fi

# Parse comma-separated list, keep only ansipa-module-* entries
WANTED_MODULES=()
while IFS=',' read -ra GRP_ARRAY; do
    for g in "${GRP_ARRAY[@]}"; do
        g="${g// /}"   # strip spaces
        if [[ "$g" == ${PREFIX}* ]]; then
            WANTED_MODULES+=("${g#$PREFIX}")
        fi
    done
done <<< "$RAW_GROUPS"

if [[ ${#WANTED_MODULES[@]} -eq 0 ]]; then
    log "No ansipa-module-* host groups found for '$HOST_FQDN'."
    exit 0
fi

log "Modules requested for this host: ${WANTED_MODULES[*]}"

# ── Apply each module ─────────────────────────────────────────────────────────
for MODULE in "${WANTED_MODULES[@]}"; do
    STAMP="$STATE_DIR/${MODULE}.done"
    SCRIPT="$MODULES_DIR/${MODULE}.sh"

    if [[ -f "$STAMP" ]]; then
        log "Module '$MODULE' already applied (stamp: $STAMP) — skipping."
        continue
    fi

    if [[ ! -f "$SCRIPT" ]]; then
        warn "Module script not found: $SCRIPT — skipping '$MODULE'."
        continue
    fi

    log "Applying module: $MODULE"
    if env PATH="$WRAP_DIR:$PATH" bash "$SCRIPT" >>"$STATE_DIR/${MODULE}.log" 2>&1; then
        touch "$STAMP"
        log "Module '$MODULE' applied successfully."
    else
        warn "Module '$MODULE' failed — see $STATE_DIR/${MODULE}.log"
    fi
done
