#!/usr/bin/env bash
# onx-phpmyadmin-doctor — phpMyAdmin & SSO end-to-end diagnostic + auto-repair.
#
# Bu script panel UI'dan (/admin/mysql "phpMyAdmin Doktor") tetiklenir.
# /phpmyadmin/index.php?onx_sso=... 404 veya signon bozuksa çalıştırılır.
#
# Kontrol edilen 9 nokta:
#   1. phpMyAdmin paketi kurulu mu (RHEL: rpm -q phpMyAdmin, Debian: dpkg)
#   2. /usr/share/phpMyAdmin (RHEL) veya /usr/share/phpmyadmin (Debian) dizini var mı
#   3. /etc/httpd/conf.d/phpMyAdmin.conf (RHEL) veya etkin conf (Debian)
#   4. Panel vhost (onoxsoft-panel.conf) içinde /phpmyadmin Alias var mı (SSL bloğunda)
#   5. /etc/phpMyAdmin/onx-signon.php var mı + mode 0640 root:apache
#   6. /etc/phpMyAdmin/config.inc.php içinde ONOXSOFT-SSO-BEGIN marker var mı
#   7. blowfish_secret atanmış mı (boş değil)
#   8. Apache httpd_can_network_connect SELinux boolean
#   9. Panel API /api/pma-sso/consume reachable (localhost curl)
#
# Input (stdin JSON):
#   {
#     "repair":           true/false   (default: false — sadece diagnose)
#     "panel_ssl_port":   666           (default: 666)
#     "panel_hostname":   "panel.host"  (default: hostname -f)
#     "onox_home":        "/usr/local/onoxsoft/panel"  (default)
#   }
#
# Output (stdout JSON):
#   {
#     "ok":     true/false,
#     "checks": {check_name: {status:"ok|warn|fail", message:"...", fixed:bool}},
#     "actions": ["Şunu yaptım: ...", ...],
#     "errors": [...]
#   }
#
# Exit codes: 0=ok 2=preflight 3=execution

set -euo pipefail

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

# ── Input ──────────────────────────────────────────────────────────────────
onx_json_input
REPAIR=$(onx_json_field "repair" "false")
PANEL_SSL_PORT=$(onx_json_field "panel_ssl_port" "666")
PANEL_HOSTNAME=$(onx_json_field "panel_hostname" "$(hostname -f 2>/dev/null || hostname)")
ONOX_HOME=$(onx_json_field "onox_home" "/usr/local/onoxsoft/panel")

require_root

# ── OS detect ──────────────────────────────────────────────────────────────
OS_FAMILY=""
WEB_CONF_DIR=""
WEB_SVC=""
WEB_USER=""
WEB_GROUP=""
PMA_DIR=""
PMA_ETC=""
PMA_APACHE_CONF=""

if [[ -f /etc/redhat-release ]] || [[ -f /etc/almalinux-release ]] || [[ -f /etc/rocky-release ]]; then
    OS_FAMILY="rhel"
    WEB_CONF_DIR="/etc/httpd/conf.d"
    WEB_SVC="httpd"
    WEB_USER="apache"
    WEB_GROUP="apache"
    PMA_DIR="/usr/share/phpMyAdmin"
    PMA_ETC="/etc/phpMyAdmin"
    PMA_APACHE_CONF="/etc/httpd/conf.d/phpMyAdmin.conf"
elif [[ -f /etc/debian_version ]]; then
    OS_FAMILY="debian"
    WEB_CONF_DIR="/etc/apache2/sites-available"
    WEB_SVC="apache2"
    WEB_USER="www-data"
    WEB_GROUP="www-data"
    PMA_DIR="/usr/share/phpmyadmin"
    PMA_ETC="/etc/phpmyadmin"
    PMA_APACHE_CONF="/etc/apache2/conf-enabled/phpmyadmin.conf"
else
    onx_die 2 "Desteklenmeyen OS — sadece RHEL/Rocky/Alma ve Debian/Ubuntu"
fi

PANEL_VHOST="${WEB_CONF_DIR}/onoxsoft-panel.conf"
PMA_SIGNON="${PMA_ETC}/onx-signon.php"
PMA_CONFIG="${PMA_ETC}/config.inc.php"
# v3.0: LSAPI cross-dir restriction nedeniyle config + signon /usr/share/phpMyAdmin/
# altına da kopyalanır. Doctor'un her iki path'i de tanıması gerekir.
PMA_CONFIG_SHARED="${PMA_DIR}/config.inc.php"
PMA_SIGNON_SHARED="${PMA_DIR}/onx-signon.php"

# ── v1.3: Active web server detection ──────────────────────────────────────
# Panel Apache/Nginx/OLS/Caddy arasında switch'lenebilir (multi-driver mimari).
# phpMyAdmin alias eklenecek web server, AKTİF olan olmalı.
ACTIVE_WEBSERVER=""
CADDY_PANEL_CONF=""

for cand in caddy httpd nginx openlitespeed lshttpd apache2; do
    if systemctl is-active --quiet "${cand}" 2>/dev/null; then
        case "${cand}" in
            caddy)             ACTIVE_WEBSERVER="caddy" ;;
            httpd|apache2)     ACTIVE_WEBSERVER="apache" ;;
            nginx)             ACTIVE_WEBSERVER="nginx" ;;
            openlitespeed|lshttpd) ACTIVE_WEBSERVER="ols" ;;
        esac
        break
    fi
done

# Default: apache (eski davranış korunsun)
[[ -z "${ACTIVE_WEBSERVER}" ]] && ACTIVE_WEBSERVER="apache"

# Caddy panel config path detect
if [[ "${ACTIVE_WEBSERVER}" == "caddy" ]]; then
    for cand in /etc/caddy/sites/onoxsoft-panel.caddy \
                /etc/caddy/conf.d/onoxsoft-panel.caddyfile \
                /etc/caddy/Caddyfile; do
        if [[ -f "$cand" ]] && grep -q "panel\.\|:${PANEL_SSL_PORT}" "$cand" 2>/dev/null; then
            CADDY_PANEL_CONF="$cand"
            break
        fi
    done
fi

onx_log "phpmyadmin-doctor: OS=${OS_FAMILY} repair=${REPAIR} active_ws=${ACTIVE_WEBSERVER} caddy_conf=${CADDY_PANEL_CONF:-n/a} hostname=${PANEL_HOSTNAME} port=${PANEL_SSL_PORT}"

# ── State ──────────────────────────────────────────────────────────────────
declare -A CHECKS_STATUS=()
declare -A CHECKS_MSG=()
declare -A CHECKS_FIXED=()
ACTIONS=()
ERRORS=()
NEED_APACHE_RELOAD=0
NEED_CADDY_RELOAD=0

mark_check() {
    local name="$1" status="$2" msg="$3" fixed="${4:-false}"
    CHECKS_STATUS["$name"]="$status"
    CHECKS_MSG["$name"]="$msg"
    CHECKS_FIXED["$name"]="$fixed"
}

# ──────────────────────────────────────────────────────────────────────────
# CHECK 1: phpMyAdmin paketi kurulu mu
# ──────────────────────────────────────────────────────────────────────────
PMA_INSTALLED=false
if [[ "${OS_FAMILY}" == "rhel" ]]; then
    if rpm -q phpMyAdmin >/dev/null 2>&1; then
        PMA_INSTALLED=true
    fi
elif [[ "${OS_FAMILY}" == "debian" ]]; then
    if dpkg -l phpmyadmin 2>/dev/null | grep -q '^ii'; then
        PMA_INSTALLED=true
    fi
fi

if ${PMA_INSTALLED}; then
    mark_check "package_installed" "ok" "phpMyAdmin paketi kurulu"
else
    if [[ "${REPAIR}" == "true" ]]; then
        onx_log "Package not installed — repairing"
        if [[ "${OS_FAMILY}" == "rhel" ]]; then
            # EPEL ekle (gerekirse)
            if ! dnf repolist enabled 2>/dev/null | grep -qi epel; then
                dnf install -y epel-release >/dev/null 2>&1 \
                    || ERRORS+=("EPEL etkinleştirilemedi")
            fi
            if dnf install -y --enablerepo=epel phpMyAdmin >/dev/null 2>&1; then
                PMA_INSTALLED=true
                ACTIONS+=("phpMyAdmin RPM kuruldu (EPEL)")
                mark_check "package_installed" "ok" "phpMyAdmin RPM kuruldu" "true"
            else
                ERRORS+=("phpMyAdmin RPM install başarısız (dnf çıktısına bak)")
                mark_check "package_installed" "fail" "RPM install başarısız (EPEL erişimi?)"
            fi
        else
            export DEBIAN_FRONTEND=noninteractive
            echo "phpmyadmin phpmyadmin/dbconfig-install boolean false" | debconf-set-selections 2>/dev/null || true
            echo "phpmyadmin phpmyadmin/reconfigure-webserver multiselect" | debconf-set-selections 2>/dev/null || true
            apt-get update >/dev/null 2>&1 || true
            if apt-get install -y phpmyadmin >/dev/null 2>&1; then
                PMA_INSTALLED=true
                ACTIONS+=("phpmyadmin deb kuruldu")
                mark_check "package_installed" "ok" "phpmyadmin deb kuruldu" "true"
            else
                ERRORS+=("phpmyadmin deb install başarısız")
                mark_check "package_installed" "fail" "deb install başarısız"
            fi
        fi
    else
        mark_check "package_installed" "fail" "phpMyAdmin paketi kurulu DEĞİL — repair çalıştır"
    fi
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 2: phpMyAdmin dizini var mı (paket kurulu ama dosya yok edge case)
# ──────────────────────────────────────────────────────────────────────────
if [[ -d "${PMA_DIR}" ]] && [[ -f "${PMA_DIR}/index.php" ]]; then
    mark_check "directory_exists" "ok" "${PMA_DIR}/index.php mevcut"
else
    mark_check "directory_exists" "fail" "${PMA_DIR} eksik veya bozuk"
    if [[ "${REPAIR}" == "true" ]] && ${PMA_INSTALLED}; then
        # Paket kurulu ama dizin yok → reinstall dene
        onx_log "Directory missing despite package install — reinstalling"
        if [[ "${OS_FAMILY}" == "rhel" ]]; then
            if dnf reinstall -y phpMyAdmin >/dev/null 2>&1; then
                ACTIONS+=("phpMyAdmin reinstall — dizin restore edildi")
                mark_check "directory_exists" "ok" "${PMA_DIR}/index.php restore edildi" "true"
            fi
        fi
    fi
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 3: Standalone Apache conf (RHEL: /etc/httpd/conf.d/phpMyAdmin.conf)
# Bu conf "Require all granted" olmalı — default 127.0.0.1 ile sınırlı
# ──────────────────────────────────────────────────────────────────────────
if [[ -f "${PMA_APACHE_CONF}" ]]; then
    # v1.1: hem "Require all granted" hem "Require local" senaryosunu yakala.
    # EPEL phpMyAdmin RHEL9'da default "Require local" var (== 127.0.0.1).
    if grep -qE "^\s*Require\s+all\s+granted" "${PMA_APACHE_CONF}" 2>/dev/null; then
        mark_check "apache_conf_granted" "ok" "Apache conf erişimi açık (Require all granted)"
    else
        if [[ "${REPAIR}" == "true" ]]; then
            # 3 yaygın kısıtlı pattern → all granted
            sed -i 's|^\s*Require\s\+ip\s\+127\.0\.0\.1|    Require all granted|g' "${PMA_APACHE_CONF}"
            sed -i 's|^\s*Require\s\+ip\s\+::1|    # Require ip ::1 (replaced by all granted)|g' "${PMA_APACHE_CONF}"
            sed -i 's|^\s*Require\s\+local\s*$|    Require all granted|g' "${PMA_APACHE_CONF}"
            # Bazı conf'larda <RequireAny> blok içinde değişir — ek olarak top-level garanti
            if ! grep -qE "^\s*Require\s+all\s+granted" "${PMA_APACHE_CONF}" 2>/dev/null; then
                # Hala yoksa <Directory /usr/share/phpMyAdmin/> içine inject et
                if grep -q "<Directory /usr/share/phpMyAdmin" "${PMA_APACHE_CONF}" 2>/dev/null; then
                    sed -i '/<Directory \/usr\/share\/phpMyAdmin/a\    Require all granted' "${PMA_APACHE_CONF}"
                fi
            fi
            NEED_APACHE_RELOAD=1
            ACTIONS+=("${PMA_APACHE_CONF}: 'Require all granted' yapıldı (Require local/ip pattern'leri değiştirildi)")
            mark_check "apache_conf_granted" "ok" "Erişim açıldı" "true"
        else
            # Mevcut kısıtı detect et — daha açıklayıcı mesaj
            if grep -qE "^\s*Require\s+local" "${PMA_APACHE_CONF}" 2>/dev/null; then
                mark_check "apache_conf_granted" "warn" "Apache conf: 'Require local' kısıtı var (sadece 127.0.0.1)"
            elif grep -qE "^\s*Require\s+ip\s+127\.0\.0\.1" "${PMA_APACHE_CONF}" 2>/dev/null; then
                mark_check "apache_conf_granted" "warn" "Apache conf: 'Require ip 127.0.0.1' kısıtı var"
            else
                mark_check "apache_conf_granted" "warn" "Apache conf'ta 'Require all granted' bulunamadı"
            fi
        fi
    fi
else
    mark_check "apache_conf_granted" "warn" "${PMA_APACHE_CONF} yok (Debian'da bu beklenebilir)"
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 4: Panel vhost'unda /phpmyadmin handler var mı (web-server-aware)
# Bu KRİTİK — bu olmadan panel:666/phpmyadmin/ 404 verir.
# v1.3: Apache YERINE Caddy/Nginx/OLS aktifse, doğru config'i kontrol/repair eder.
# ──────────────────────────────────────────────────────────────────────────
case "${ACTIVE_WEBSERVER}" in
    caddy)
        # ──────────────────────────────────────────────────────────────────
        # v1.4: Caddy active iken iki şey yapılır:
        #   1. Dedicated FPM pool (onoxsoft-phpmyadmin) deploy + JIT off
        #   2. Caddy panel config'e handle_path /phpmyadmin/* inject — dedicated socket'a
        # Outer php_fastcgi'ye DOKUNULMAZ (panel.sock kalır).
        # ──────────────────────────────────────────────────────────────────
        if [[ -z "${CADDY_PANEL_CONF}" ]] || [[ ! -f "${CADDY_PANEL_CONF}" ]]; then
            mark_check "panel_alias" "fail" "Caddy panel config bulunamadı (/etc/caddy/sites/onoxsoft-panel.caddy)"
            ERRORS+=("Caddy aktif ama panel config dosyası yok — install.sh tam çalışmamış olabilir")
        elif grep -q "handle_path /phpmyadmin/\*" "${CADDY_PANEL_CONF}" 2>/dev/null \
             && grep -q "onoxsoft-phpmyadmin.sock" "${CADDY_PANEL_CONF}" 2>/dev/null \
             && grep -q "redir /phpmyadmin /phpmyadmin/" "${CADDY_PANEL_CONF}" 2>/dev/null; then
            mark_check "panel_alias" "ok" "Caddy panel config'inde phpmyadmin handler + dedicated socket + bare redirect mevcut"
        else
            if [[ "${REPAIR}" == "true" ]]; then
                # 1. Dedicated FPM pool deploy (eğer yoksa)
                POOL_DST="/etc/opt/remi/php82/php-fpm.d/onoxsoft-phpmyadmin.conf"
                POOL_SRC="${ONOX_HOME}/config/onoxsoft/templates/phpmyadmin/fpm-pool.conf.stub"
                FPM_SOCK="/var/opt/remi/php82/run/php-fpm/onoxsoft-phpmyadmin.sock"

                if [[ -f "${POOL_DST}" ]]; then
                    onx_log "Dedicated FPM pool zaten mevcut: ${POOL_DST}"
                elif [[ -f "${POOL_SRC}" ]]; then
                    # Template'i deploy et — WEB_USER environment substitution
                    WEB_USER_EFF="${WEB_USER}"
                    sed "s|\${WEB_USER}|${WEB_USER_EFF}|g" "${POOL_SRC}" > "${POOL_DST}"
                    chown root:root "${POOL_DST}"
                    chmod 0644 "${POOL_DST}"
                    ACTIONS+=("Dedicated FPM pool oluşturuldu: ${POOL_DST}")

                    # PHP-FPM restart (reload bazı versiyonlarda yeni pool'u yüklemez)
                    if systemctl is-active --quiet php82-php-fpm 2>/dev/null; then
                        systemctl restart php82-php-fpm 2>/dev/null && \
                            ACTIONS+=("php82-php-fpm restart (yeni pool aktif)")
                    fi
                else
                    ERRORS+=("FPM pool template bulunamadı: ${POOL_SRC}")
                fi

                # 2. Caddy handler ekle — DEDICATED socket kullan
                # Backup
                cp -a "${CADDY_PANEL_CONF}" "${CADDY_PANEL_CONF}.bak-$(date +%Y%m%d%H%M%S)"

                CADDY_HANDLER="
    # ONOXSOFT phpMyAdmin handler (auto-added by onx-phpmyadmin-doctor v1.5)
    # Dedicated FPM pool — JIT off, isolated open_basedir
    # v1.5: bare path redirect (browser /phpmyadmin → /phpmyadmin/)
    redir /phpmyadmin /phpmyadmin/ permanent
    redir /phpMyAdmin /phpMyAdmin/ permanent
    handle_path /phpmyadmin/* {
        root * /usr/share/phpMyAdmin
        php_fastcgi unix/${FPM_SOCK} {
            env DOCUMENT_ROOT /usr/share/phpMyAdmin
        }
        file_server
    }
    handle_path /phpMyAdmin/* {
        root * /usr/share/phpMyAdmin
        php_fastcgi unix/${FPM_SOCK} {
            env DOCUMENT_ROOT /usr/share/phpMyAdmin
        }
        file_server
    }
"
                # Python ile careful insertion
                tmp_caddy=$(mktemp)
                CADDY_PANEL_CONF_ESCAPED="${CADDY_PANEL_CONF}"
                CADDY_HANDLER_PY="${CADDY_HANDLER}"
                python3 <<PYEOF > "${tmp_caddy}"
import re
src = open('${CADDY_PANEL_CONF_ESCAPED}').read()
handler = '''${CADDY_HANDLER_PY}'''
# v1.5 idempotent cleanup — eski phpMyAdmin handler/redir bloklarını sil
# (outer php_fastcgi'ye DOKUNMA)
src = re.sub(
    r'\n\s*(?:#[^\n]*\n\s*)*handle_path /php[mM]yAdmin/\*\s*\{[^}]*?file_server\s*\}\s*',
    '\n', src, flags=re.DOTALL,
)
# Eski redir satırlarını sil
src = re.sub(r'\n\s*redir /php[mM]yAdmin /php[mM]yAdmin/\s+permanent\s*\n', '\n', src)
# Eski header yorumunu sil (re-inject olacak)
src = re.sub(r'\n\s*# ONOXSOFT phpMyAdmin handler.*?\n', '\n', src)
# Panel block açılışından sonra (catch-all'dan ÖNCE) inject
m = re.search(r'(panel\.[^{]*\{|:[0-9]+\s*\{)', src)
if not m:
    print(src, end='')
    import sys; sys.exit(0)
pos = m.end()
print(src[:pos] + handler + src[pos:], end='')
PYEOF

                if grep -q "handle_path /phpmyadmin" "${tmp_caddy}" 2>/dev/null \
                   && grep -q "onoxsoft-panel.sock" "${tmp_caddy}" 2>/dev/null; then
                    # Outer panel.sock referansının korunduğundan emin ol (regression önlemi)
                    mv "${tmp_caddy}" "${CADDY_PANEL_CONF}"
                    chmod 0644 "${CADDY_PANEL_CONF}"
                    NEED_CADDY_RELOAD=1
                    ACTIONS+=("Caddy panel config'e handle_path /phpmyadmin/* eklendi (dedicated socket: ${FPM_SOCK})")
                    mark_check "panel_alias" "ok" "Caddy handler eklendi (dedicated pool)" "true"
                else
                    rm -f "${tmp_caddy}"
                    if ! grep -q "onoxsoft-panel.sock" "${CADDY_PANEL_CONF}" 2>/dev/null; then
                        ERRORS+=("KRİTİK: outer panel.sock kaybolmuş — backup'tan restore et: ${CADDY_PANEL_CONF}.bak-*")
                    fi
                    ERRORS+=("Caddy panel config'e handler eklenemedi (panel bloğu bulunamadı)")
                    mark_check "panel_alias" "fail" "Handler eklenemedi — manuel"
                fi
            else
                mark_check "panel_alias" "fail" "Caddy panel config'inde handle_path /phpmyadmin yok — /phpmyadmin 404 sebebi"
            fi
        fi
        ;;

    apache)
        # Apache panel vhost (eski mantık)
        if [[ ! -f "${PANEL_VHOST}" ]]; then
            mark_check "panel_alias" "fail" "Apache panel vhost bulunamadı: ${PANEL_VHOST}"
            ERRORS+=("Apache panel vhost yok — install.sh tam çalışmamış olabilir")
        elif grep -qE '^\s*Alias\s+/phpmyadmin\s+' "${PANEL_VHOST}" 2>/dev/null; then
            mark_check "panel_alias" "ok" "Apache panel vhost'unda /phpmyadmin Alias mevcut"
        else
            if [[ "${REPAIR}" == "true" ]]; then
                ALIAS_BLOCK="
    # ONOXSOFT phpMyAdmin Alias (auto-added by onx-phpmyadmin-doctor)
    Alias /phpmyadmin /usr/share/phpMyAdmin
    Alias /phpMyAdmin /usr/share/phpMyAdmin
    <Directory /usr/share/phpMyAdmin>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
    <Directory /usr/share/phpMyAdmin/libraries>
        Require all denied
    </Directory>
    <Directory /usr/share/phpMyAdmin/setup/lib>
        Require all denied
    </Directory>
"
                [[ "${OS_FAMILY}" == "debian" ]] && \
                    ALIAS_BLOCK=$(echo "${ALIAS_BLOCK}" | sed 's|/usr/share/phpMyAdmin|/usr/share/phpmyadmin|g')

                cp -a "${PANEL_VHOST}" "${PANEL_VHOST}.bak-$(date +%Y%m%d%H%M%S)"

                tmp_vhost=$(mktemp)
                awk -v block="${ALIAS_BLOCK}" -v ssl_port="${PANEL_SSL_PORT}" '
                    BEGIN { in_ssl_block = 0; injected = 0 }
                    /^\s*<VirtualHost\s+\*:/ {
                        if (match($0, /\*:[0-9]+/)) {
                            port_str = substr($0, RSTART+2, RLENGTH-2)
                            if (port_str == ssl_port) in_ssl_block = 1
                            else in_ssl_block = 0
                        }
                    }
                    /^\s*<\/VirtualHost>\s*$/ {
                        if (in_ssl_block && !injected) {
                            printf "%s", block
                            injected = 1
                        }
                        in_ssl_block = 0
                    }
                    { print }
                ' "${PANEL_VHOST}" > "${tmp_vhost}"

                if grep -q "/phpmyadmin" "${tmp_vhost}" 2>/dev/null; then
                    mv "${tmp_vhost}" "${PANEL_VHOST}"
                    chmod 0644 "${PANEL_VHOST}"
                    NEED_APACHE_RELOAD=1
                    ACTIONS+=("Apache panel vhost'una /phpmyadmin Alias eklendi (port ${PANEL_SSL_PORT})")
                    mark_check "panel_alias" "ok" "Apache Alias eklendi" "true"
                else
                    rm -f "${tmp_vhost}"
                    ERRORS+=("Apache panel vhost'una Alias eklenemedi (SSL bloğu bulunamadı?)")
                    mark_check "panel_alias" "fail" "Alias eklenemedi — manuel"
                fi
            else
                mark_check "panel_alias" "fail" "Apache panel vhost'unda Alias YOK — /phpmyadmin 404 sebebi"
            fi
        fi
        ;;

    nginx|ols)
        # v1.3 Phase 1 — nginx + OLS sadece warn (manuel eklemeli)
        mark_check "panel_alias" "warn" "${ACTIVE_WEBSERVER} aktif — phpMyAdmin handler manuel eklemeli. Tipik konum: /etc/nginx/conf.d/onoxsoft-panel.conf veya OLS panel vhost. Detay docs."
        ;;

    *)
        mark_check "panel_alias" "warn" "Aktif web server tespit edilemedi (${ACTIVE_WEBSERVER}) — manuel kontrol gerekli"
        ;;
esac

# ──────────────────────────────────────────────────────────────────────────
# CHECK 5: Signon script kurulu mu
# v3.0+ LSAPI/PHP signon'u config.inc.php'nin yanından (PMA_DIR) okur.
# Ek olarak v3.1+ per-DB redirect mantığı içerir (data['db'] varsa ?db= temiz URL).
# ──────────────────────────────────────────────────────────────────────────
if [[ ! -d "${PMA_ETC}" ]] && [[ ! -d "${PMA_DIR}" ]]; then
    mark_check "signon_script" "fail" "${PMA_ETC} ve ${PMA_DIR} yok (phpMyAdmin install eksik)"
else
    # En az bir path'te geçerli signon dosyası var mı?
    signon_active=""
    signon_v31=""
    for cand in "${PMA_SIGNON}" "${PMA_SIGNON_SHARED}"; do
        if [[ -f "$cand" ]] && grep -q "ONOXSOFT" "$cand" 2>/dev/null; then
            signon_active="$cand"
            # v3.1+ marker: per-DB redirect var mı?
            if grep -q "v3\.1\|onx-pma-signon/2\.\|Per-DB focus redirect\|PMA_single_signon_user" "$cand" 2>/dev/null; then
                signon_v31="$cand"
            fi
            break
        fi
    done

    if [[ -n "$signon_active" ]]; then
        # Mode + owner kontrolü (sadece /etc/phpMyAdmin path için katı; /usr/share root:apache 0644 olabilir)
        actual_mode=$(stat -c "%a" "$signon_active" 2>/dev/null || echo "000")
        actual_owner=$(stat -c "%U:%G" "$signon_active" 2>/dev/null || echo "?:?")
        # Kabul edilebilir mode set'i: 640, 644 (v3.0 deploy 644 root:apache yapıyor)
        good_mode=false
        case "$actual_mode" in
            640|644) good_mode=true ;;
        esac
        good_owner=false
        case "$actual_owner" in
            "root:${WEB_GROUP}"|"root:root") good_owner=true ;;
        esac

        if $good_mode && $good_owner; then
            if [[ -n "$signon_v31" ]]; then
                mark_check "signon_script" "ok" "Signon script v3.1+ aktif: ${signon_active}"
            else
                mark_check "signon_script" "warn" "Signon script mevcut ama v3.1 redirect mantığı yok: ${signon_active}"
            fi
        else
            if [[ "${REPAIR}" == "true" ]]; then
                chown "root:${WEB_GROUP}" "$signon_active"
                chmod 0640 "$signon_active"
                ACTIONS+=("Signon script izinleri düzeltildi (0640 root:${WEB_GROUP})")
                mark_check "signon_script" "ok" "İzinler düzeltildi" "true"
            else
                mark_check "signon_script" "warn" "İzinler yanlış: ${actual_mode} ${actual_owner}"
            fi
        fi
    else
        if [[ "${REPAIR}" == "true" ]]; then
            SRC_SIGNON="${ONOX_HOME}/config/onoxsoft/templates/phpmyadmin/onx-signon.php.stub"
            if [[ -f "${SRC_SIGNON}" ]]; then
                # Hem /etc/phpMyAdmin hem /usr/share/phpMyAdmin'e kopyala (v3.0 paritesi)
                for target in "${PMA_SIGNON}" "${PMA_SIGNON_SHARED}"; do
                    target_dir=$(dirname "$target")
                    if [[ -d "$target_dir" ]]; then
                        cp -f "${SRC_SIGNON}" "$target"
                        chown "root:${WEB_GROUP}" "$target"
                        chmod 0640 "$target"
                    fi
                done
                ACTIONS+=("Signon script v3.1 deploy edildi (etc + shared)")
                mark_check "signon_script" "ok" "Signon script deploy edildi" "true"
            else
                ERRORS+=("Template bulunamadı: ${SRC_SIGNON}")
                mark_check "signon_script" "fail" "Template eksik: ${SRC_SIGNON}"
            fi
        else
            mark_check "signon_script" "fail" "Signon script yok (${PMA_SIGNON} ve ${PMA_SIGNON_SHARED})"
        fi
    fi
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 6: config.inc.php SSO snippet veya v3.0 inline signon config
# ──────────────────────────────────────────────────────────────────────────
# v3.0+ deploy config.inc.php'yi DOĞRUDAN auth_type='signon' ile yazdığı için
# eski "ONOXSOFT-SSO-BEGIN" marker'ı bulunmayabilir. Doctor her iki path'i
# (PMA_ETC, PMA_DIR) ve her iki imzayı (marker VEYA inline signon) tanır.

sso_config_detected() {
    local f="$1"
    [[ -f "$f" ]] || return 1
    # v1.x marker
    grep -q "ONOXSOFT-SSO-BEGIN" "$f" 2>/dev/null && return 0
    # v3.0+ inline: auth_type='signon' (boşluk varyantları + tek/çift tırnak)
    grep -Eq "auth_type[[:space:]]*=[[:space:]]*['\"]signon['\"]" "$f" 2>/dev/null && return 0
    return 1
}

if sso_config_detected "${PMA_CONFIG}" || sso_config_detected "${PMA_CONFIG_SHARED}"; then
    detected_in=""
    sso_config_detected "${PMA_CONFIG}" && detected_in="${PMA_CONFIG}"
    [[ -z "$detected_in" ]] && sso_config_detected "${PMA_CONFIG_SHARED}" && detected_in="${PMA_CONFIG_SHARED}"
    mark_check "sso_snippet" "ok" "SSO config aktif: ${detected_in}"
else
    if [[ "${REPAIR}" == "true" ]]; then
        SRC_SNIP="${ONOX_HOME}/config/onoxsoft/templates/phpmyadmin/config.snippet.stub"
        if [[ -f "${SRC_SNIP}" ]]; then
            # /etc/phpMyAdmin/config.inc.php yoksa yarat (minimal)
            if [[ ! -f "${PMA_CONFIG}" ]]; then
                cat > "${PMA_CONFIG}" <<'EOF_MIN'
<?php
declare(strict_types=1);
$cfg['blowfish_secret'] = ''; // doctor doldurur
EOF_MIN
                chmod 0640 "${PMA_CONFIG}"
                chown root:"${WEB_GROUP}" "${PMA_CONFIG}" 2>/dev/null || true
            else
                cp -a "${PMA_CONFIG}" "${PMA_CONFIG}.bak-$(date +%Y%m%d%H%M%S)"
            fi
            # <?php satırını atla, geri kalanı ekle
            tmp_snip=$(mktemp)
            grep -v "^<?php" "${SRC_SNIP}" > "${tmp_snip}"
            cat "${tmp_snip}" >> "${PMA_CONFIG}"
            rm -f "${tmp_snip}"
            ACTIONS+=("SSO snippet config.inc.php'ye eklendi")
            mark_check "sso_snippet" "ok" "SSO snippet eklendi" "true"
        else
            ERRORS+=("Template bulunamadı: ${SRC_SNIP}")
            mark_check "sso_snippet" "fail" "Snippet template eksik"
        fi
    else
        mark_check "sso_snippet" "fail" "SSO config bulunamadı (${PMA_CONFIG} veya ${PMA_CONFIG_SHARED})"
    fi
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 7: blowfish_secret atanmış mı
# ──────────────────────────────────────────────────────────────────────────
if [[ -f "${PMA_CONFIG}" ]]; then
    if grep -qE "cfg\['blowfish_secret'\]\s*=\s*''" "${PMA_CONFIG}" 2>/dev/null; then
        if [[ "${REPAIR}" == "true" ]]; then
            SECRET="$(openssl rand -base64 32 | tr -d '/\n=' | head -c 32)"
            sed -i "s|cfg\['blowfish_secret'\] = '';|cfg['blowfish_secret'] = '${SECRET}';|" "${PMA_CONFIG}"
            ACTIONS+=("blowfish_secret üretildi (32 char)")
            mark_check "blowfish_secret" "ok" "blowfish_secret atandı" "true"
        else
            mark_check "blowfish_secret" "warn" "blowfish_secret boş — auth cookie warning verir"
        fi
    else
        mark_check "blowfish_secret" "ok" "blowfish_secret atanmış"
    fi
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 8: SELinux httpd_can_network_connect (signon localhost cURL için)
# ──────────────────────────────────────────────────────────────────────────
if command -v getsebool >/dev/null 2>&1; then
    if getsebool httpd_can_network_connect 2>/dev/null | grep -q ' on$'; then
        mark_check "selinux_network" "ok" "httpd_can_network_connect=on (signon cURL OK)"
    else
        if [[ "${REPAIR}" == "true" ]]; then
            setsebool -P httpd_can_network_connect 1 2>/dev/null || true
            ACTIONS+=("SELinux httpd_can_network_connect=on yapıldı")
            mark_check "selinux_network" "ok" "Boolean açıldı" "true"
        else
            mark_check "selinux_network" "warn" "httpd_can_network_connect=off — signon cURL fail eder"
        fi
    fi
else
    mark_check "selinux_network" "ok" "SELinux yok (Debian)"
fi

# ──────────────────────────────────────────────────────────────────────────
# CHECK 9: Panel API /api/pma-sso/consume reachable (localhost curl)
# ──────────────────────────────────────────────────────────────────────────
# v1.2: SNI-aware check — Apache panel vhost ServerName kontrolü zorunlu.
# 127.0.0.1:666 doğrudan dene → default vhost'a düşebilir (ssl cert mismatch).
# --resolve ile public hostname'i 127.0.0.1'e map'le → doğru vhost match olur.
#
# Sıralı dene: önce hostname (SNI doğru), olmazsa 127.0.0.1 (loopback fallback).
_probe_panel() {
    local url="$1" resolve_opt="${2:-}"
    local code
    code=$(curl -s -o /dev/null -w "%{http_code}" -k --max-time 5 \
           ${resolve_opt} "$url" 2>/dev/null) || code="000"
    code="${code:0:3}"
    [[ -z "$code" ]] && code="000"
    echo "$code"
}

# Try 1: hostname via --resolve (SNI doğru, vhost match)
HTTP_CODE=$(_probe_panel "https://${PANEL_HOSTNAME}:${PANEL_SSL_PORT}/api/pma-sso/consume" \
                         "--resolve ${PANEL_HOSTNAME}:${PANEL_SSL_PORT}:127.0.0.1")
PROBE_METHOD="hostname+resolve"

# Try 2: 127.0.0.1 (default vhost / no SNI)
if [[ "${HTTP_CODE}" == "000" ]]; then
    HTTP_CODE=$(_probe_panel "https://127.0.0.1:${PANEL_SSL_PORT}/api/pma-sso/consume")
    PROBE_METHOD="127.0.0.1"
fi

# Try 3: ss/netstat ile portun gerçekten LISTEN'da olup olmadığını kontrol et
PORT_LISTENING=false
if command -v ss >/dev/null 2>&1; then
    if ss -tln 2>/dev/null | awk '{print $4}' | grep -qE ":${PANEL_SSL_PORT}\$"; then
        PORT_LISTENING=true
    fi
elif command -v netstat >/dev/null 2>&1; then
    if netstat -tln 2>/dev/null | awk '{print $4}' | grep -qE ":${PANEL_SSL_PORT}\$"; then
        PORT_LISTENING=true
    fi
fi

case "${HTTP_CODE}" in
    400|405|422)
        # 400 invalid_token / 405 method / 422 validation = reachable
        mark_check "panel_api_reachable" "ok" "Panel API erişilebilir (HTTP ${HTTP_CODE} via ${PROBE_METHOD})"
        ;;
    200|301|302|404)
        # 200/3xx/404 reachable ama beklenmedik — yine de panel up
        mark_check "panel_api_reachable" "ok" "Panel reachable (HTTP ${HTTP_CODE} via ${PROBE_METHOD})"
        ;;
    000)
        if ${PORT_LISTENING}; then
            # Port LISTEN'da ama curl 000 → muhtemelen TLS/SNI sorunu
            mark_check "panel_api_reachable" "warn" "Port ${PANEL_SSL_PORT} LISTEN'da ama loopback curl 000 — TLS/SNI sorunu olabilir; tarayıcıdan çalışıyorsa kritik değil"
        else
            mark_check "panel_api_reachable" "fail" "Panel API erişilmez — port ${PANEL_SSL_PORT} LISTEN değil"
            ERRORS+=("Apache panel vhost down — systemctl status httpd kontrol et")
        fi
        ;;
    *)
        mark_check "panel_api_reachable" "ok" "Panel yanıt verdi (HTTP ${HTTP_CODE} via ${PROBE_METHOD})"
        ;;
esac

# ──────────────────────────────────────────────────────────────────────────
# Web server reload (gerekli ise) — Apache / Caddy
# ──────────────────────────────────────────────────────────────────────────
if [[ "${REPAIR}" == "true" ]]; then
    # Apache reload
    if [[ ${NEED_APACHE_RELOAD} -eq 1 ]]; then
        if systemctl is-active --quiet httpd 2>/dev/null; then
            if httpd -t >/dev/null 2>&1; then
                systemctl reload httpd >/dev/null 2>&1 && ACTIONS+=("httpd reload (Alias aktif)")
            else
                ERRORS+=("httpd -t fail — config bozuk olabilir, reload atlandı")
            fi
        elif systemctl is-active --quiet apache2 2>/dev/null; then
            if apache2ctl -t >/dev/null 2>&1; then
                systemctl reload apache2 >/dev/null 2>&1 && ACTIONS+=("apache2 reload (Alias aktif)")
            else
                ERRORS+=("apache2ctl -t fail — config bozuk olabilir, reload atlandı")
            fi
        else
            ACTIONS+=("Apache değişiklik yapıldı ama servis aktif değil (Caddy/Nginx kullanılıyor olabilir)")
        fi
    fi

    # Caddy reload
    if [[ ${NEED_CADDY_RELOAD} -eq 1 ]]; then
        if systemctl is-active --quiet caddy 2>/dev/null; then
            # Caddy validate
            if caddy validate --config /etc/caddy/Caddyfile >/dev/null 2>&1; then
                systemctl reload caddy >/dev/null 2>&1 && ACTIONS+=("caddy reload (handle_path /phpmyadmin aktif)")
            else
                ERRORS+=("caddy validate fail — config bozuk olabilir, reload atlandı")
            fi
        else
            ERRORS+=("Caddy değişiklik yapıldı ama servis aktif değil — systemctl start caddy")
        fi
    fi
fi

# ──────────────────────────────────────────────────────────────────────────
# Sonuç: tüm checks ok mu?
# ──────────────────────────────────────────────────────────────────────────
OVERALL_OK=true
for name in "${!CHECKS_STATUS[@]}"; do
    if [[ "${CHECKS_STATUS[$name]}" == "fail" ]]; then
        OVERALL_OK=false
    fi
done

# JSON output (jq ile)
checks_json="{}"
for name in "${!CHECKS_STATUS[@]}"; do
    checks_json=$(echo "${checks_json}" | jq \
        --arg n "${name}" \
        --arg s "${CHECKS_STATUS[$name]}" \
        --arg m "${CHECKS_MSG[$name]}" \
        --argjson f "${CHECKS_FIXED[$name]:-false}" \
        '. + {($n): {status: $s, message: $m, fixed: $f}}')
done

# v1.1: Boş array için empty string oluşmasın — array length 0 ise direkt "[]" ver
if [[ ${#ACTIONS[@]} -eq 0 ]]; then
    actions_json="[]"
else
    actions_json=$(printf '%s\n' "${ACTIONS[@]}" | jq -R . | jq -s . 2>/dev/null || echo "[]")
fi
if [[ ${#ERRORS[@]} -eq 0 ]]; then
    errors_json="[]"
else
    errors_json=$(printf '%s\n' "${ERRORS[@]}" | jq -R . | jq -s . 2>/dev/null || echo "[]")
fi

jq -n \
    --argjson ok "${OVERALL_OK}" \
    --argjson checks "${checks_json}" \
    --argjson actions "${actions_json}" \
    --argjson errors "${errors_json}" \
    --arg url "https://${PANEL_HOSTNAME}:${PANEL_SSL_PORT}/phpmyadmin/" \
    --arg webserver "${ACTIVE_WEBSERVER}" \
    --arg caddy_conf "${CADDY_PANEL_CONF:-}" \
    '{
      ok: $ok,
      url: $url,
      active_webserver: $webserver,
      caddy_panel_conf: $caddy_conf,
      checks: $checks,
      actions: $actions,
      errors: $errors
    }'

onx_log "phpmyadmin-doctor: ok=${OVERALL_OK} ws=${ACTIVE_WEBSERVER} actions=${#ACTIONS[@]} errors=${#ERRORS[@]}"
exit 0
