#!/usr/bin/env bash
# scripts/onboard/steps/20-base.sh — base system configuration for LUSTRO
#
# Stages:
#   1. swap→zram  — disable dphys-swapfile, install + configure zram-tools
#   2. /opt/homelab — create base directory, chown <ssh_user>:<ssh_user>
#   3. event dir  — create /opt/homelab/events/<ts_hostname>, chown -R
#
# Dry-run convention:
#   - Probes (state queries) run unconditionally — dry-run reflects real state
#   - Mutations use rrun() which skips execution when DRY_RUN=1

set -euo pipefail

STEP_NAME="20-base"

: "${REPO_ROOT:?REPO_ROOT is not set — run via onboard.sh}"
: "${NODE_YAML:?NODE_YAML is not set — run via onboard.sh}"
: "${DRY_RUN:=0}"

# Source common.sh when run standalone (orchestrator sources it before calling steps)
if ! declare -f log >/dev/null 2>&1; then
    # shellcheck source=../lib/common.sh
    source "${REPO_ROOT}/scripts/onboard/lib/common.sh"
fi

# ── parse node.yaml ───────────────────────────────────────────────────────────
SSH_USER=$(yaml_get    "$NODE_YAML" "ssh_user")
TS_HOSTNAME=$(yaml_get "$NODE_YAML" "tailscale.hostname")

[[ -z "$SSH_USER"    ]] && die "ssh_user not set in $NODE_YAML"
[[ -z "$TS_HOSTNAME" ]] && die "tailscale.hostname not set in $NODE_YAML"

export ONBOARD_SSH_USER="${ONBOARD_SSH_USER:-${SSH_USER}}"
export ONBOARD_SSH_HOST="${ONBOARD_SSH_HOST:-${TS_HOSTNAME}}"

# shellcheck source=../lib/remote.sh
source "${REPO_ROOT}/scripts/onboard/lib/remote.sh"

# ── rprobe: read-only remote probe — always runs, even in dry-run ─────────────
rprobe() {
    ssh "${_SSH_OPTS[@]}" "${ONBOARD_SSH_USER}@${ONBOARD_SSH_HOST}" -- "$@"
}

# ═══════════════════════════════════════════════════════════════════════════════
# Stage 1 — swap→zram
# ═══════════════════════════════════════════════════════════════════════════════
step "[$STEP_NAME] 1/3 swap→zram (PERCENT=50, algo=zstd)"

# Guard by EFFECT: zram device present in swapon AND dphys-swapfile not active
# → desired end-state already reached, skip the whole stage.
_zram_active=0
_dphys_active=0
rprobe 'sudo swapon --show 2>/dev/null | grep -q /dev/zram' && _zram_active=1 || true
rprobe 'systemctl is-active dphys-swapfile' >/dev/null 2>&1  && _dphys_active=1 || true

if [[ "$_zram_active" -eq 1 && "$_dphys_active" -eq 0 ]]; then
    log "zram already active, dphys-swapfile not active — skip"
else
    # Substage: disable dphys-swapfile if still active
    if [[ "$_dphys_active" -eq 1 ]]; then
        log "dphys-swapfile active — disabling"
        rrun sudo dphys-swapfile swapoff
        rrun sudo systemctl disable --now dphys-swapfile
        if rprobe '[ -f /var/swap ]' 2>/dev/null; then
            rrun sudo rm -f /var/swap
            log "Removed /var/swap"
        fi
    else
        log "dphys-swapfile not active — skip disable"
    fi

    # Substage: install zram-tools if package not present
    # Use dpkg -l rather than command -v: zramswap binary may not be on PATH over SSH
    if ! rprobe 'dpkg -l zram-tools 2>/dev/null | grep -q "^ii"' 2>/dev/null; then
        log "zram-tools not installed — installing"
        rrun sudo apt-get install -y zram-tools
    else
        log "zram-tools already installed"
    fi

    # Write config and (re)start zramswap
    log "Writing /etc/default/zramswap (ALGO=zstd, PERCENT=50)"
    rrun bash -c "printf '%s\n' 'ALGO=zstd' 'PERCENT=50' | sudo tee /etc/default/zramswap > /dev/null"
    rrun sudo systemctl enable zramswap
    rrun sudo systemctl restart zramswap
fi

# Verify (skipped in dry-run — mutations may not have run)
if [ "${DRY_RUN:-0}" != 1 ]; then
    if rprobe 'sudo swapon --show 2>/dev/null | grep -q /dev/zram'; then
        log "Verify OK: zram swap active"
        rprobe 'sudo swapon --show' || true
    else
        die "zram swap not active after setup — check: systemctl status zramswap on ${TS_HOSTNAME}"
    fi
    if rprobe 'systemctl is-active dphys-swapfile' >/dev/null 2>&1; then
        warn "dphys-swapfile still reports active — manual inspection needed"
    else
        log "Verify OK: dphys-swapfile not active"
    fi
fi

# ═══════════════════════════════════════════════════════════════════════════════
# Stage 2 — /opt/homelab
# ═══════════════════════════════════════════════════════════════════════════════
step "[$STEP_NAME] 2/3 /opt/homelab (owner: ${SSH_USER}:${SSH_USER})"

# Guard: exists AND owned by SSH_USER?
_dir_ok=0
if rprobe '[ -d /opt/homelab ]' 2>/dev/null; then
    _owner=$(rprobe "stat -c '%U' /opt/homelab" 2>/dev/null || echo "")
    if [[ "$_owner" == "$SSH_USER" ]]; then
        _dir_ok=1
        log "/opt/homelab exists, owner=${SSH_USER} — skip"
    else
        log "/opt/homelab exists but owner='${_owner}' — fixing"
    fi
else
    log "/opt/homelab missing — creating"
fi

if [[ "$_dir_ok" -eq 0 ]]; then
    rrun sudo mkdir -p /opt/homelab
    rrun sudo chown "${SSH_USER}:${SSH_USER}" /opt/homelab
fi

# ═══════════════════════════════════════════════════════════════════════════════
# Stage 3 — event dir
# ═══════════════════════════════════════════════════════════════════════════════
step "[$STEP_NAME] 3/3 event dir (/opt/homelab/events/${TS_HOSTNAME})"

# Guard: event subdir exists AND /opt/homelab/events owned by SSH_USER?
_evdir_ok=0
if rprobe "[ -d /opt/homelab/events/${TS_HOSTNAME} ]" 2>/dev/null; then
    _ev_owner=$(rprobe "stat -c '%U' /opt/homelab/events" 2>/dev/null || echo "")
    if [[ "$_ev_owner" == "$SSH_USER" ]]; then
        _evdir_ok=1
        log "/opt/homelab/events/${TS_HOSTNAME} exists, owner=${SSH_USER} — skip"
    else
        log "/opt/homelab/events exists but owner='${_ev_owner}' — fixing"
    fi
else
    log "/opt/homelab/events/${TS_HOSTNAME} missing — creating"
fi

if [[ "$_evdir_ok" -eq 0 ]]; then
    rrun sudo mkdir -p "/opt/homelab/events/${TS_HOSTNAME}"
    rrun sudo chown -R "${SSH_USER}:${SSH_USER}" /opt/homelab/events
fi

log "[$STEP_NAME] done"
