<?php

declare(strict_types=1);

namespace App\Http\Controllers\Customer;

use App\Domain\Account\Models\Account;
use App\Domain\Dns\Models\DnsZone;
use App\Domain\Dns\Services\DnsProvisioner;
use App\Domain\Domain\Enums\DomainStatus;
use App\Domain\Domain\Enums\DomainType;
use App\Domain\Domain\Exceptions\DomainException;
use App\Domain\Domain\Models\Domain;
use App\Domain\Domain\Services\DomainProvisioner;
use App\Domain\Domain\Services\SystemSubdomainProvisioner;
use App\Domain\Domain\Services\VhostProvisioner;
use App\Domain\Email\Models\EmailAccount;
use App\Domain\Ssl\Models\SslCertificate;
use App\Domain\Sysapi\Contracts\SysapiBridge;
use App\Domain\Sysapi\Exceptions\SysapiException;
use App\Domain\WebServer\Services\WebServerFactory;
use App\Http\Controllers\Controller;
use App\Jobs\MailboxProvisioningJob;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Str;
use Inertia\Inertia;
use Inertia\Response;

class DomainController extends Controller
{
    public function __construct(
        private readonly DomainProvisioner $provisioner,
        private readonly VhostProvisioner $vhost,
        private readonly SystemSubdomainProvisioner $systemSubdomains,
        private readonly WebServerFactory $webServerFactory,
    ) {}

    public function index(Request $request): Response
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        // Eager-load parentDomain bir sorguda — N+1'i önler
        $allDomains = Domain::where('account_id', $account->id)
            ->with('parentDomain:id,name')
            ->latest()
            ->get();

        $hasWildcardCol = Schema::hasColumn('domains', 'is_wildcard');

        $domains = $allDomains->map(function ($d) use ($hasWildcardCol) {
            $payload = [
                'id' => $d->id,
                'name' => $d->name,
                'type' => $d->type->value,
                'type_label' => $d->type->label(),
                'status' => $d->status->value,
                'status_label' => $d->status->label(),
                'php_version' => $d->php_version,
                'ssl_enabled' => $d->ssl_enabled,
                'force_https' => $d->force_https,
                'reverse_proxy_enabled' => $d->reverse_proxy_enabled,
                'is_wildcard' => $hasWildcardCol ? (bool) ($d->is_wildcard ?? false) : false,
                'wildcard_target_path' => $hasWildcardCol ? ($d->wildcard_target_path ?? null) : null,
                'parent' => $d->parentDomain?->name,
                'document_root' => $d->document_root,
                'created_at' => $d->created_at->format('d.m.Y'),
                'last_error' => $d->last_error,
                'system_subdomains' => [], // default empty
            ];

            // Main/Addon → cPanel-style 6 sistem subdomain status payload
            if (in_array($d->type, [DomainType::Main, DomainType::Addon], strict: true)) {
                $payload['system_subdomains'] = array_values($this->systemSubdomains->statusFor($d));
            }

            return $payload;
        });

        // Kullanım sayılarını in-memory hesapla (3 ayrı DB sorgusu yerine)
        $usageMain = $allDomains->where('type', DomainType::Main)->count();
        $usageAddon = $allDomains->whereIn('type', [DomainType::Addon, DomainType::Parked])->count();
        $usageSubdomain = $allDomains->where('type', DomainType::Subdomain)->count();

        // Paket, account ile birlikte yüklenmiş olmalı; değilse lazy load yap
        $account->loadMissing('package');

        return Inertia::render('Customer/Domains/Index', [
            'domains' => $domains,
            'limits' => [
                'main' => $account->package?->limit('domain_count') ?? null,
                'addon' => $account->package?->limit('addon_domain_count') ?? null,
                'subdomain' => $account->package?->limit('subdomain_count') ?? null,
            ],
            'usage' => [
                'main' => $usageMain,
                'addon' => $usageAddon,
                'subdomain' => $usageSubdomain,
            ],
            'php_versions' => $account->package?->allowedPhpVersions() ?? ['8.2'],
            'parents' => $allDomains
                ->whereIn('type', [DomainType::Main, DomainType::Addon])
                ->values()
                ->map(fn ($d) => ['id' => $d->id, 'name' => $d->name, 'type' => $d->type->value]),
            'active_web_server' => $this->webServerFactory->activeKey(),
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        $validated = $request->validate([
            // RFC 1035 — geçerli FQDN, en az bir nokta ve TLD ≥ 2 harf
            'name' => ['required', 'string', 'max:253', 'regex:/^(?=.{1,253}$)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/'],
            'type' => ['required', 'in:addon,parked,subdomain'],
            'parent_domain_id' => ['nullable', 'integer', 'exists:domains,id'],
            'php_version' => ['nullable', 'string', 'max:4'],
            'ssl_enabled' => ['boolean'],
            'reverse_proxy_enabled' => ['boolean'],
        ], [
            'name.regex' => 'Geçerli bir alan adı girin (örn: example.com).',
        ]);

        // Php versiyonu opsiyonel — verilmezse sistem default'una düşer (domains migration: '8.2')
        $validated['php_version'] ??= '8.2';

        // Reverse proxy yalnız Nginx aktifken anlamlı
        $reverseProxy = ($validated['reverse_proxy_enabled'] ?? false)
            && $this->webServerFactory->activeKey() === 'nginx';

        try {
            $domain = $this->provisioner->add($account, $validated['name'], [
                'type' => DomainType::from($validated['type']),
                'parent_domain_id' => $validated['parent_domain_id'] ?? null,
                'php_version' => $validated['php_version'],
                'ssl_enabled' => $validated['ssl_enabled'] ?? false,
                'reverse_proxy_enabled' => $reverseProxy,
            ]);

            // Wire FPM pool + confirm vhost is active after DB insert.
            // DomainProvisioner already calls vhost-add; this call is
            // the canonical post-provision hook for any extra vhost ops
            // (e.g. FPM pool, cert path update after first SSL issue).
            try {
                $this->vhost->create($domain);
            } catch (SysapiException $e) {
                // Vhost already created by DomainProvisioner — log but don't fail the request.
                // A separate admin action can re-run the vhost creation if needed.
                report($e);
            }

            return redirect()
                ->route('customer.domains.index')
                ->with('success', "Domain '{$validated['name']}' başarıyla eklendi.");
        } catch (DomainException $e) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', $e->getMessage());
        } catch (SysapiException $e) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', "Sistem hatası: {$e->getMessage()}");
        }
    }

    public function destroy(Request $request, Domain $domain): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        // Multi-tenant izolasyon: başka hesabın domain'i için 404 dön (varlığı sızdırma)
        if ($domain->account_id !== $account->id) {
            abort(404);
        }

        try {
            // Remove vhost config first (before DB delete, so we still have domain data).
            try {
                $this->vhost->remove($domain);
            } catch (SysapiException $e) {
                // Non-fatal: vhost may already be absent (manual removal, migration).
                // DomainProvisioner.remove() also calls vhost-remove; log and continue.
                report($e);
            }

            $this->provisioner->remove($domain);

            return redirect()
                ->route('customer.domains.index')
                ->with('success', "Domain '{$domain->name}' kaldırıldı.");
        } catch (DomainException $e) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', $e->getMessage());
        } catch (SysapiException $e) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', "Sistem hatası: {$e->getMessage()}");
        }
    }

    /**
     * Phase 1 Epic 6 — PHP-FPM versiyon değiştir.
     */
    public function updatePhpVersion(Request $request, Domain $domain, SysapiBridge $sysapi): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        if ($domain->account_id !== $account->id) {
            abort(403);
        }

        $allowedVersions = $account->package?->allowedPhpVersions() ?? ['8.2'];
        $validated = $request->validate([
            'php_version' => ['required', 'string', 'in:'.implode(',', $allowedVersions)],
        ]);

        $oldVersion = $domain->php_version;

        $result = $sysapi->run('fpm-pool-switch-version', [
            'username' => $account->username,
            'domain' => $domain->name,
            'old_version' => $oldVersion,
            'new_version' => $validated['php_version'],
            'vhost_file' => $domain->vhostFileName(),
        ]);

        if ($result->failed()) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', "PHP versiyon değiştirme başarısız: {$result->stderr}");
        }

        $domain->update(['php_version' => $validated['php_version']]);

        return redirect()
            ->route('customer.domains.index')
            ->with('success', "PHP versiyonu {$oldVersion} → {$validated['php_version']} olarak değiştirildi.");
    }

    /**
     * Sistem subdomain'leri (mail/webmail/panel/webdisk/autodiscover/autoconfig)
     * yeniden provision et. Admin/Customer arasında ortak; aşağıdaki guard ile
     * yalnızca kendi hesabının domain'i için izin verilir.
     */
    public function reprovisionSystemSubdomains(Request $request, Domain $domain): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        if ($domain->account_id !== $account->id) {
            abort(403);
        }

        // Yalnızca main/addon için anlamlı
        if (! in_array($domain->type, [DomainType::Main, DomainType::Addon], strict: true)) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', 'Sistem subdomain\'leri yalnızca ana veya ek alan adları için provision edilir.');
        }

        try {
            $result = $this->systemSubdomains->provisionSystemSubdomains($domain);

            $createdCount = count($result['created']);
            $errorCount = count($result['errors']);

            if ($errorCount > 0) {
                $errorList = implode(', ', array_keys($result['errors']));

                return redirect()
                    ->route('customer.domains.index')
                    ->with('warning', "Kısmi başarı: {$createdCount} subdomain provision edildi, {$errorCount} başarısız ({$errorList}).");
            }

            return redirect()
                ->route('customer.domains.index')
                ->with('success', "{$createdCount} sistem subdomain'i başarıyla provision edildi.");
        } catch (\Throwable $e) {
            return redirect()
                ->route('customer.domains.index')
                ->with('error', "Sistem subdomain provision hatası: {$e->getMessage()}");
        }
    }

    // ─── One-Click Setup Wizard ───────────────────────────────────────────
    //
    // /panel/domains/wizard           → form (step 1-3)
    // POST /panel/domains/wizard      → provision + render Wizard at step 4
    // GET  /panel/domains/{d}/status  → JSON live progress (polled every 2s)
    //
    // Felsefe: tek tıkla full setup — Apache vhost, DNS zone, AutoSSL,
    // 6 sistem subdomain, default site, ve isteğe bağlı info@ mailbox +
    // WordPress kurulumu. Kullanıcı bekleyecek tek şey: AutoSSL'in DNS
    // propagation için beklediği 5dk.

    public function wizard(Request $request): Response
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $account->loadMissing('package');

        // Admin "Sistem Ayarları" → DNS sekmesinden NS bilgilerini oku
        $nsSettings = \Illuminate\Support\Facades\DB::table('server_settings')
            ->whereIn('key', ['dns_ns1', 'dns_ns2', 'dns_ns3', 'dns_ns4', 'primary_ip'])
            ->pluck('value', 'key');

        $nameservers = array_values(array_filter([
            $nsSettings['dns_ns1'] ?? 'ns1.onox.com.tr',
            $nsSettings['dns_ns2'] ?? 'ns2.onox.com.tr',
            $nsSettings['dns_ns3'] ?? null,
            $nsSettings['dns_ns4'] ?? null,
        ]));

        $serverIp = $nsSettings['primary_ip']
            ?? config('onoxsoft.server_ip')
            ?? config('app.server_ip');

        return Inertia::render('Customer/Domains/Wizard', [
            'php_versions' => $account->package?->allowedPhpVersions() ?? ['8.2'],
            'server_ip' => $serverIp,
            'nameservers' => $nameservers,
            'initial_step' => 1,
        ]);
    }

    public function wizardStore(Request $request): Response|RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $account->loadMissing('package');

        $allowedPhpVersions = $account->package?->allowedPhpVersions() ?? ['8.2'];

        $validated = $request->validate([
            // RFC 1035 — aynı store() ile aynı regex
            'name' => ['required', 'string', 'max:253', 'regex:/^(?=.{1,253}$)(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]{2,}$/'],
            'php_version' => ['required', 'string', 'in:'.implode(',', $allowedPhpVersions)],
            'enable_ssl' => ['boolean'],
            'create_dns' => ['boolean'],
            'system_subdomains' => ['boolean'],
            'default_site' => ['boolean'],
            'create_email' => ['boolean'],
            'wordpress_install' => ['boolean'],
        ], [
            'name.regex' => 'Geçerli bir alan adı girin (örn: example.com).',
        ]);

        $name = strtolower(trim($validated['name']));

        try {
            // 1. Domain provision (vhost + DB + sistem subdomain trigger).
            //    DomainAdded event → CreateDnsZoneOnDomainAdded + AutoSslOnDomainAdded
            //    listener'ları tetikler. Yani DNS zone ve AutoSSL otomatik kuyruğa girer.
            $domain = $this->provisioner->add($account, $name, [
                'type' => DomainType::Addon, // Wizard her zaman addon kurar
                'php_version' => $validated['php_version'],
                'ssl_enabled' => $validated['enable_ssl'] ?? true,
            ]);

            // Vhost post-provision hook (FPM pool wiring; idempotent)
            try {
                $this->vhost->create($domain);
            } catch (SysapiException $e) {
                report($e); // log only, non-fatal
            }

            // 2. İsteğe bağlı — info@ mailbox + MailboxProvisioningJob
            if ($validated['create_email'] ?? false) {
                $tempPassword = Str::random(16);
                $email = EmailAccount::create([
                    'account_id' => $account->id,
                    'local' => 'info',
                    'domain' => $name,
                    'password_hash' => password_hash($tempPassword, PASSWORD_BCRYPT),
                    'quota_mb' => 1024,
                    'status' => 'provisioning',
                ]);
                dispatch(new MailboxProvisioningJob(
                    emailAccountId: $email->id,
                    action: 'create',
                    plainPassword: $tempPassword,
                ));
            }

            // 3. İsteğe bağlı — WordPress otomatik kurulum (queue'a at)
            //    InstallWordPressJob henüz yoksa loglanır; kullanıcı UI'da
            //    "skipped" görür ama setup bloklamaz.
            if ($validated['wordpress_install'] ?? false) {
                $this->dispatchWordPressInstallSafely($domain, $account);
            }

            return Inertia::render('Customer/Domains/Wizard', [
                'php_versions' => $allowedPhpVersions,
                'server_ip' => config('onoxsoft.server_ip') ?? config('app.server_ip'),
                'initial_step' => 4,
                'domain' => [
                    'id' => $domain->id,
                    'name' => $domain->name,
                ],
                'default_site' => $validated['default_site'] ?? true,
                'create_email' => $validated['create_email'] ?? false,
                'wordpress_install' => $validated['wordpress_install'] ?? false,
            ]);
        } catch (DomainException $e) {
            return redirect()
                ->route('customer.domains.wizard')
                ->withErrors(['name' => $e->getMessage()]);
        } catch (SysapiException $e) {
            return redirect()
                ->route('customer.domains.wizard')
                ->withErrors(['name' => "Sistem hatası: {$e->getMessage()}"]);
        }
    }

    /**
     * Live progress JSON — Wizard.vue 2sn'de bir poll eder.
     * State'ler: pending | in_progress | done | failed | skipped
     */
    public function wizardStatus(Request $request, Domain $domain): JsonResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        if ($domain->account_id !== $account->id) {
            abort(404);
        }

        // ─── vhost ──────────────────────────────────────────────────────
        $vhost = match ($domain->status) {
            DomainStatus::Active => 'done',
            DomainStatus::Error => 'failed',
            DomainStatus::Provisioning => 'in_progress',
            default => 'pending',
        };

        // ─── DNS zone (listener tarafından oluşturulur) ─────────────────
        $dnsZone = DnsZone::where('name', $domain->name)->first();
        $dns = match (true) {
            $dnsZone === null => $vhost === 'done' ? 'in_progress' : 'pending',
            ($dnsZone->status ?? null) === 'error' => 'failed',
            default => 'done',
        };

        // ─── Sistem subdomain'leri (statusFor stateless → vhost done ise done) ──
        $subdomains = $vhost === 'done' ? 'done' : ($vhost === 'failed' ? 'failed' : 'in_progress');

        // ─── SSL cert (AutoSslOnDomainAdded listener → 5dk delay job) ──
        $ssl = 'pending';
        if (! $domain->ssl_enabled) {
            $ssl = 'skipped';
        } else {
            $cert = SslCertificate::where('domain_id', $domain->id)
                ->whereNull('deleted_at')
                ->first();
            if ($cert !== null) {
                $ssl = match ($cert->status?->value ?? 'pending') {
                    'active', 'issued' => 'done',
                    'error', 'failed' => 'failed',
                    default => 'in_progress',
                };
            } elseif ($vhost === 'done') {
                // Vhost geçti ama cert henüz yok — AutoSSL listener delay job'da
                $ssl = 'in_progress';
            }
        }

        // ─── Default site (provisioner'da onx-user-add yazıyor → vhost done ise done) ──
        $defaultSite = $vhost === 'done' ? 'done' : 'pending';

        // ─── info@ mailbox ──────────────────────────────────────────────
        $emailAccount = EmailAccount::where('domain', $domain->name)
            ->where('local', 'info')
            ->where('account_id', $account->id)
            ->first();
        $email = match (true) {
            $emailAccount === null => 'skipped',
            ($emailAccount->status ?? null) === 'active' => 'done',
            ($emailAccount->status ?? null) === 'suspended' => 'failed',
            default => 'in_progress',
        };

        // ─── WordPress (cache flag from wizardStore) ────────────────────
        $wordpress = $this->checkWordPressInstall($domain);

        return response()->json([
            'vhost' => $vhost,
            'dns' => $dns,
            'subdomains' => $subdomains,
            'ssl' => $ssl,
            'default_site' => $defaultSite,
            'email' => $email,
            'wordpress' => $wordpress,
            'last_error' => $domain->last_error,
        ]);
    }

    /**
     * InstallWordPressJob hâlâ phase 2'de — şu an cache flag ile pseudo-status döner.
     * Job hazır olduğunda burası gerçek job state'ine bağlanır.
     */
    private function dispatchWordPressInstallSafely(Domain $domain, Account $account): void
    {
        try {
            // Cache flag — UI hemen "pending" gösterebilsin (job henüz çalışmaya başlamadan).
            // Job kendi state'lerini cache'e ezerek günceller (running → completed/failed).
            cache()->put(
                "wordpress_install:{$domain->id}",
                ['state' => 'pending', 'queued_at' => now()->toIso8601String()],
                now()->addHour(),
            );

            \App\Jobs\InstallWordPressJob::dispatch($domain->id, $account->id)
                ->onQueue('provisioning');

            Log::info('Wizard: WordPress install queued', [
                'domain' => $domain->name,
                'account_id' => $account->id,
            ]);
        } catch (\Throwable $e) {
            // Job dispatch başarısız oldu (queue çalışmıyor vs.) — cache'i failed'a ezme,
            // pending kalsın ki kullanıcı retry edebilsin.
            Log::warning('Wizard: WordPress install dispatch failed', [
                'domain' => $domain->name,
                'error' => $e->getMessage(),
            ]);
        }
    }

    private function checkWordPressInstall(Domain $domain): string
    {
        $flag = cache()->get("wordpress_install:{$domain->id}");
        if ($flag === null) {
            return 'skipped';
        }

        return match ($flag['state'] ?? 'pending') {
            'done', 'installed' => 'done',
            'failed', 'error' => 'failed',
            'installing' => 'in_progress',
            default => 'pending',
        };
    }

    // ─── Wildcard subdomain (Faz J) ───────────────────────────────────────
    //
    // POST /panel/domains/{domain}/wildcard/enable  → ServerAlias *.{domain}
    // POST /panel/domains/{domain}/wildcard/disable → kaldır
    //
    // Bash dispatcher 'wildcard:true' arg'ı ile vhost'a şu satırı yazar:
    //   ServerAlias *.{domain}
    // Ayrıca DNS zone'a `*` A kaydı eklenir (DnsProvisioner::upsertRecord).

    public function enableWildcard(Request $request, Domain $domain, DnsProvisioner $dnsProvisioner): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        if ($domain->account_id !== $account->id) {
            abort(404);
        }

        // Wildcard yalnız main/addon için anlamlı — subdomain'in altına
        // wildcard koymak DNS tarafında catch-all olarak kabul edilmez.
        if (! in_array($domain->type, [DomainType::Main, DomainType::Addon], strict: true)) {
            return back()->with('error', 'Wildcard subdomain yalnız ana veya ek alan adları için etkinleştirilebilir.');
        }

        // Defensive — migration henüz çalışmadıysa açıkça uyar
        if (! Schema::hasColumn('domains', 'is_wildcard')) {
            return back()->with('error', 'Wildcard sütunu henüz oluşturulmamış — admin migration\'ı çalıştırmalı.');
        }

        $validated = $request->validate([
            'wildcard_target_path' => ['nullable', 'string', 'max:512'],
        ]);

        $targetPath = $validated['wildcard_target_path'] ?? null;

        try {
            $domain->update([
                'is_wildcard' => true,
                'wildcard_target_path' => $targetPath,
            ]);

            // Vhost'u wildcard flag'ıyla yeniden yaz — VhostProvisioner zaten
            // is_wildcard'ı okuyup sysapi'ye 'wildcard:true' geçirir.
            $this->vhost->create($domain);

            // DNS — `*` A record (wildcard) ve `*.www` opsiyonel.
            // Zone domain ile aynı ada sahip; account_id de eşleşmeli.
            $serverIp = (string) (\Illuminate\Support\Facades\DB::table('server_settings')
                ->where('key', 'primary_ip')
                ->value('value')
                ?? config('onoxsoft.server_ip')
                ?? config('app.server_ip')
                ?? '127.0.0.1');

            $zone = DnsZone::where('name', $domain->name)
                ->where('account_id', $account->id)
                ->first();

            $dnsAdded = false;
            if ($zone !== null && filter_var($serverIp, FILTER_VALIDATE_IP)) {
                try {
                    $dnsProvisioner->upsertRecord($zone, [
                        'name' => '*.'.$domain->name,
                        'type' => 'A',
                        'content' => $serverIp,
                        'ttl' => 3600,
                    ]);
                    $dnsAdded = true;
                } catch (\Throwable $e) {
                    Log::warning('wildcard.dns_failed', [
                        'domain' => $domain->name,
                        'error' => $e->getMessage(),
                    ]);
                }
            }

            Log::info('domain.wildcard_enabled', [
                'account_id' => $account->id,
                'domain_id' => $domain->id,
                'domain' => $domain->name,
                'target_path' => $targetPath,
                'dns_added' => $dnsAdded,
            ]);

            $suffix = $dnsAdded ? ' (DNS *.A kaydı eklendi)' : ' (DNS kaydı eklenemedi — manuel kontrol)';

            return back()->with('success', "Wildcard subdomain etkin: *.{$domain->name}".$suffix);
        } catch (SysapiException $e) {
            // Rollback — DB'yi geri al ki kullanıcı tutarsız state görmesin
            $domain->update(['is_wildcard' => false, 'wildcard_target_path' => null]);

            return back()->with('error', "Vhost güncellenemedi: {$e->getMessage()}");
        }
    }

    public function disableWildcard(Request $request, Domain $domain, DnsProvisioner $dnsProvisioner): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');

        if ($domain->account_id !== $account->id) {
            abort(404);
        }

        if (! Schema::hasColumn('domains', 'is_wildcard')) {
            return back()->with('error', 'Wildcard sütunu henüz oluşturulmamış.');
        }

        try {
            $domain->update([
                'is_wildcard' => false,
                'wildcard_target_path' => null,
            ]);

            // Vhost'u ServerAlias *.{domain} olmadan yeniden yaz
            $this->vhost->create($domain);

            // DNS — `*` A record'u sil (varsa)
            $zone = DnsZone::where('name', $domain->name)
                ->where('account_id', $account->id)
                ->first();

            if ($zone !== null) {
                $wildcardRecord = $zone->records()
                    ->where('name', '*.'.$domain->name)
                    ->where('type', 'A')
                    ->first();

                if ($wildcardRecord !== null) {
                    try {
                        $dnsProvisioner->deleteRecord($wildcardRecord);
                    } catch (\Throwable $e) {
                        Log::warning('wildcard.dns_remove_failed', [
                            'domain' => $domain->name,
                            'error' => $e->getMessage(),
                        ]);
                    }
                }
            }

            Log::info('domain.wildcard_disabled', [
                'account_id' => $account->id,
                'domain_id' => $domain->id,
                'domain' => $domain->name,
            ]);

            return back()->with('success', "Wildcard subdomain devre dışı: {$domain->name}");
        } catch (SysapiException $e) {
            return back()->with('error', "Vhost güncellenemedi: {$e->getMessage()}");
        }
    }
}
