<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Domain\Sysapi\Contracts\SysapiBridge;
use App\Domain\Sysapi\Exceptions\SysapiException;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response as HttpResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Inertia\Inertia;
use Inertia\Response;

/**
 * Admin Apache Global Configuration (WHM EasyApache muadili).
 *
 * Faz L: DB değişikliğinden sonra `apache-write-conf` ile gerçek
 *        /etc/httpd/conf.d/onox-custom.conf yazımı + apachectl configtest gate
 *        + auto-rollback. Test ve reload zaten sysapi'ye bağlı (Faz 0).
 */
class ApacheConfigController extends Controller
{
    /**
     * Apache modül listesi — sysapi başarısız olursa kullanılan fallback liste.
     * Normal akışta `apache-modules-list` sysapi action'ından `apachectl -M` parse
     * sonucu döner; bu liste sadece OS ulaşılamadığında UI'nın boş kalmamasını sağlar.
     */
    /**
     * Modul kataloğu — WHM "Apache Modules" muadili.
     *
     * Her modülün:
     *   - category: ui'da gruplama (core/auth/proxy/security/performance/cgi/dav/misc)
     *   - depends: hangi modüller bunu enable etmeden önce zorunlu (mod_proxy_fcgi → mod_proxy)
     *   - dependents: bu modülü disable ederken etkilenecek modüller
     *   - vendor_install: stok repo dışıysa nasıl kurulur (mod_pagespeed = mod_pagespeed-stable)
     */
    private const LOADED_MODULES = [
        // ── Core (always loaded, not toggleable) ────────────────────────────
        ['name' => 'mod_authz_core',    'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Temel yetkilendirme çerçevesi'],
        ['name' => 'mod_authz_host',    'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Host tabanlı erişim kontrolü'],
        ['name' => 'mod_alias',         'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'URL takma adı ve yönlendirme'],
        ['name' => 'mod_dir',           'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Dizin dizin listesi ve DirectoryIndex'],
        ['name' => 'mod_mime',          'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'MIME türü eşleştirme'],
        ['name' => 'mod_negotiation',   'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'İçerik anlaşması (Accept headers)'],
        ['name' => 'mod_setenvif',      'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Koşullu ortam değişkeni ayarlama'],
        ['name' => 'mod_log_config',    'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Erişim logu yapılandırması'],
        ['name' => 'mod_logio',         'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Giriş/çıkış bayt sayısı loglama'],
        ['name' => 'mod_mpm_event',     'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Event MPM — AlmaLinux 9 varsayılan'],
        ['name' => 'mod_systemd',       'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'systemd entegrasyonu'],
        ['name' => 'mod_unixd',         'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Unix kullanıcı/grup güvenliği'],
        ['name' => 'mod_filter',        'loaded' => true,  'toggleable' => false, 'category' => 'core',     'description_tr' => 'Çıktı filtre zinciri'],

        // ── URL & Routing ───────────────────────────────────────────────────
        ['name' => 'mod_rewrite',       'loaded' => true,  'toggleable' => true,  'category' => 'routing',  'description_tr' => 'URL yeniden yazma kuralları (.htaccess RewriteRule)'],
        ['name' => 'mod_substitute',    'loaded' => false, 'toggleable' => true,  'category' => 'routing',  'description_tr' => 'Yanıt içeriği metin değiştirme'],
        ['name' => 'mod_speling',       'loaded' => false, 'toggleable' => true,  'category' => 'routing',  'description_tr' => 'URL yazım hatası düzeltme'],
        ['name' => 'mod_userdir',       'loaded' => false, 'toggleable' => true,  'category' => 'routing',  'description_tr' => '~/public_html kullanıcı dizinleri'],

        // ── Security & TLS ──────────────────────────────────────────────────
        ['name' => 'mod_ssl',           'loaded' => true,  'toggleable' => true,  'category' => 'security', 'description_tr' => 'HTTPS / TLS şifreleme'],
        ['name' => 'mod_headers',       'loaded' => true,  'toggleable' => true,  'category' => 'security', 'description_tr' => 'HTTP başlık ekleme/değiştirme (HSTS, CSP, X-Frame)'],
        ['name' => 'mod_security2',     'loaded' => true,  'toggleable' => true,  'category' => 'security', 'description_tr' => 'ModSecurity WAF çekirdeği'],
        ['name' => 'mod_evasive',       'loaded' => false, 'toggleable' => true,  'category' => 'security', 'description_tr' => 'DoS/DDoS koruma modülü', 'vendor_install' => 'mod_evasive'],
        ['name' => 'mod_qos',           'loaded' => false, 'toggleable' => true,  'category' => 'security', 'description_tr' => 'QoS / bant genişliği kontrolü', 'vendor_install' => 'mod_qos'],
        ['name' => 'mod_remoteip',      'loaded' => true,  'toggleable' => true,  'category' => 'security', 'description_tr' => 'CDN/load balancer arkasında gerçek IP tespiti'],
        ['name' => 'mod_unique_id',     'loaded' => true,  'toggleable' => true,  'category' => 'security', 'description_tr' => 'Her istek için benzersiz ID üretimi'],

        // ── Performance & Compression ───────────────────────────────────────
        ['name' => 'mod_deflate',       'loaded' => true,  'toggleable' => true,  'category' => 'performance', 'description_tr' => 'gzip sıkıştırma'],
        ['name' => 'mod_brotli',        'loaded' => true,  'toggleable' => true,  'category' => 'performance', 'description_tr' => 'Brotli sıkıştırma (gzip alternatifi)'],
        ['name' => 'mod_expires',       'loaded' => true,  'toggleable' => true,  'category' => 'performance', 'description_tr' => 'Tarayıcı önbellek Expires başlıkları'],
        ['name' => 'mod_xsendfile',     'loaded' => false, 'toggleable' => true,  'category' => 'performance', 'description_tr' => 'X-Sendfile başlığı ile dosya gönderme', 'vendor_install' => 'mod_xsendfile'],
        ['name' => 'mod_pagespeed',     'loaded' => false, 'toggleable' => true,  'category' => 'performance', 'description_tr' => 'Google PageSpeed Optimization', 'vendor_install' => 'mod-pagespeed-stable'],

        // ── Proxy & FastCGI ─────────────────────────────────────────────────
        ['name' => 'mod_proxy',         'loaded' => true,  'toggleable' => true,  'category' => 'proxy',    'description_tr' => 'Proxy/ters proxy temel modülü'],
        ['name' => 'mod_proxy_fcgi',    'loaded' => true,  'toggleable' => true,  'category' => 'proxy',    'description_tr' => 'PHP-FPM FastCGI proxy (mod_proxy alt modülü)', 'depends' => ['mod_proxy']],
        ['name' => 'mod_proxy_http',    'loaded' => true,  'toggleable' => true,  'category' => 'proxy',    'description_tr' => 'HTTP/HTTPS proxy (mod_proxy alt modülü)', 'depends' => ['mod_proxy']],

        // ── CGI / Scripting ─────────────────────────────────────────────────
        ['name' => 'mod_cgi',           'loaded' => false, 'toggleable' => true,  'category' => 'cgi',      'description_tr' => 'CGI script çalıştırma (FPM kullanılıyorsa gereksiz)'],
        ['name' => 'mod_cgid',          'loaded' => false, 'toggleable' => true,  'category' => 'cgi',      'description_tr' => 'Threaded MPM için CGI daemon'],
        ['name' => 'mod_php',           'loaded' => false, 'toggleable' => true,  'category' => 'cgi',      'description_tr' => 'mod_php (devre dışı — PHP-FPM kullanılıyor)'],
        ['name' => 'mod_lua',           'loaded' => false, 'toggleable' => true,  'category' => 'cgi',      'description_tr' => 'Lua betik entegrasyonu'],
        ['name' => 'mod_perl',          'loaded' => false, 'toggleable' => true,  'category' => 'cgi',      'description_tr' => 'Perl modül entegrasyonu'],

        // ── WebDAV / Files ──────────────────────────────────────────────────
        ['name' => 'mod_dav',           'loaded' => false, 'toggleable' => true,  'category' => 'webdav',   'description_tr' => 'WebDAV temel modülü'],
        ['name' => 'mod_dav_fs',        'loaded' => false, 'toggleable' => true,  'category' => 'webdav',   'description_tr' => 'WebDAV dosya sistemi sağlayıcısı', 'depends' => ['mod_dav']],

        // ── Monitoring & Status ─────────────────────────────────────────────
        ['name' => 'mod_status',        'loaded' => true,  'toggleable' => true,  'category' => 'monitoring', 'description_tr' => 'Sunucu durum sayfası (/server-status)'],
    ];

    /** UI'da gösterilecek kategori sırası + Türkçe etiketler. */
    private const CATEGORIES = [
        'core' => ['label' => 'Çekirdek (Daima Yüklü)', 'icon' => 'CogIcon', 'color' => 'slate'],
        'security' => ['label' => 'Güvenlik & TLS', 'icon' => 'ShieldCheckIcon', 'color' => 'red'],
        'performance' => ['label' => 'Performans & Sıkıştırma', 'icon' => 'BoltIcon', 'color' => 'amber'],
        'proxy' => ['label' => 'Proxy & FastCGI', 'icon' => 'ArrowsRightLeftIcon', 'color' => 'indigo'],
        'routing' => ['label' => 'URL & Yönlendirme', 'icon' => 'MapIcon', 'color' => 'blue'],
        'cgi' => ['label' => 'CGI & Scripting', 'icon' => 'CodeBracketIcon', 'color' => 'purple'],
        'webdav' => ['label' => 'WebDAV & Dosya', 'icon' => 'FolderIcon', 'color' => 'cyan'],
        'monitoring' => ['label' => 'İzleme & Durum', 'icon' => 'ChartBarIcon', 'color' => 'emerald'],
        'misc' => ['label' => 'Diğer', 'icon' => 'EllipsisHorizontalIcon', 'color' => 'slate'],
    ];

    public function index(Request $request): Response
    {
        $rows = DB::table('apache_server_config')
            ->orderBy('category')
            ->orderBy('key')
            ->get()
            ->map(fn ($r) => array_merge(
                (array) $r,
                ['enum_values' => $r->enum_values ? json_decode($r->enum_values) : null]
            ));

        $grouped = collect($rows)->groupBy('category');

        // Modül listesi — sysapi 'apache-modules-list' ile gerçek `apachectl -M` çıktısı
        // (production'da). Sysapi erişilemiyorsa LOADED_MODULES static fallback.
        $loaded_modules = $this->fetchLoadedModules();

        // Runtime status — sysapi 'apache-status' ile mod_status + systemctl uptime
        $status = $this->fetchApacheStatus();

        // Module categories — UI'da accordion / tab grouping için
        $module_categories = collect(self::CATEGORIES)
            ->map(fn ($v, $k) => array_merge($v, ['slug' => $k]))
            ->values()
            ->all();

        return Inertia::render('Admin/Apache/Index', compact(
            'grouped', 'loaded_modules', 'status', 'module_categories'
        ));
    }

    /**
     * Apache loaded modules — production'da sysapi 'apache-modules-list' apachectl -M parse eder.
     * Sysapi başarısız olursa LOADED_MODULES static array fallback.
     */
    private function fetchLoadedModules(): array
    {
        $catalog = collect(self::LOADED_MODULES)->keyBy('name');
        $live = null;

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-modules-list', [], timeoutSeconds: 5);
            if ($result->successful && ! empty($result->data['loaded'])) {
                // Live'dan dönen modül adlarını set'e koy — katalog ile cross-reference
                $live = collect($result->data['loaded'])->pluck('name')->all();
            }
        } catch (\Throwable $e) {
            Log::info('apache.modules_list_sysapi_failed', ['error' => $e->getMessage()]);
        }

        // Live çıktı varsa loaded flag'i live'a göre, yoksa katalog default'larına göre
        return $catalog->map(function (array $m) use ($live): array {
            $name = $m['name'];
            return array_merge($m, [
                'loaded' => $live === null ? $m['loaded'] : in_array($name, $live, true),
                'category' => $m['category'] ?? 'misc',
                'depends' => $m['depends'] ?? [],
                'vendor_install' => $m['vendor_install'] ?? null,
            ]);
        })->values()->all();
    }

    /**
     * Modul bağımlılık kontrolü:
     *  - Enable: bağlı olduğu modüller (depends) yüklü değilse "önce şu modülleri açın"
     *  - Disable: bu modülü gerektiren modüller (dependents) varsa "önce şu modülleri kapatın"
     *
     * @return array{ok: bool, message?: string, missing_deps?: array<string>, blocking_dependents?: array<string>}
     */
    private function checkModuleDependencies(string $module, bool $enable): array
    {
        $catalog = collect(self::LOADED_MODULES)->keyBy('name');
        $target = $catalog->get($module);

        if (! $target) {
            return ['ok' => true]; // unknown modul, controller validation already enforced regex
        }

        $live = $this->fetchLoadedModules();
        $loadedSet = collect($live)->where('loaded', true)->pluck('name')->all();

        if ($enable) {
            // Bağlı olduğu modüller yüklü mü?
            $missing = array_diff($target['depends'] ?? [], $loadedSet);
            if (! empty($missing)) {
                return [
                    'ok' => false,
                    'message' => "{$module} bağımlılığı eksik. Önce şu modülleri etkinleştirin: ".implode(', ', $missing),
                    'missing_deps' => array_values($missing),
                ];
            }
        } else {
            // Bu modülü gerektiren başka modüller yüklü mü?
            $dependents = $catalog->filter(fn ($m) => in_array($module, $m['depends'] ?? [], true))
                ->where('name', '!=', $module)
                ->pluck('name')
                ->all();
            $blocking = array_intersect($dependents, $loadedSet);
            if (! empty($blocking)) {
                return [
                    'ok' => false,
                    'message' => "{$module} kapatılamıyor — şu modüller hâlâ buna bağımlı: ".implode(', ', $blocking),
                    'blocking_dependents' => array_values($blocking),
                ];
            }
        }

        return ['ok' => true];
    }

    /**
     * Apache runtime status — sysapi 'apache-status' (mod_status server-status parse).
     * Sysapi erişilemiyorsa boş/null değerler döner, UI "veri yok" gösterir.
     */
    private function fetchApacheStatus(): array
    {
        $defaults = [
            'service' => 'unknown',
            'uptime' => '—',
            'requests_total' => null,
            'current_workers' => null,
            'idle_workers' => null,
            'busy_workers' => null,
            'max_workers' => null,
            'cpu_load' => null,
            'requests_per_sec' => null,
            'bytes_per_sec' => null,
            'apache_version' => $this->detectApacheVersion(),
        ];

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-status', [], timeoutSeconds: 5);
            if ($result->successful) {
                $d = $result->data;
                return array_merge($defaults, [
                    'service' => $d['service'] ?? 'active',
                    'uptime' => $d['uptime'] ?? '—',
                    'requests_total' => $d['total_accesses'] ?? null,
                    'busy_workers' => $d['workers_busy'] ?? null,
                    'idle_workers' => $d['workers_idle'] ?? null,
                    'current_workers' => ($d['workers_busy'] ?? 0) + ($d['workers_idle'] ?? 0),
                    'requests_per_sec' => $d['requests_per_sec'] ?? null,
                    'bytes_per_sec' => $d['bytes_per_sec'] ?? null,
                    'cpu_load' => $d['cpu_load'] ?? null,
                    'apache_version' => $d['version'] ?? $defaults['apache_version'],
                ]);
            }
        } catch (\Throwable $e) {
            Log::info('apache.status_sysapi_failed', ['error' => $e->getMessage()]);
        }

        return $defaults;
    }

    private function detectApacheVersion(): string
    {
        try {
            $a = app(\App\Domain\WebServer\Contracts\WebServerAdapter::class);
            return $a->isInstalled() ? $a->version() : 'Apache (kurulu değil)';
        } catch (\Throwable) {
            return 'Apache (tespit edilemedi)';
        }
    }

    public function update(Request $request): RedirectResponse
    {
        $request->validate([
            'settings' => ['required', 'array'],
            'apply' => ['nullable', 'boolean'],
        ]);

        $rows = DB::table('apache_server_config')
            ->get()
            ->keyBy('key');

        foreach ($request->input('settings') as $key => $value) {
            if (! $rows->has($key)) {
                continue;
            }

            $row = $rows->get($key);

            // Type-aware validation
            if ($row->data_type === 'integer' && ! is_numeric($value)) {
                continue;
            }

            if ($row->data_type === 'enum' && $row->enum_values) {
                $allowed = json_decode($row->enum_values, true);
                if (! in_array($value, $allowed, true)) {
                    continue;
                }
            }

            DB::table('apache_server_config')
                ->where('key', $key)
                ->update(['value' => (string) $value, 'updated_at' => now()]);
        }

        // Faz L: DB yazımından sonra /etc/httpd/conf.d/onox-custom.conf yaz +
        // configtest gate + auto-rollback + reload (atomic 3-step).
        // Frontend `apply=false` gönderirse sadece DB güncellenir.
        $apply = (bool) $request->input('apply', true);
        if (! $apply) {
            return back()->with('success', 'Apache konfigürasyonu DB\'ye kaydedildi. "Uygula" ile dosyaya yazıp reload edebilirsiniz.');
        }

        return $this->applyToFilesystem();
    }

    /**
     * DB satırlarını render edip /etc/httpd/conf.d/onox-custom.conf'a yazar,
     * apachectl configtest geçerse systemctl reload httpd çalıştırır.
     * Configtest fail olursa script kendisi rollback yapar (sysapi exit 4).
     */
    public function applyToFilesystem(): RedirectResponse
    {
        $conf = $this->renderConf();

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-write-conf', [
                'content' => $conf,
                'target' => '/etc/httpd/conf.d/onox-custom.conf',
            ], timeoutSeconds: 30);

            if ($result->failed()) {
                Log::warning('apache.write_conf_failed', ['stderr' => $result->stderr]);

                return back()->with('error', "Apache config yazılamadı: {$result->stderr}");
            }

            $backup = $result->data['backup'] ?? '';

            return back()->with('success', 'Apache konfigürasyonu uygulandı, configtest geçti, reload edildi.'
                . ($backup ? " (Backup: {$backup})" : ''));
        } catch (SysapiException $e) {
            // Exit 4: configtest failed → script restored the old conf already.
            $hint = str_contains($e->getMessage(), 'configtest')
                ? ' Önceki konfigürasyon otomatik geri yüklendi.'
                : '';

            return back()->with('error', "Apache yazımı başarısız: {$e->getMessage()}.{$hint}");
        }
    }

    /**
     * DB → /etc/httpd/conf.d/onox-custom.conf metni.
     * exportConf() ile aynı body, ortak helper.
     */
    private function renderConf(): string
    {
        $rows = DB::table('apache_server_config')->get()->keyBy('key');
        $get = fn (string $key): string => (string) ($rows->get($key)?->value ?? '');
        $mpm = $get('mpm');
        $ts = now()->format('Y-m-d H:i:s T');

        $conf = <<<CONF
# Onoxsoft-managed Apache config — generated {$ts}
# /etc/httpd/conf.d/onox-custom.conf
# Do NOT edit manually — managed via Onoxsoft Admin Panel.

# ── Performance ─────────────────────────────────────────────────────
Timeout {$get('Timeout')}
KeepAlive {$get('KeepAlive')}
KeepAliveTimeout {$get('KeepAliveTimeout')}
MaxKeepAliveRequests {$get('MaxKeepAliveRequests')}
HostnameLookups {$get('HostnameLookups')}

# ── MPM: {$mpm} ──────────────────────────────────────────────────────
<IfModule mpm_{$mpm}_module>
    StartServers           {$get('mpm_StartServers')}
    MinSpareThreads        {$get('mpm_MinSpareThreads')}
    MaxSpareThreads        {$get('mpm_MaxSpareThreads')}
    ThreadsPerChild        {$get('mpm_ThreadsPerChild')}
    MaxRequestWorkers      {$get('mpm_MaxRequestWorkers')}
    MaxConnectionsPerChild {$get('mpm_MaxConnectionsPerChild')}
</IfModule>

# ── Security ────────────────────────────────────────────────────────
ServerSignature {$get('ServerSignature')}
ServerTokens {$get('ServerTokens')}
TraceEnable {$get('TraceEnable')}
RLimitCPU {$get('RLimitCPU')}
RLimitMEM {$get('RLimitMEM')}

# ── General ─────────────────────────────────────────────────────────
LogLevel {$get('LogLevel')}
CONF;

        return $conf;
    }

    public function toggleModule(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'module' => ['required', 'string', 'max:50', 'regex:/^mod_[a-z0-9_]+$/'],
            'enable' => ['required', 'boolean'],
            'force' => ['boolean'],   // Bağımlılık kontrolünü atla (admin advanced kullanım)
        ]);

        $module = $validated['module'];
        $enable = (bool) $validated['enable'];
        $force = (bool) ($validated['force'] ?? false);

        // Bağımlılık kontrolü — force=false ise enforce et
        if (! $force) {
            $depCheck = $this->checkModuleDependencies($module, $enable);
            if (! $depCheck['ok']) {
                return back()->with('error', $depCheck['message'].' (force=true ile zorla yapabilirsiniz)');
            }
        }

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-module-toggle', [
                'module' => $module,
                'enable' => $enable,
            ], timeoutSeconds: 20);

            if ($result->failed()) {
                return back()->with('error', "Modül {$module} değiştirilemedi: {$result->stderr}");
            }

            // Audit log
            try {
                if (\Illuminate\Support\Facades\Schema::hasTable('audit_log')) {
                    DB::table('audit_log')->insert([
                        'user_id' => $request->user()?->id,
                        'action' => $enable ? 'apache.module_enabled' : 'apache.module_disabled',
                        'target_type' => 'apache_module',
                        'target_id' => null,
                        'ip_address' => $request->ip(),
                        'outcome' => 'success',
                        'metadata' => json_encode(['module' => $module, 'forced' => $force]),
                        'created_at' => now(),
                    ]);
                }
            } catch (\Throwable) {
                // soft-fail
            }

            return back()->with('success', $enable
                ? "{$module} aktif edildi. Apache reload butonuna basın."
                : "{$module} devre dışı bırakıldı. Apache reload butonuna basın.");
        } catch (SysapiException $e) {
            Log::warning('apache.module_toggle_failed', ['module' => $module, 'enable' => $enable, 'error' => $e->getMessage()]);

            return back()->with('error', "Modül {$module} sysapi hatası: {$e->getMessage()}");
        }
    }

    /**
     * Vendor modül install — stok dnf repo'su dışında olan modülleri kur (mod_pagespeed gibi).
     * Sysapi yeni action: `apache-module-install` package adıyla çalıştırır.
     */
    public function installModule(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'module' => ['required', 'string', 'max:50', 'regex:/^mod_[a-z0-9_]+$/'],
        ]);

        $module = $validated['module'];
        $catalog = collect(self::LOADED_MODULES)->keyBy('name');
        $entry = $catalog->get($module);

        if (! $entry || empty($entry['vendor_install'])) {
            return back()->with('error', "Modül {$module} için install paketi tanımsız.");
        }

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-module-install', [
                'module' => $module,
                'package' => $entry['vendor_install'],
            ], timeoutSeconds: 300);

            if ($result->failed()) {
                return back()->with('error', "Modül kurulum başarısız: {$result->stderr}");
            }

            return back()->with('success',
                "{$module} kuruldu ({$entry['vendor_install']}). Aktive etmek için 'Aktif Et' butonuna basın."
            );
        } catch (\Throwable $e) {
            return back()->with('error', "Modül kurulumu sysapi hatası: {$e->getMessage()}");
        }
    }

    public function resetToDefaults(Request $request): RedirectResponse
    {
        DB::table('apache_server_config')
            ->update([
                'value' => DB::raw('default_value'),
                'updated_at' => now(),
            ]);

        return back()->with('success', 'Varsayılan değerlere sıfırlandı.');
    }

    public function exportConf(Request $request): HttpResponse
    {
        return response($this->renderConf())
            ->header('Content-Type', 'text/plain')
            ->header('Content-Disposition', 'attachment; filename="onox-apache.conf"');
    }

    public function reload(Request $request): RedirectResponse
    {
        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-reload', timeoutSeconds: 30);

            if ($result->failed()) {
                return back()->with('error', "Apache reload başarısız: {$result->stderr}");
            }

            $uptime = $result->data['uptime'] ?? 'bilinmiyor';

            return back()->with('success', "Apache reload edildi. Uptime: {$uptime}");
        } catch (SysapiException $e) {
            return back()->with('error', "Sysapi hatası: {$e->getMessage()}");
        }
    }

    public function testConfig(Request $request): RedirectResponse
    {
        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('apache-test', timeoutSeconds: 15);

            // apache-test exits 0 on syntax OK, non-zero on syntax error.
            // SysapiException is only thrown for script-level failures.
            if ($result->failed()) {
                $output = $result->data['output'] ?? $result->stderr;

                return back()->with('error', "Apache config syntax hatası: {$output}");
            }

            $output = $result->data['output'] ?? 'Syntax OK';

            return back()->with('success', "Apache config test: {$output}");
        } catch (SysapiException $e) {
            return back()->with('error', "Sysapi hatası: {$e->getMessage()}");
        }
    }
}
