#!/usr/bin/env bash
# =============================================================================
# onx-caddy-config-prepare — Ensure Caddy actually serves vhost files.
#
# v77: WebServerManager::switchTo() → CaddyAdapter::prepareForActivation()
# Called BEFORE caddy systemctl start so the daemon comes up with a working
# Caddyfile that imports /etc/caddy/sites/*.caddy and has a panel vhost.
#
# Strategy:
#   - Ensure /etc/caddy/sites/ exists (mkdir -p)
#   - Ensure /etc/caddy/Caddyfile has `import sites/*.caddy` directive
#     (idempotent — only appended if missing)
#   - Generate /etc/caddy/sites/onoxsoft-panel.caddy for panel vhost
#     (panel.<hostname>:666 → reverse_proxy localhost:9000 / php-fpm socket)
#   - Run `caddy validate` gate (rollback Caddyfile on bad config)
#   - Idempotent — re-runs leave config unchanged if everything in place
#
# Input (stdin JSON):
#   {}                              (no args — discovers panel hostname/port)
#
# Output (stdout JSON):
#   { "ok": true, "import_added": bool, "panel_vhost": bool,
#     "sites_dir_created": bool, "validate_ok": bool, "message": "..." }
#
# Exit codes (per _lib/common.sh convention):
#   0  — success
#   1  — invalid input
#   2  — preflight fail (caddy not installed)
#   3  — execution fail (write)
#   4  — execution fail + rollback succeeded (validate failed)
#
# Sudoers:
#   apache ALL=(root) NOPASSWD: /usr/local/onoxsoft/bin/onx-caddy-config-prepare
#
# Deployed to: /usr/local/onoxsoft/bin/onx-caddy-config-prepare
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
# shellcheck source=_lib/common.sh
source "${SCRIPT_DIR}/_lib/common.sh"

# ── Constants ────────────────────────────────────────────────────────────────
CADDY_DIR="/etc/caddy"
CADDYFILE="${CADDY_DIR}/Caddyfile"
SITES_DIR="${CADDY_DIR}/sites"
PANEL_VHOST="${SITES_DIR}/onoxsoft-panel.caddy"
PANEL_PORT="${ONOX_PANEL_SSL_PORT:-666}"
PANEL_CERT_DIR="/etc/onoxsoft/ssl"

# ── Preflight ────────────────────────────────────────────────────────────────
command -v caddy >/dev/null 2>&1 || onx_die 2 "caddy not found in PATH"

# ── Read input (no args used) ────────────────────────────────────────────────
onx_json_input

# ── Discover panel hostname + FPM socket (for reverse_proxy target) ──────────
PANEL_HOST=$(hostname -f 2>/dev/null || hostname || echo "panel")

# FPM socket — try common locations (mirror WebServerManager::detectPhpSock logic)
discover_fpm_sock() {
    local candidates=(
        "/var/opt/remi/php82/run/php-fpm/onoxsoft-panel.sock"
        "/var/opt/remi/php82/run/php-fpm/onoxsoft.sock"
        "/run/php-fpm/onoxsoft.sock"
        "/run/php82-php-fpm/onoxsoft.sock"
        "/run/php-fpm/www.sock"
        "/run/php/php8.2-fpm-onoxsoft.sock"
        "/var/run/php-fpm/www.sock"
    )
    local sock
    for sock in "${candidates[@]}"; do
        [[ -S "$sock" ]] && { printf '%s' "$sock"; return 0; }
    done
    # Glob fallback
    for sock in /var/opt/remi/*/run/php-fpm/*.sock /run/php-fpm/*.sock /run/php/*.sock; do
        [[ -S "$sock" ]] || continue
        if [[ "$sock" == *onoxsoft* || "$sock" == *panel* ]]; then
            printf '%s' "$sock"; return 0
        fi
    done
    # Last resort
    for sock in /run/php-fpm/*.sock; do
        [[ -S "$sock" ]] && { printf '%s' "$sock"; return 0; }
    done
    return 1
}

FPM_SOCK=$(discover_fpm_sock || echo "/run/php-fpm/www.sock")

# Discover panel cert (same logic as ols-listener-prepare)
discover_panel_cert() {
    local cand
    if [[ -f "${PANEL_CERT_DIR}/${PANEL_HOST}.fullchain" ]] && \
       [[ -f "${PANEL_CERT_DIR}/${PANEL_HOST}.key" ]]; then
        PANEL_CERT="${PANEL_CERT_DIR}/${PANEL_HOST}.fullchain"
        PANEL_KEY="${PANEL_CERT_DIR}/${PANEL_HOST}.key"
        return 0
    fi
    for cand in "${PANEL_CERT_DIR}"/*.fullchain; do
        [[ -f "$cand" ]] || continue
        local key="${cand%.fullchain}.key"
        if [[ -f "$key" ]]; then
            PANEL_CERT="$cand"; PANEL_KEY="$key"; return 0
        fi
    done
    return 1
}

PANEL_CERT=""
PANEL_KEY=""
PANEL_CERT_FOUND="false"
if discover_panel_cert; then
    PANEL_CERT_FOUND="true"
fi

# ── Ensure /etc/caddy/sites/ exists ──────────────────────────────────────────
SITES_DIR_CREATED="false"
if [[ ! -d "${SITES_DIR}" ]]; then
    mkdir -p "${SITES_DIR}"
    chmod 0755 "${SITES_DIR}"
    chown root:caddy "${SITES_DIR}" 2>/dev/null || chown root:root "${SITES_DIR}"
    SITES_DIR_CREATED="true"
    onx_log "Created sites dir: ${SITES_DIR}"
fi

# ── Ensure Caddyfile exists ──────────────────────────────────────────────────
CADDYFILE_BACKUP=""
if [[ ! -f "${CADDYFILE}" ]]; then
    # Initialize empty Caddyfile (just the import directive — added below)
    install -m 0644 /dev/null "${CADDYFILE}"
    chown root:caddy "${CADDYFILE}" 2>/dev/null || chown root:root "${CADDYFILE}"
    onx_log "Initialized empty Caddyfile: ${CADDYFILE}"
fi

# ── Add import directive if missing ──────────────────────────────────────────
IMPORT_ADDED="false"
# Match `import sites/*.caddy` (whitespace tolerant, glob-only)
if ! grep -qE "^[[:space:]]*import[[:space:]]+sites/\*\.caddy[[:space:]]*$" "${CADDYFILE}"; then
    # Backup before mutating
    CADDYFILE_BACKUP="${CADDYFILE}.bak-$(date +%s)"
    cp -p "${CADDYFILE}" "${CADDYFILE_BACKUP}"
    onx_rollback_register "mv -f '${CADDYFILE_BACKUP}' '${CADDYFILE}'"

    # Prepend import directive + global block — global directives must be at TOP.
    # v77.6: `auto_https disable_redirects` global block — Caddy automatic cert
    # basma/redirect agresif davranisini kapatir; vhost'lar tls /path /path
    # veya tls internal ile cert verir. www.* alias gibi DNS yoksa NXDOMAIN
    # rate limit (HTTP 429 Let's Encrypt) spam'i onlenir.
    TMPF=$(mktemp -t onx-caddyfile-XXXXXX)
    chmod 0644 "${TMPF}"
    {
        printf '# v77.6: panel-managed Caddyfile (added by onx-caddy-config-prepare)\n'
        printf '{\n'
        printf '\tauto_https disable_redirects\n'
        printf '}\n'
        printf '\n'
        printf 'import sites/*.caddy\n'
        printf '\n'
        cat "${CADDYFILE}"
    } > "${TMPF}"
    mv -f "${TMPF}" "${CADDYFILE}"
    chmod 0644 "${CADDYFILE}"
    IMPORT_ADDED="true"
    onx_log "Added global block + 'import sites/*.caddy' to ${CADDYFILE}"
fi

# ── v77.6: Mevcut Caddyfile'a auto_https directive yoksa global block ekle ──
# (import zaten varsa yukarıdaki blok atlanır, ama global directive eksik olabilir)
if ! grep -qE "auto_https[[:space:]]+(disable_redirects|disable_certs|off)" "${CADDYFILE}"; then
    if grep -qE "^[[:space:]]*\{" "${CADDYFILE}"; then
        # Mevcut global block içine inject (ilk { satırından sonra)
        sed -i '0,/^[[:space:]]*\{/{s//&\n\tauto_https disable_redirects/}' "${CADDYFILE}"
    else
        # Global block yok — başa ekle
        TMPF=$(mktemp -t onx-caddyfile-XXXXXX)
        {
            printf '# v77.6: panel-managed global block\n'
            printf '{\n'
            printf '\tauto_https disable_redirects\n'
            printf '}\n'
            printf '\n'
            cat "${CADDYFILE}"
        } > "${TMPF}"
        mv -f "${TMPF}" "${CADDYFILE}"
        chmod 0644 "${CADDYFILE}"
    fi
    onx_log "Added 'auto_https disable_redirects' global to ${CADDYFILE}"
fi

# ── Generate panel vhost (onoxsoft-panel.caddy) ──────────────────────────────
PANEL_VHOST_WRITTEN="false"
PANEL_VHOST_BACKUP=""

# Backup existing panel vhost if present (so validate failure can restore)
if [[ -f "${PANEL_VHOST}" ]]; then
    PANEL_VHOST_BACKUP="${PANEL_VHOST}.bak-$(date +%s)"
    cp -p "${PANEL_VHOST}" "${PANEL_VHOST_BACKUP}"
    onx_rollback_register "mv -f '${PANEL_VHOST_BACKUP}' '${PANEL_VHOST}'"
else
    onx_rollback_register "rm -f '${PANEL_VHOST}'"
fi

trap 'onx_rollback_run' ERR

# Panel docroot — Laravel public/
# v77.5: Path detect — installer'a göre değişir. Onoxsoft default /opt/onoxsoft/public.
PANEL_DOCROOT="/opt/onoxsoft/public"
[[ -d "$PANEL_DOCROOT" ]] || PANEL_DOCROOT="/var/www/onoxsoft/public"
[[ -d "$PANEL_DOCROOT" ]] || PANEL_DOCROOT="/usr/share/onoxsoft/public"

# Build TLS block: use panel cert if found, else `tls internal` (self-signed)
if [[ "${PANEL_CERT_FOUND}" == "true" ]]; then
    TLS_BLOCK="    tls ${PANEL_CERT} ${PANEL_KEY}"
else
    # Caddy `tls internal` issues a local CA cert (browser warning, but works)
    TLS_BLOCK="    tls internal"
fi

TMP_VHOST=$(mktemp -t onx-caddy-panel-XXXXXX.caddy)
chmod 0644 "${TMP_VHOST}"
cat > "${TMP_VHOST}" <<PANELEOF
# /etc/caddy/sites/onoxsoft-panel.caddy
# v77: panel vhost — generated by onx-caddy-config-prepare
# Auto-regenerated on each Caddy activation; safe to manually edit but will be overwritten on switch.

${PANEL_HOST}:${PANEL_PORT} {
${TLS_BLOCK}

    root * ${PANEL_DOCROOT}

    encode gzip zstd

    # PHP via FPM socket
    php_fastcgi unix/${FPM_SOCK} {
        index index.php
    }

    file_server

    log {
        output file /var/log/caddy/onoxsoft-panel.log {
            roll_size 50mb
            roll_keep 7
        }
        format json
    }
}
PANELEOF

mv -f "${TMP_VHOST}" "${PANEL_VHOST}"
chmod 0644 "${PANEL_VHOST}"
chown root:caddy "${PANEL_VHOST}" 2>/dev/null || chown root:root "${PANEL_VHOST}"
PANEL_VHOST_WRITTEN="true"
onx_log "Wrote panel vhost: ${PANEL_VHOST}"

# Ensure caddy log dir exists
mkdir -p /var/log/caddy
chown caddy:caddy /var/log/caddy 2>/dev/null || true

# ── caddy validate gate ──────────────────────────────────────────────────────
# Run as root since we own files; --adapter caddyfile default for .caddy stanzas.
VALIDATE_OK="false"
if VALIDATE_OUT=$(caddy validate --config "${CADDYFILE}" --adapter caddyfile 2>&1); then
    VALIDATE_OK="true"
    onx_log "caddy validate OK"
else
    onx_log "caddy validate FAILED: ${VALIDATE_OUT}"
    false  # trigger ERR trap → rollback
fi

# Disable trap before success output
trap - ERR

# Clean up backups on success (keep last for forensics — leave .bak-* alone)

# ── Success ──────────────────────────────────────────────────────────────────
onx_json_out \
    "ok"                 "true" \
    "import_added"       "${IMPORT_ADDED}" \
    "panel_vhost"        "${PANEL_VHOST_WRITTEN}" \
    "sites_dir_created"  "${SITES_DIR_CREATED}" \
    "panel_cert_found"   "${PANEL_CERT_FOUND}" \
    "validate_ok"        "${VALIDATE_OK}" \
    "fpm_sock"           "${FPM_SOCK}" \
    "panel_host"         "${PANEL_HOST}" \
    "panel_port"         "${PANEL_PORT}" \
    "message"            "caddy config prepare ok"

exit 0
