<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Domain\Domain\Models\Domain;
use App\Domain\Php\Services\PhpVersionRegistry;
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\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\Rule;
use Inertia\Inertia;
use Inertia\Response;

/**
 * MultiPHP Manager (WHM "MultiPHP Manager" muadili).
 *
 * Admin tüm domainlerin PHP versiyonlarını topluca yönetir.
 * Bulk update + per-domain update + install/uninstall (Faz R).
 *
 * PHP versiyonları PhpVersionRegistry'den gelir (tek kaynak).
 */
class MultiPhpController extends Controller
{
    public function __construct(private readonly PhpVersionRegistry $phpRegistry) {}

    public function index(Request $request): Response
    {
        $installedVersions = $this->phpRegistry->installed();
        $installedSlugs = $this->phpRegistry->installedVersions();

        // Per-version domain count
        $versionCounts = Domain::whereNull('deleted_at')
            ->groupBy('php_version')
            ->selectRaw('php_version, count(*) as count')
            ->pluck('count', 'php_version')
            ->toArray();

        $versionsWithCounts = collect($installedVersions)->map(fn ($v) => array_merge($v, [
            'domain_count' => $versionCounts[$v['version']] ?? 0,
            'default' => $v['version'] === $this->phpRegistry->recommended(),
        ]));

        // All known versions with install state (for "manage" cards)
        $allKnown = collect(PhpVersionRegistry::KNOWN)->map(function ($v) use ($installedSlugs, $versionCounts) {
            $isInstalled = in_array($v['version'], $installedSlugs, true);

            return array_merge($v, [
                'installed' => $isInstalled,
                'fpm_unit' => 'php'.str_replace('.', '', $v['version']).'-php-fpm',
                'domain_count' => $versionCounts[$v['version']] ?? 0,
                'default' => $v['version'] === $this->phpRegistry->recommended(),
            ]);
        })->values();

        // All domains with their PHP version
        $domains = Domain::whereNull('deleted_at')
            ->with(['account:id,username,email'])
            ->orderBy('name')
            ->get()
            ->map(fn ($d) => [
                'id' => $d->id,
                'name' => $d->name,
                'type' => $d->type->value,
                'php_version' => $d->php_version,
                'account_username' => $d->account?->username,
                'account_email' => $d->account?->email,
                'status' => $d->status->value,
            ]);

        return Inertia::render('Admin/MultiPhp', [
            'versions' => $versionsWithCounts,
            'all_known' => $allKnown,
            'domains' => $domains,
            'system_default' => DB::table('server_settings')->where('key', 'php_default_version')->value('value')
                ?? $this->phpRegistry->recommended(),
            'available_for_install' => $this->phpRegistry->availableForInstall(),
        ]);
    }

    public function bulkUpdate(Request $request): RedirectResponse
    {
        $installedVersions = $this->phpRegistry->installedVersions();

        $validated = $request->validate([
            'domain_ids' => ['required', 'array', 'min:1'],
            'domain_ids.*' => ['integer', 'exists:domains,id'],
            'php_version' => ['required', 'string', Rule::in($installedVersions)],
        ]);

        $count = Domain::whereIn('id', $validated['domain_ids'])
            ->whereNull('deleted_at')
            ->update(['php_version' => $validated['php_version']]);

        return back()->with('success', "{$count} domain PHP {$validated['php_version']} sürümüne güncellendi (FPM pool reload pending).");
    }

    public function setSystemDefault(Request $request): RedirectResponse
    {
        $installedVersions = $this->phpRegistry->installedVersions();

        $validated = $request->validate([
            'php_version' => ['required', 'string', Rule::in($installedVersions)],
        ]);

        DB::table('server_settings')->updateOrInsert(
            ['key' => 'php_default_version'],
            ['value' => $validated['php_version'], 'type' => 'select', 'group' => 'php',
                'updated_at' => now(), 'created_at' => now()],
        );

        return back()->with('success', "Sistem varsayılan PHP: {$validated['php_version']}");
    }

    /**
     * Faz R: yeni PHP versiyonu kur (Remi/Sury repo'dan).
     */
    public function install(Request $request): RedirectResponse
    {
        $knownVersions = collect(PhpVersionRegistry::KNOWN)
            ->pluck('version')->all();

        $validated = $request->validate([
            'version' => ['required', 'string', Rule::in($knownVersions)],
            'source' => ['required', 'string', Rule::in(['remi', 'sury', 'source'])],
        ]);

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('php-install', [
                'version' => $validated['version'],
                'source' => $validated['source'],
            ], timeoutSeconds: 600);

            if ($result->failed()) {
                Log::warning('php.install_failed', ['version' => $validated['version'], 'stderr' => $result->stderr]);

                return back()->with('error', "PHP {$validated['version']} kurulamadı: {$result->stderr}");
            }

            $this->phpRegistry->flush();
            $runtime = $result->data['runtime'] ?? "PHP {$validated['version']}";

            return back()->with('success', "PHP {$validated['version']} kuruldu — {$runtime}");
        } catch (SysapiException $e) {
            return back()->with('error', "PHP {$validated['version']} kurulamadı: {$e->getMessage()}");
        }
    }

    /**
     * Faz R: PHP versiyonunu sistemden kaldır.
     * Vhost guard: o versiyonu kullanan vhost varsa script reddeder.
     */
    public function uninstall(Request $request): RedirectResponse
    {
        $installedVersions = $this->phpRegistry->installedVersions();

        $validated = $request->validate([
            'version' => ['required', 'string', Rule::in($installedVersions)],
            'force' => ['nullable', 'boolean'],
        ]);

        // İlk koruma: o versiyon hâlâ domain'lerde kullanılıyorsa engelle
        $usingCount = Domain::whereNull('deleted_at')
            ->where('php_version', $validated['version'])
            ->count();

        if ($usingCount > 0 && empty($validated['force'])) {
            return back()->with('error', "PHP {$validated['version']} hâlâ {$usingCount} domain tarafından kullanılıyor. Önce başka versiyona geçir.");
        }

        try {
            /** @var SysapiBridge $sysapi */
            $sysapi = app(SysapiBridge::class);
            $result = $sysapi->run('php-uninstall', [
                'version' => $validated['version'],
                'force' => (bool) ($validated['force'] ?? false),
            ], timeoutSeconds: 300);

            if ($result->failed()) {
                return back()->with('error', "PHP {$validated['version']} kaldırılamadı: {$result->stderr}");
            }

            $this->phpRegistry->flush();
            $removed = $result->data['packages_removed'] ?? 0;

            return back()->with('success', "PHP {$validated['version']} kaldırıldı ({$removed} paket).");
        } catch (SysapiException $e) {
            return back()->with('error', "PHP {$validated['version']} kaldırılamadı: {$e->getMessage()}");
        }
    }
}
