#!/bin/bash
# ABOUTME: Moonarch system health checker — verifies services, configs, packages and paths.
# ABOUTME: Shipped as /usr/bin/moonarch-doctor (alias: moondoc) by the moonarch-git package.

set -uo pipefail

# --- Output helpers ---

PASS=0
FAIL=0
WARN=0

pass() {
    echo -e "  \e[1;32m✓\e[0m $*"
    ((PASS++))
}

fail() {
    echo -e "  \e[1;31m✗\e[0m $*"
    ((FAIL++))
}

warn() {
    echo -e "  \e[1;33m⚠\e[0m $*"
    ((WARN++))
}

section() {
    echo
    echo -e "\e[1;34m[$1]\e[0m"
}

# --- Check functions ---

check_system_service() {
    local svc="$1"
    local type
    type=$(systemctl show "$svc" --property=Type 2>/dev/null | cut -d= -f2)

    if systemctl is-enabled "$svc" &>/dev/null; then
        if systemctl is-active "$svc" &>/dev/null; then
            pass "$svc (enabled, active)"
        elif [[ "$type" == "oneshot" ]]; then
            # Oneshot services are inactive after completion — check if they succeeded
            local result
            result=$(systemctl show "$svc" --property=Result 2>/dev/null | cut -d= -f2)
            if [[ "$result" == "success" ]]; then
                pass "$svc (enabled, oneshot completed)"
            else
                fail "$svc (enabled, oneshot failed: $result)"
            fi
        else
            fail "$svc (enabled, NOT active)"
        fi
    else
        fail "$svc (NOT enabled)"
    fi
}

check_user_service() {
    local svc="$1"
    if systemctl --user is-enabled "$svc" &>/dev/null; then
        if systemctl --user is-active "$svc" &>/dev/null; then
            pass "$svc (enabled, active)"
        else
            # User services may be inactive if not in a graphical session
            warn "$svc (enabled, not active — may need graphical session)"
        fi
    else
        fail "$svc (NOT enabled)"
    fi
}

check_config_match() {
    local deployed="$1"
    local source="$2"
    local label="${deployed}"

    if [[ ! -f "$deployed" ]]; then
        fail "$label (missing)"
        return
    fi
    if [[ ! -f "$source" ]]; then
        warn "$label (exists, but no source to compare at $source)"
        return
    fi

    local hash_deployed hash_source
    hash_deployed=$(sha256sum "$deployed" | cut -d' ' -f1)
    hash_source=$(sha256sum "$source" | cut -d' ' -f1)

    if [[ "$hash_deployed" == "$hash_source" ]]; then
        pass "$label"
    else
        warn "$label (differs from moonarch default)"
    fi
}

# --- Header ---

echo -e "\e[1;34m"
echo "  Moonarch Doctor"
echo -e "\e[0m"

# --- 1. Packages ---

section "Packages"

OFFICIAL="/usr/share/moonarch/official.txt"
AUR="/usr/share/moonarch/aur.txt"

# Hoist INSTALLED so the AUR block below can use it even if OFFICIAL is absent —
# otherwise `set -u` aborts the script when $INSTALLED is referenced unset.
INSTALLED=$(pacman -Qq 2>/dev/null)

if [[ -f "$OFFICIAL" ]]; then
    MISSING_OFFICIAL=()
    while IFS= read -r pkg; do
        [[ "$pkg" =~ ^[[:space:]]*# ]] && continue
        [[ -z "${pkg// }" ]] && continue
        if ! echo "$INSTALLED" | grep -qx "$pkg"; then
            MISSING_OFFICIAL+=("$pkg")
        fi
    done < "$OFFICIAL"

    if [[ ${#MISSING_OFFICIAL[@]} -eq 0 ]]; then
        pass "All official packages installed"
    else
        fail "Missing official packages: ${MISSING_OFFICIAL[*]}"
    fi
else
    warn "$OFFICIAL not found (moonarch-git not installed?)"
fi

if [[ -f "$AUR" ]]; then
    MISSING_AUR=()
    while IFS= read -r pkg; do
        [[ "$pkg" =~ ^[[:space:]]*# ]] && continue
        [[ -z "${pkg// }" ]] && continue
        if ! echo "$INSTALLED" | grep -qx "$pkg"; then
            MISSING_AUR+=("$pkg")
        fi
    done < "$AUR"

    if [[ ${#MISSING_AUR[@]} -eq 0 ]]; then
        pass "All AUR packages installed"
    else
        fail "Missing AUR packages: ${MISSING_AUR[*]}"
    fi
else
    warn "$AUR not found (moonarch-git not installed?)"
fi

ORPHANS=$(pacman -Qdtq 2>/dev/null || true)
if [[ -z "$ORPHANS" ]]; then
    pass "No orphaned packages"
else
    ORPHAN_COUNT=$(echo "$ORPHANS" | wc -l)
    warn "$ORPHAN_COUNT orphaned package(s) (run moonup to clean)"
fi

# --- 2. System Services ---

section "System Services"

for svc in NetworkManager bluetooth greetd systemd-timesyncd ufw auto-cpufreq; do
    check_system_service "$svc"
done

# Battery conservation service (laptop only)
THRESHOLD_FILE="/sys/class/power_supply/BAT0/charge_control_end_threshold"
if [[ -f "$THRESHOLD_FILE" ]]; then
    check_system_service moonarch-batsaver

    # Verify udev rule effectiveness — file must be group=wheel and group-writable
    THRESHOLD_GROUP=$(stat -c '%G' "$THRESHOLD_FILE")
    THRESHOLD_PERMS=$(stat -c '%a' "$THRESHOLD_FILE")
    if [[ "$THRESHOLD_GROUP" == "wheel" ]] && [[ "${THRESHOLD_PERMS:1:1}" -ge 6 ]]; then
        pass "battery threshold writable by wheel (udev rule active)"
    else
        fail "battery threshold not writable by wheel (group=$THRESHOLD_GROUP, mode=$THRESHOLD_PERMS — udev rule not applied)"
    fi
else
    pass "moonarch-batsaver (skipped — no battery threshold support)"
fi

# --- 3. User Services ---

section "User Services"

if [[ $EUID -eq 0 ]]; then
    warn "Running as root — skipping user service checks"
elif pacman -Qq moonarch-git &>/dev/null; then
    EXPECTED_SVCS=()
    while IFS= read -r svc_file; do
        EXPECTED_SVCS+=("$(basename "$svc_file" .service)")
    done < <(pacman -Qql moonarch-git | grep -E '^/etc/systemd/user/[^/]+\.service$')
    # Services enabled by post-install.sh from other packages
    EXPECTED_SVCS+=(stasis)

    for svc in "${EXPECTED_SVCS[@]}"; do
        check_user_service "$svc"
    done
else
    warn "moonarch-git not installed — skipping user service checks"
fi

# --- 4. Config Files ---

section "Config Files"

SRC="/usr/share/moonarch"

check_config_match "/etc/xdg/foot/foot.ini"        "$SRC/foot/foot.ini"
check_config_match "/etc/xdg/waybar/style.css"      "$SRC/waybar/style.css"
check_config_match "/etc/xdg/swaync/config.json"    "$SRC/swaync/config.json"
check_config_match "/etc/xdg/swaync/style.css"      "$SRC/swaync/style.css"
check_config_match "/etc/greetd/config.toml"         "$SRC/greetd/config.toml"
check_config_match "/etc/greetd/niri-greeter.kdl"    "$SRC/greetd/niri-greeter.kdl"
check_config_match "/etc/moongreet/moongreet.toml"   "$SRC/moongreet/moongreet.toml"

# --- 5. Helper Scripts ---

section "Helper Scripts"

if pacman -Qq moonarch-git &>/dev/null; then
    EXPECTED_SCRIPTS=()
    while IFS= read -r script; do
        EXPECTED_SCRIPTS+=("$(basename "$script")")
    done < <(pacman -Qql moonarch-git | grep -E '^/usr/bin/moonarch-[^/]+$')

    MISSING_SCRIPTS=()
    for script in "${EXPECTED_SCRIPTS[@]}"; do
        if [[ ! -x "/usr/bin/$script" ]]; then
            MISSING_SCRIPTS+=("$script")
        fi
    done

    if [[ ${#MISSING_SCRIPTS[@]} -eq 0 ]]; then
        pass "All ${#EXPECTED_SCRIPTS[@]} helper scripts present"
    else
        fail "Missing scripts: ${MISSING_SCRIPTS[*]}"
    fi
else
    warn "moonarch-git not installed — skipping helper script checks"
fi

# Symlinks
for link in moonup moondoc; do
    if [[ -L "/usr/bin/$link" ]]; then
        pass "$link symlink"
    else
        fail "$link symlink (missing)"
    fi
done

# --- 6. System Config ---

section "System Config"

# UFW (check via systemd, no sudo needed)
if command -v ufw &>/dev/null; then
    if systemctl is-active ufw &>/dev/null; then
        pass "UFW active"
    else
        fail "UFW not active"
    fi
else
    fail "UFW not installed"
fi

# Pacman moonarch repo
if grep -q '^\[moonarch\]' /etc/pacman.conf 2>/dev/null; then
    pass "Pacman [moonarch] repo configured"
else
    fail "Pacman [moonarch] repo missing from /etc/pacman.conf"
fi

# Default shell
USER_SHELL=$(getent passwd "$USER" | cut -d: -f7)
if [[ "$USER_SHELL" == */zsh ]]; then
    pass "Default shell: zsh"
else
    warn "Default shell: $USER_SHELL (expected zsh)"
fi

# --- 7. Directories ---

section "Directories"

if [[ -d /var/lib/moonarch ]]; then
    DIR_PERMS=$(stat -c '%a' /var/lib/moonarch)
    DIR_GROUP=$(stat -c '%G' /var/lib/moonarch)
    if [[ "$DIR_GROUP" == "wheel" ]]; then
        pass "/var/lib/moonarch/ (group: wheel, mode: $DIR_PERMS)"
    else
        warn "/var/lib/moonarch/ (group: $DIR_GROUP, expected wheel)"
    fi
else
    warn "/var/lib/moonarch/ missing (created on first battery toggle)"
fi

# --- Summary ---

echo
TOTAL=$((PASS + FAIL + WARN))
echo -e "\e[1;34m[Summary]\e[0m $TOTAL checks: \e[1;32m$PASS passed\e[0m, \e[1;31m$FAIL failed\e[0m, \e[1;33m$WARN warnings\e[0m"

if [[ $FAIL -gt 0 ]]; then
    exit 1
fi
