#!/usr/bin/env bash
# Apache preflight check - run before every reload/restart
# Returns 0 = pass, 1 = fail (do not proceed with restart)

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
LOG_DIR="/opt/server-resilience/logs"
LOG_FILE="$LOG_DIR/preflight-$(date +%Y%m%d).log"
QUARANTINE_DIR="/etc/apache2/conf.d/quarantine"
ISSUES_FILE="$LOG_DIR/preflight-issues-$(date +%Y%m%d_%H%M%S).txt"

mkdir -p "$LOG_DIR" "$QUARANTINE_DIR"

RED='\033[0;31m'; YELLOW='\033[1;33m'; GREEN='\033[0;32m'; NC='\033[0m'; BOLD='\033[1m'
PASS=0; FAIL=0; WARN=0
FAILED_DOMAINS=()

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"; }
pass() { echo -e "${GREEN}[PASS]${NC} $*"; log "PASS: $*"; ((PASS++)); }
warn() { echo -e "${YELLOW}[WARN]${NC} $*"; log "WARN: $*"; ((WARN++)); }
fail() { echo -e "${RED}[FAIL]${NC} $*"; log "FAIL: $*"; ((FAIL++)); }
header() { echo -e "\n${BOLD}=== $* ===${NC}"; log "--- $* ---"; }

# ─── 1. APACHE SYNTAX CHECK ───────────────────────────────────────────────────
header "Apache Syntax Check"
SYNTAX_OUT=$(httpd -t 2>&1)
SYNTAX_RC=$?
if [[ $SYNTAX_RC -eq 0 ]]; then
    pass "Apache config syntax OK"
else
    fail "Apache config syntax FAILED"
    echo "$SYNTAX_OUT" | tee -a "$LOG_FILE"
    echo "SYNTAX_ERROR: $SYNTAX_OUT" >> "$ISSUES_FILE"
fi

# ─── 2. SSL CERT/KEY MISMATCH CHECK ───────────────────────────────────────────
header "SSL Certificate/Key Match Check"
TODAY_TS=$(date +%s)
WARN_TS=$(date -d "+14 days" +%s)

for dir in /var/cpanel/ssl/apache_tls/*/; do
    domain=$(basename "$dir")
    combined="$dir/combined"
    key_file="$dir/key"

    [[ ! -f "$combined" ]] && continue
    [[ ! -f "$key_file" ]] && continue

    # Check cert/key moduli match
    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 [[ -z "$cert_md5" ]]; then
        # Try EC key
        cert_md5=$(openssl x509 -noout -pubkey -in "$combined" 2>/dev/null | openssl md5 | awk '{print $2}')
        key_md5=$(openssl ec -noout -pubout -in "$key_file" 2>/dev/null | openssl md5 | awk '{print $2}')
    fi

    if [[ -z "$cert_md5" || "$cert_md5" != "$key_md5" ]]; then
        # Only report as FAIL if this domain is actually in httpd.conf
        if grep -q "apache_tls/$domain/" /etc/apache2/conf/httpd.conf /etc/apache2/conf.d/*.conf 2>/dev/null; then
            fail "SSL MISMATCH (active vhost): $domain"
            FAILED_DOMAINS+=("$domain")
            echo "SSL_MISMATCH: $domain" >> "$ISSUES_FILE"
        else
            warn "SSL mismatch (inactive vhost, not blocking): $domain"
        fi
        continue
    fi

    # Check expiry
    expiry_str=$(openssl x509 -noout -enddate -in "$combined" 2>/dev/null | cut -d= -f2)
    if [[ -n "$expiry_str" ]]; then
        expiry_ts=$(date -d "$expiry_str" +%s 2>/dev/null || echo 0)
        if [[ $expiry_ts -gt 0 && $expiry_ts -lt $TODAY_TS ]]; then
            warn "SSL EXPIRED: $domain (expired: $expiry_str)"
        elif [[ $expiry_ts -gt 0 && $expiry_ts -lt $WARN_TS ]]; then
            days=$(( (expiry_ts - TODAY_TS) / 86400 ))
            warn "SSL expiring in ${days}d: $domain"
        fi
    fi
done

# ─── 3. MISSING CERT FILES CHECK ──────────────────────────────────────────────
header "Missing/Broken SSL File Check"
while IFS= read -r cert_line; do
    cert_path=$(echo "$cert_line" | awk '{print $2}' | tr -d '"')
    if [[ ! -f "$cert_path" ]]; then
        domain=$(grep -B5 "SSLCertificateFile $cert_line" /etc/apache2/conf/httpd.conf 2>/dev/null | grep "ServerName" | awk '{print $2}' | head -1)
        fail "Missing SSLCertificateFile: $cert_path"
        echo "MISSING_CERT: $cert_path" >> "$ISSUES_FILE"
        [[ -n "$domain" ]] && FAILED_DOMAINS+=("$domain")
    fi
done < <(grep "SSLCertificateFile\|SSLCertificateKeyFile" /etc/apache2/conf/httpd.conf /etc/apache2/conf.d/*.conf 2>/dev/null | awk -F: '{print $2}')

# ─── 4. DOCUMENTROOT EXISTS CHECK ─────────────────────────────────────────────
header "DocumentRoot Existence Check"
MISSING_ROOTS=0
while IFS= read -r docroot; do
    [[ ! -d "$docroot" ]] && { warn "Missing DocumentRoot: $docroot"; ((MISSING_ROOTS++)); }
done < <(grep "^\s*DocumentRoot" /etc/apache2/conf/httpd.conf | awk '{print $2}' | tr -d '"' | sort -u)
[[ $MISSING_ROOTS -eq 0 ]] && pass "All DocumentRoots exist" || warn "$MISSING_ROOTS DocumentRoots missing (warnings, won't stop start)"

# ─── 5. MODULE LOAD CHECK ─────────────────────────────────────────────────────
header "Required Module Check"
for mod in ssl_module socache_shmcb_module; do
    if httpd -M 2>/dev/null | grep -q "$mod"; then
        pass "Module loaded: $mod"
    else
        fail "Module NOT loaded: $mod"
    fi
done

# ─── 6. PORT CONFLICT CHECK ───────────────────────────────────────────────────
header "Port Conflict Check"
# In nginx+Apache setup, Apache uses 81/444 (nginx fronts 80/443)
for port in 81 444; do
    if ss -tlnp 2>/dev/null | grep -q ":$port "; then
        HOLDER=$(ss -tlnp 2>/dev/null | grep ":$port " | awk '{print $NF}' | head -1)
        if echo "$HOLDER" | grep -q "httpd\|apache"; then
            pass "Port $port: held by httpd (expected)"
        else
            warn "Port $port: held by $HOLDER (not httpd - may conflict if apache starts)"
        fi
    else
        pass "Port $port: free (apache can bind)"
    fi
done

# ─── SUMMARY ──────────────────────────────────────────────────────────────────
echo ""
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e " Preflight: ${GREEN}${PASS} pass${NC}  ${YELLOW}${WARN} warn${NC}  ${RED}${FAIL} fail${NC}"

if [[ ${#FAILED_DOMAINS[@]} -gt 0 ]]; then
    echo -e " ${RED}BLOCKING FAILURES on: ${FAILED_DOMAINS[*]}${NC}"
fi

if [[ $SYNTAX_RC -ne 0 ]]; then
    echo -e " ${RED}RESULT: BLOCKED - syntax error prevents restart${NC}"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    exit 1
fi

if [[ $FAIL -gt 0 ]]; then
    echo -e " ${RED}RESULT: BLOCKED - fix failures before restarting${NC}"
    echo " Issues logged to: $ISSUES_FILE"
    echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    exit 1
fi

echo -e " ${GREEN}RESULT: PASS - safe to restart Apache${NC}"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
exit 0
