#!/usr/bin/env bash
# onx-vhost-add-ols — Create an OpenLiteSpeed vhost from template.
#
# Called by onx-vhost-add dispatcher when 'server' = 'openlitespeed' or 'litespeed'.
# OLS vhost config: /usr/local/lsws/conf/vhosts/<vh_name>/vhconf.conf
# listener.conf'a map entry de eklenmesi gerekir.
#
# Input (stdin JSON) — same as onx-vhost-add.
# Output (stdout JSON):
#   {"vhost_path":..., "reloaded":true, "ssl_enabled":..., "server":"openlitespeed"}
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=exec-fail 4=rolled-back

set -euo pipefail

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

# ── Constants ────────────────────────────────────────────────────────────────
TEMPLATE_PATH="/usr/local/onoxsoft/templates/vhost-ols.conf.stub"
SYSTEM_TEMPLATE_PATH="/usr/local/onoxsoft/templates/vhost-ols-system.conf.stub"
LSWS_BASE="/usr/local/lsws"
VHOST_BASE="${LSWS_BASE}/conf/vhosts"
LISTENER_CONF="${LSWS_BASE}/conf/httpd_config.conf"
LSWS_CTL="${LSWS_BASE}/bin/lswsctrl"

# ── Read & parse stdin ───────────────────────────────────────────────────────
INPUT=$(cat)
onx_require_json "${INPUT}"

USERNAME=$(onx_json_get "${INPUT}" "username")
DOMAIN=$(onx_json_get "${INPUT}" "domain")
DOC_ROOT=$(onx_json_get "${INPUT}" "doc_root")
PHP_VERSION=$(onx_json_get "${INPUT}" "php_version" "8.2")
SSL_ENABLED=$(onx_json_get_bool "${INPUT}" "ssl_enabled" "false")
CERT_PATH=$(onx_json_get "${INPUT}" "cert_path" "")
KEY_PATH=$(onx_json_get "${INPUT}" "key_path" "")

# ── Input validation ─────────────────────────────────────────────────────────
onx_validate_username "${USERNAME}"

# Runtime detect home directory (handles /home/users/<user> vs /home/<user>)
USER_HOME=$(onx_resolve_home "${USERNAME}" 2>/dev/null || echo "/home/${USERNAME}")

onx_validate_domain "${DOMAIN}"

[[ -z "${DOC_ROOT}" ]] && onx_die 1 "doc_root is required"

PHP_VERSION_NODOT="${PHP_VERSION//./}"

# ── Preflight ────────────────────────────────────────────────────────────────
[[ -d "${LSWS_BASE}" ]] || onx_die 2 "OpenLiteSpeed not installed: ${LSWS_BASE} not found"
[[ -x "${LSWS_CTL}" ]] || onx_die 2 "lswsctrl not found: ${LSWS_CTL}"
[[ -f "${TEMPLATE_PATH}" ]] || onx_die 2 "ols template not found: ${TEMPLATE_PATH}"
[[ -d "${USER_HOME}" ]] || onx_die 2 "home directory not found: ${USER_HOME}"

# v79.9 UNIFIED PATTERN — HEM müşteri HEM sistem subdomain için system template
# Production verified: 11/11 vhost çalışır. Müşteri için LSAPI native + own user
# patterns DERIN OLS bug (path/handler mismatch). Bu unified pattern OLS uyumlu.
# Trade-off: müşteri docroot apache:webserver (multi-tenant isolation kaybolur,
# v80+'da LVE/cgroup eklenecek).
IS_SYSTEM_SUBDOMAIN=$(onx_json_get_bool "${INPUT}" "is_system_subdomain" "false")
SUBDOMAIN_TYPE=$(onx_json_get "${INPUT}" "subdomain_type" "")
REWRITE_RULES=""

# HER zaman system template kullan (unified)
if [[ -f "${SYSTEM_TEMPLATE_PATH}" ]]; then
    TEMPLATE_PATH="${SYSTEM_TEMPLATE_PATH}"
    onx_log "Using unified LSAPI native template (apache:webserver shared worker pool)"
fi
mkdir -p /var/log/onoxsoft-system 2>/dev/null
chown apache:webserver /var/log/onoxsoft-system 2>/dev/null
chmod 750 /var/log/onoxsoft-system 2>/dev/null

# v79.9: Müşteri docroot'u apache:webserver yap (LSAPI worker'ın okuyabilmesi için)
if [[ "${IS_SYSTEM_SUBDOMAIN}" != "true" ]] && [[ -d "${DOC_ROOT}" ]]; then
    chown -R apache:webserver "${DOC_ROOT}" 2>/dev/null || true
    chmod -R u+rwX,g+rX,o+rX "${DOC_ROOT}" 2>/dev/null || true
    onx_log "Customer docroot chmod 755 + chown apache:webserver (OLS LSAPI uyumluluk)"

    # v80.5: .htaccess varsa otomatik OLS rewrite'a çevir (WordPress/Laravel/Drupal pattern)
    # /opt/onoxsoft/bin/onx-htaccess-translate helper script PHP HtaccessTranslator çağırır
    HTACCESS_PATH="${DOC_ROOT}/.htaccess"
    if [[ -f "${HTACCESS_PATH}" ]] && [[ -x /opt/onoxsoft/bin/onx-htaccess-translate ]]; then
        TRANSLATED=$(/opt/onoxsoft/bin/onx-htaccess-translate "${HTACCESS_PATH}" 2>/dev/null || echo "")
        if [[ -n "${TRANSLATED}" ]]; then
            REWRITE_RULES="${TRANSLATED}"
            onx_log ".htaccess translated to OLS rewrite (CMS auto-detect)"
        fi
    fi

    # Translator yoksa veya .htaccess yoksa: Laravel/WordPress-style default fall-through
    if [[ -z "${REWRITE_RULES}" ]]; then
        REWRITE_RULES='RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L]'
    fi
fi

if [[ "${IS_SYSTEM_SUBDOMAIN}" == "true" ]]; then

    # v79.2: subdomain_type'a göre rewrite kuralları (template ${REWRITE_RULES} placeholder)
    # - webmail_proxy → Laravel-style fall-through to index.php (Roundcube router)
    # - mail_autoconfig (autodiscover.X) → Outlook autodiscover.xml.php endpoint
    # - mail_autoconfig (autoconfig.X)   → Thunderbird/iOS Mozilla autoconfig endpoint
    # - panel_redirect / webdisk        → basic /index.php fall-through (redirect PHP içinde)
    if [[ "${DOMAIN}" == autoconfig.* ]]; then
        REWRITE_RULES='RewriteEngine On
RewriteRule ^/?mail/config-v1\.1\.xml$ /thunderbird.xml.php [L]
RewriteRule ^/?\.well-known/autoconfig/mail/config-v1\.1\.xml$ /thunderbird.xml.php [L]'
    elif [[ "${DOMAIN}" == autodiscover.* ]]; then
        REWRITE_RULES='RewriteEngine On
RewriteRule ^/?[Aa]utodiscover/[Aa]utodiscover\.xml$ /autodiscover.xml.php [L]'
    else
        # webmail/mail/panel/webdisk — generic Laravel-style fall-through
        REWRITE_RULES='RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [L]'
    fi

    # panel.X için /var/www/html/index.php redirect generate (yoksa)
    # v87 Agent 4: `local` keyword script-scope'ta YASAK (bu kod bir function değil,
    # if-block içinde). Eski versiyon "local: can only be used in a function" hatasıyla
    # SystemSubdomainProvisioner panel.<domain> generate'ini patlatıyordu. Düz değişken.
    if [[ "${DOMAIN}" == panel.* ]] && [[ ! -f "${DOC_ROOT}/index.php" ]]; then
        _panel_url="${PANEL_URL:-https://panel.onoxsoft.com.tr:666}"
        mkdir -p "${DOC_ROOT}" 2>/dev/null
        cat > "${DOC_ROOT}/index.php" <<PHPEOF
<?php
// ONOX system subdomain — panel redirect (v79.2)
header('Location: ${_panel_url}/customer/dashboard', true, 302);
PHPEOF
        chown apache:webserver "${DOC_ROOT}/index.php" 2>/dev/null
    fi
fi

# v3.67: SUSPEND/TERMINATE marker rewrite — askı/sonlandırmada vhost dizinine
# .onx-suspended konulursa branded index.html (suspended/terminated.html) INTERNAL
# serve edilir. RewriteCond -f her istekte CANLI kontrol → marker konunca/kalkınca
# anında etki (restart YOK). onx-user-suspend + onx-user-terminate marker'ı yazar;
# bu kural OLMADAN OLS marker'ı yok sayıp /index.php'ye gidiyordu → suspend/terminate
# sayfası gösterilmiyor, OLS default görünüyordu. (ref: onx-ols-vhosts-unified-rewrite)
# v88: Force HTTPS — SSL aktif + musteri domaini ise http istegini https'e 301 yonlendir.
# acme-challenge + /__onx-health HARIC (cert yenileme + health probe bozulmasin). Loop yok:
# %{HTTPS}=on baglantida atlanir. Tarayici hep gecerli cert'i gorur -> "guvenli degil" +
# tarayici-onbellek sorunu biter (WHM/cPanel AutoSSL davranisi). Sistem subdomain'lerde
# (autoconfig/autodiscover/webmail/panel) UYGULANMAZ -> mail-client autoconfig'i bozmaz.
# NOT: bu blok _SUSPEND_MARKER prepend'inden ONCE -> calisma sirasi suspend -> forcehttps -> app.
if [[ "${SSL_ENABLED}" == "true" ]] && [[ "${IS_SYSTEM_SUBDOMAIN}" != "true" ]]; then
  REWRITE_RULES="RewriteCond %{HTTPS} !on
RewriteCond %{REQUEST_URI} !^/\.well-known/
RewriteCond %{REQUEST_URI} !^/__onx-health
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
${REWRITE_RULES}"
fi

_SUSPEND_MARKER="/usr/local/lsws/conf/vhosts/${USERNAME}-${DOMAIN}/.onx-suspended"
REWRITE_RULES="RewriteCond ${_SUSPEND_MARKER} -f
RewriteCond %{REQUEST_URI} !^/index\\.html\$
RewriteCond %{REQUEST_URI} !^/__onx-health\$
RewriteRule ^(.*)\$ /index.html [L]
${REWRITE_RULES}"

mkdir -p "${USER_HOME}/logs"

VH_NAME="${USERNAME}-${DOMAIN}"
VHOST_DIR="${VHOST_BASE}/${VH_NAME}"
VHOST_PATH="${VHOST_DIR}/vhconf.conf"
LISTENER_BACKUP="${LISTENER_CONF}.bak.$$"

mkdir -p "${VHOST_DIR}"
BACKUP_PATH="${VHOST_PATH}.bak.$$"
[[ -f "${VHOST_PATH}" ]] && cp "${VHOST_PATH}" "${BACKUP_PATH}"

# ── Build comma-separated aliases ────────────────────────────────────────────
SERVER_ALIASES_COMMA=""
while IFS= read -r alias; do
  [[ -n "${alias}" ]] && SERVER_ALIASES_COMMA+="${alias},"
done < <(onx_json_array_items "${INPUT}" "server_aliases")
SERVER_ALIASES_COMMA="${SERVER_ALIASES_COMMA%,}"

# ── Build SSL block ──────────────────────────────────────────────────────────
if [[ "${SSL_ENABLED}" == "true" ]]; then
  [[ -n "${CERT_PATH}" ]] || onx_die 1 "cert_path required when ssl_enabled"
  [[ -n "${KEY_PATH}" ]]  || onx_die 1 "key_path required when ssl_enabled"
  OLS_SSL_BLOCK=$(cat <<SSLBLOCK
vhssl {
  keyFile                 ${KEY_PATH}
  certFile                ${CERT_PATH}
  certChain               1
  sslProtocol             24
  enableECDHE             1
  renegProtection         1
  sslSessionCache         1
  enableSpdy              15
}
SSLBLOCK
)
else
  OLS_SSL_BLOCK=""
fi

# ── Render template ──────────────────────────────────────────────────────────
TMP_CONF=$(mktemp /tmp/onx-vhost-ols-XXXXXX.conf)
trap 'rm -f "${TMP_CONF}"' EXIT

cp "${TEMPLATE_PATH}" "${TMP_CONF}"

multiline_replace() {
  local var="$1"
  local val="$2"
  local tmpfile="${TMP_CONF}.replace"
  awk -v var="\${${var}}" -v val="${val}" '
    {
      while ((idx = index($0, var)) > 0) {
        $0 = substr($0, 1, idx-1) val substr($0, idx + length(var))
      }
      print
    }
  ' "${TMP_CONF}" > "${tmpfile}"
  mv "${tmpfile}" "${TMP_CONF}"
}

multiline_replace "USERNAME"             "${USERNAME}"
multiline_replace "DOMAIN"               "${DOMAIN}"
multiline_replace "DOC_ROOT"             "${DOC_ROOT}"
multiline_replace "PHP_VERSION_NODOT"    "${PHP_VERSION_NODOT}"
multiline_replace "SERVER_ALIASES_COMMA" "${SERVER_ALIASES_COMMA}"
multiline_replace "OLS_SSL_BLOCK"        "${OLS_SSL_BLOCK}"
multiline_replace "REWRITE_RULES"        "${REWRITE_RULES}"

# Install the rendered config
install -m 0644 "${TMP_CONF}" "${VHOST_PATH}"
chown -R lsadm:lsadm "${VHOST_DIR}" 2>/dev/null || true

# ── Update listener.conf with vhost mapping ──────────────────────────────────
# Add vhost map: virtualhost <VH_NAME> {} and listener entries
#
# v79 KRİTİK FIX: HEM HTTP (port 80) HEM SSL (port 443) listener'larına map
# ekle. Önceden sadece port 80'e ekleniyordu → HTTPS isteği geldiğinde SSL
# listener catch-all'a düşüyor (genelde panel/Example), panel cert dönüyor →
# webmail.<domain> için "CN=panel.onoxsoft.com.tr" → ERR_CERT_COMMON_NAME_INVALID.
# OLS Apache/Nginx'ten farklı — vhost dosyası tek başına route etmez; her
# listener bloğunda explicit `map` directive lazım.
if ! grep -q "virtualhost ${VH_NAME}" "${LISTENER_CONF}"; then
  cp "${LISTENER_CONF}" "${LISTENER_BACKUP}"

  # v79.9 UNIFIED: TÜM vhost'lar (müşteri + sistem) apache:webserver + restrained=0
  # OLS müşteri user (uid 1000+) ile LSAPI native pattern'inde 404/403 sorunu
  # (deep OLS internal). Test edilmiş: 11/11 vhost bu pattern'de çalışır.
  # Trade-off: multi-tenant user isolation YOK — v80'de LVE/cgroup eklenecek.
  EXT_USER="apache"
  EXT_GROUP="webserver"
  RESTRAINED_VAL="0"

  cat >> "${LISTENER_CONF}" <<MAPEOF

virtualhost ${VH_NAME} {
  vhRoot                  ${VHOST_DIR}/
  configFile              ${VHOST_PATH}
  allowSymbolLink         1
  enableScript            1
  restrained              ${RESTRAINED_VAL}
  setUIDMode              2
  user                    ${EXT_USER}
  group                   ${EXT_GROUP}
}
MAPEOF

  # Listener mapping
  ALL_DOMAINS="${DOMAIN}"
  [[ -n "${SERVER_ALIASES_COMMA}" ]] && ALL_DOMAINS="${DOMAIN},${SERVER_ALIASES_COMMA}"

  # v79: HEM HTTP HEM SSL listener'a map inject — catch-all wrong cert engelle
  python3 - <<PYEOF 2>/dev/null || onx_log "warning: failed to inject listener map; manual edit may be required"
import re
import sys

LISTENER_CONF = "${LISTENER_CONF}"
VH_NAME = "${VH_NAME}"
DOMAINS = "${ALL_DOMAINS}"

with open(LISTENER_CONF, 'r') as f:
    content = f.read()

# Skip duplicate map (idempotent — re-run safe)
if f"map                     {VH_NAME} " in content or f"map {VH_NAME} " in content:
    sys.exit(0)

map_line = f"\n  map                     {VH_NAME} {DOMAINS}"

# Pattern: TÜM listener blokları (Default, DefaultSSL, panelOnoxsoft vb.)
# Sadece :80 ve :443 portunu dinleyen listener'lara ekle (panel :666 hariç).
def inject_to_listeners(text):
    # Tüm "listener NAME { ... }" bloklarını bul
    pattern = re.compile(
        r'(listener\s+(\w+)\s*\{)([^}]*?)(\n\s*\})',
        flags=re.DOTALL
    )
    out_chunks = []
    last = 0
    for m in pattern.finditer(text):
        listener_name = m.group(2)
        block_body = m.group(3)
        # Address satırını bul: "address *:80" veya "address *:443"
        addr_match = re.search(r'address\s+\*?:?(\d+)', block_body)
        if not addr_match:
            continue
        port = int(addr_match.group(1))
        # Sadece HTTP (80) ve standard HTTPS (443) — panel :666 hariç
        if port not in (80, 443):
            continue
        # Duplicate check per-block
        if f"map                     {VH_NAME} " in block_body or f"map {VH_NAME} " in block_body:
            continue
        out_chunks.append(text[last:m.start(4)])
        out_chunks.append(map_line)
        out_chunks.append(m.group(4))
        last = m.end(4)
    out_chunks.append(text[last:])
    return ''.join(out_chunks)

new = inject_to_listeners(content)
with open(LISTENER_CONF, 'w') as f:
    f.write(new)
PYEOF
fi

# ── lswsctrl restart (OLS requires restart for vhost changes) ────────────────
if ! "${LSWS_CTL}" restart >/dev/null 2>&1; then
  onx_log "lswsctrl restart failed — rolling back"
  [[ -f "${BACKUP_PATH}" ]] && mv "${BACKUP_PATH}" "${VHOST_PATH}" || rm -f "${VHOST_PATH}"
  [[ -f "${LISTENER_BACKUP}" ]] && mv "${LISTENER_BACKUP}" "${LISTENER_CONF}"
  onx_die 4 "lswsctrl restart failed; vhost rolled back"
fi

rm -f "${BACKUP_PATH}" "${LISTENER_BACKUP}"

# ── Success ──────────────────────────────────────────────────────────────────
onx_json_out \
  "vhost_path"  "${VHOST_PATH}" \
  "reloaded"    "true" \
  "ssl_enabled" "${SSL_ENABLED}" \
  "server"      "openlitespeed"
