#!/usr/bin/env bash
# One-command server health dashboard
# Shows: Apache, Nginx, MySQL, memory, disk, SSL expiry, recent errors

set -uo pipefail

RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; CYAN='\033[0;36m'
BOLD='\033[1m'; NC='\033[0m'

TODAY_TS=$(date +%s)
WARN_TS=$(date -d "+21 days" +%s)
CRITICAL_TS=$(date -d "+7 days" +%s)
HOSTNAME=$(hostname -f 2>/dev/null || hostname)

ok()   { echo -e "  ${GREEN}●${NC} $*"; }
warn() { echo -e "  ${YELLOW}●${NC} $*"; }
crit() { echo -e "  ${RED}●${NC} $*"; }
header() { echo -e "\n${BOLD}${CYAN}── $* ──${NC}"; }

echo -e "${BOLD}╔══════════════════════════════════════════════════════════╗${NC}"
echo -e "${BOLD}║  SERVER HEALTH  •  $HOSTNAME${NC}"
echo -e "${BOLD}║  $(date '+%Y-%m-%d %H:%M:%S UTC')${NC}"
echo -e "${BOLD}╚══════════════════════════════════════════════════════════╝${NC}"

# ─── SERVICES ─────────────────────────────────────────────────────────────────
header "Services"
for svc in httpd nginx mariadb; do
    state=$(systemctl is-active "$svc" 2>/dev/null || echo "unknown")
    if [[ "$state" == "active" ]]; then
        pid=$(systemctl show -p MainPID "$svc" 2>/dev/null | cut -d= -f2)
        uptime_s=$(ps -o etimes= -p "$pid" 2>/dev/null | tr -d ' ' || echo "?")
        if [[ "$uptime_s" =~ ^[0-9]+$ ]]; then
            h=$((uptime_s/3600)); m=$(( (uptime_s%3600)/60 ))
            ok "$svc: running  (up ${h}h${m}m)"
        else
            ok "$svc: running"
        fi
    elif [[ "$state" == "inactive" ]]; then
        warn "$svc: stopped (inactive)"
    else
        crit "$svc: $state"
    fi
done

# PHP-FPM pools
PHP_POOLS=$(ps aux 2>/dev/null | grep "php-fpm: pool" | grep -v grep | awk '{print $NF}' | sort -u | wc -l)
ok "php-fpm pools active: $PHP_POOLS"

# ─── MEMORY ───────────────────────────────────────────────────────────────────
header "Memory"
MEM_TOTAL=$(free -m | awk '/^Mem/{print $2}')
MEM_USED=$(free -m | awk '/^Mem/{print $3}')
MEM_AVAIL=$(free -m | awk '/^Mem/{print $7}')
MEM_PCT=$((MEM_USED * 100 / MEM_TOTAL))
SWAP_TOTAL=$(free -m | awk '/^Swap/{print $2}')
SWAP_USED=$(free -m | awk '/^Swap/{print $3}')

if [[ $MEM_PCT -gt 90 ]]; then
    crit "RAM: ${MEM_USED}M/${MEM_TOTAL}M used (${MEM_PCT}%) - CRITICAL"
elif [[ $MEM_PCT -gt 75 ]]; then
    warn "RAM: ${MEM_USED}M/${MEM_TOTAL}M used (${MEM_PCT}%)"
else
    ok "RAM: ${MEM_USED}M/${MEM_TOTAL}M used (${MEM_PCT}%)"
fi

if [[ $SWAP_TOTAL -gt 0 ]]; then
    SWAP_PCT=$((SWAP_USED * 100 / SWAP_TOTAL))
    if [[ $SWAP_PCT -gt 90 ]]; then
        crit "SWAP: ${SWAP_USED}M/${SWAP_TOTAL}M used (${SWAP_PCT}%) - EXHAUSTED"
    elif [[ $SWAP_PCT -gt 50 ]]; then
        warn "SWAP: ${SWAP_USED}M/${SWAP_TOTAL}M used (${SWAP_PCT}%)"
    else
        ok "SWAP: ${SWAP_USED}M/${SWAP_TOTAL}M used (${SWAP_PCT}%)"
    fi
fi

# Top memory process
TOP_MEM=$(ps aux --sort=-%mem 2>/dev/null | awk 'NR==2{printf "%s (%.1f%%)", $11, $4}')
echo "  Top process: $TOP_MEM"

# ─── DISK ─────────────────────────────────────────────────────────────────────
header "Disk"
while IFS= read -r line; do
    PCT=$(echo "$line" | awk '{print $5}' | tr -d '%')
    MOUNT=$(echo "$line" | awk '{print $6}')
    INFO=$(echo "$line" | awk '{printf "%s used of %s on %s", $3, $2, $6}')
    if [[ $PCT -gt 90 ]]; then
        crit "Disk ${PCT}%: $INFO"
    elif [[ $PCT -gt 75 ]]; then
        warn "Disk ${PCT}%: $INFO"
    else
        ok "Disk ${PCT}%: $INFO"
    fi
done < <(df -h 2>/dev/null | awk 'NR>1 && /^\/dev/' | grep -v "tmpfs\|devtmpfs")

# ─── LOAD ─────────────────────────────────────────────────────────────────────
header "Load Average"
LOAD=$(uptime | awk -F'load average:' '{print $2}' | xargs)
LOAD1=$(echo "$LOAD" | cut -d, -f1 | xargs)
NCPU=$(nproc 2>/dev/null || echo 1)
LOAD_PCT=$(echo "$LOAD1 $NCPU" | awk '{printf "%d", ($1/$2)*100}')
if [[ $LOAD_PCT -gt 150 ]]; then
    crit "Load: $LOAD  (${LOAD_PCT}% of ${NCPU} CPUs)"
elif [[ $LOAD_PCT -gt 80 ]]; then
    warn "Load: $LOAD  (${LOAD_PCT}% of ${NCPU} CPUs)"
else
    ok "Load: $LOAD  (${NCPU} CPUs)"
fi

# ─── SSL EXPIRY ───────────────────────────────────────────────────────────────
header "SSL Certificate Expiry (next 21 days)"
SSL_ISSUES=0
for dir in /var/cpanel/ssl/apache_tls/*/; do
    domain=$(basename "$dir")
    combined="$dir/combined"
    [[ ! -f "$combined" ]] && continue
    expiry_str=$(openssl x509 -noout -enddate -in "$combined" 2>/dev/null | cut -d= -f2)
    [[ -z "$expiry_str" ]] && continue
    expiry_ts=$(date -d "$expiry_str" +%s 2>/dev/null || echo 0)
    [[ $expiry_ts -eq 0 ]] && continue
    if [[ $expiry_ts -lt $TODAY_TS ]]; then
        crit "EXPIRED: $domain"
        ((SSL_ISSUES++))
    elif [[ $expiry_ts -lt $CRITICAL_TS ]]; then
        days=$(( (expiry_ts - TODAY_TS) / 86400 ))
        crit "Expires in ${days}d: $domain"
        ((SSL_ISSUES++))
    elif [[ $expiry_ts -lt $WARN_TS ]]; then
        days=$(( (expiry_ts - TODAY_TS) / 86400 ))
        warn "Expires in ${days}d: $domain"
        ((SSL_ISSUES++))
    fi
done
[[ $SSL_ISSUES -eq 0 ]] && ok "All active SSL certs valid > 21 days"

# ─── SSL MISMATCHES ───────────────────────────────────────────────────────────
MISMATCH_COUNT=0
for dir in /var/cpanel/ssl/apache_tls/*/; do
    domain=$(basename "$dir")
    combined="$dir/combined"
    key_file="$dir/key"
    [[ ! -f "$combined" || ! -f "$key_file" ]] && continue
    cert_md5=$(openssl x509 -noout -modulus -in "$combined" 2>/dev/null | openssl md5 | awk '{print $2}')
    key_md5=$(openssl rsa -noout -modulus -in "$key_file" 2>/dev/null | openssl md5 | awk '{print $2}')
    if [[ -n "$cert_md5" && "$cert_md5" != "$key_md5" ]]; then
        # Only flag if active in httpd
        if grep -q "apache_tls/$domain/" /etc/apache2/conf/httpd.conf /etc/apache2/conf.d/*.conf 2>/dev/null; then
            crit "SSL MISMATCH (ACTIVE): $domain"
            ((MISMATCH_COUNT++))
        fi
    fi
done
[[ $MISMATCH_COUNT -eq 0 ]] && ok "No active SSL cert/key mismatches"

# ─── RECENT APACHE ERRORS ─────────────────────────────────────────────────────
header "Recent Apache Errors (last 30 min)"
ERROR_LOG="/etc/apache2/logs/error_log"
if [[ -f "$ERROR_LOG" ]]; then
    SINCE=$(date -d "30 minutes ago" '+%a %b %d %H:%M' 2>/dev/null || true)
    RECENT_ERRORS=$(tail -200 "$ERROR_LOG" 2>/dev/null | grep "\[emerg\]\|\[crit\]\|\[alert\]" | tail -5)
    if [[ -n "$RECENT_ERRORS" ]]; then
        crit "Recent critical errors in error_log:"
        echo "$RECENT_ERRORS" | while IFS= read -r line; do echo "    $line"; done
    else
        ok "No emerg/crit/alert errors in last 200 log lines"
    fi
else
    warn "Error log not found: $ERROR_LOG"
fi

# ─── APACHE RESTART HISTORY ───────────────────────────────────────────────────
header "Apache Restart History (last 24h)"
RESTART_LOG="/opt/server-resilience/logs/restart-$(date +%Y%m%d).log"
if [[ -f "$RESTART_LOG" ]]; then
    RESTART_COUNT=$(grep -c "safe-apache-restart" "$RESTART_LOG" 2>/dev/null || echo 0)
    FAIL_COUNT=$(grep -c "FATAL\|FAILED\|rollback" "$RESTART_LOG" 2>/dev/null || echo 0)
    ok "Restarts today: $RESTART_COUNT  |  Failures: $FAIL_COUNT"
else
    ok "No restart log for today"
fi

# ─── AUTOSSL STATUS ───────────────────────────────────────────────────────────
header "AutoSSL"
AUTOSSL_LAST=$(ls /var/cpanel/logs/autossl/ 2>/dev/null | tail -1)
if [[ -n "$AUTOSSL_LAST" ]]; then
    ok "Last AutoSSL run: $AUTOSSL_LAST"
else
    warn "No AutoSSL logs found"
fi

echo ""
echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
echo -e "${BOLD}Commands:${NC}"
echo "  preflight-check          Validate before any Apache change"
echo "  safe-apache-restart      Restart with preflight + rollback"
echo "  isolate-broken-vhost     Disable one bad domain, keep rest live"
echo "  ssl-audit                Full SSL cert health report"
echo "  server-rollback          Roll back to last known-good config"
echo ""
