<?php

declare(strict_types=1);

namespace App\Http\Controllers\Customer;

use App\Domain\Account\Models\Account;
use App\Domain\AppInstaller\Models\InstalledApp;
use App\Domain\WordPress\Models\WpActionLog;
use App\Domain\WordPress\Services\WordPressStagingService;
use App\Domain\WordPress\Services\WpCliService;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Inertia\Inertia;
use Inertia\Response;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

/**
 * WordPress Toolkit — Plesk WP Toolkit muadili (Phase 2).
 *
 * Phase 2 yenilikleri:
 * - Plugin/theme/user gerçek WP-CLI yönetimi (WpCliService)
 * - Staging ortamı oluştur/push/sil (WordPressStagingService)
 * - Debug modu, maintenance modu, güvenlik sertleştirme
 * - Search-replace, DB export, WP-Cron görüntüleyici
 * - wp_action_log audit trail
 *
 * Mock data FakeSysapi ile dev modda çalışmaya devam eder.
 */
class WordPressToolkitController extends Controller
{
    public function __construct(
        private readonly WpCliService $wpCli,
        private readonly WordPressStagingService $staging,
    ) {}

    // ─── Index / Show ─────────────────────────────────────────────────────────

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

        $sites = InstalledApp::where('account_id', $account->id)
            ->whereIn('app_type', ['wordpress', 'woocommerce'])
            ->whereNull('is_staging_of')   // Staging'leri listede gösterme
            ->with('domain:id,name')
            ->whereNull('deleted_at')
            ->get()
            ->map(fn ($a) => [
                'id' => $a->id,
                'site_title' => $a->site_title,
                'install_url' => $a->install_url,
                'version' => $a->version,
                'wp_version' => $a->wp_version,
                'app_type' => $a->app_type,
                'domain_name' => $a->domain?->name,
                'updates_available' => $a->updates_available,
                'latest_available_version' => $a->latest_available_version,
                'auto_update' => $a->config_overrides['auto_update'] ?? false,
                'auto_update_core' => $a->auto_update_core ?? 'minor',
                'security_hardened' => $a->security_hardened ?? false,
                'wp_debug_enabled' => $a->wp_debug_enabled ?? false,
                'wp_maintenance_mode' => $a->wp_maintenance_mode ?? false,
                'staging_count' => InstalledApp::where('is_staging_of', $a->id)->whereNull('deleted_at')->count(),
                'installed_at' => $a->installed_at?->format('d.m.Y'),
                'last_checked_at' => $a->last_checked_at?->format('d.m.Y H:i'),
            ]);

        return Inertia::render('Customer/WordPress/Index', [
            'sites' => $sites,
        ]);
    }

    public function show(Request $request, InstalledApp $app): Response
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $app->load('domain:id,name');

        // WP-CLI üzerinden (Phase 2) — FakeSysapi dev modda mock döner
        $plugins = $this->wpCli->plugins($app);
        $themes = $this->wpCli->themes($app);
        $users = $this->wpCli->users($app);
        $cron = $this->wpCli->cron($app);

        // Staging'ler
        $stagings = InstalledApp::where('is_staging_of', $app->id)
            ->whereNull('deleted_at')
            ->with('domain:id,name')
            ->get()
            ->map(fn ($s) => [
                'id' => $s->id,
                'staging_label' => $s->staging_label,
                'install_url' => $s->install_url,
                'status' => $s->status,
                'installed_at' => $s->installed_at?->format('d.m.Y H:i'),
            ]);

        // Action log (son 50)
        $actionLog = WpActionLog::where('installed_app_id', $app->id)
            ->orderByDesc('executed_at')
            ->limit(50)
            ->get()
            ->map(fn ($l) => [
                'id' => $l->id,
                'action' => $l->action,
                'success' => $l->success,
                'output' => $l->output,
                'duration_ms' => $l->duration_ms,
                'executed_at' => $l->executed_at?->format('d.m.Y H:i:s'),
            ]);

        return Inertia::render('Customer/WordPress/Show', [
            'site' => [
                'id' => $app->id,
                'site_title' => $app->site_title,
                'install_url' => $app->install_url,
                'version' => $app->version,
                'wp_version' => $app->wp_version,
                'app_type' => $app->app_type,
                'domain_name' => $app->domain?->name,
                'admin_username' => $app->admin_username,
                'admin_email' => $app->admin_email,
                'language' => $app->language,
                'updates_available' => $app->updates_available,
                'latest_available_version' => $app->latest_available_version,
                'auto_update' => $app->config_overrides['auto_update'] ?? false,
                'auto_update_core' => $app->auto_update_core ?? 'minor',
                'auto_update_plugins' => $app->auto_update_plugins ?? false,
                'auto_update_themes' => $app->auto_update_themes ?? false,
                'wp_debug_enabled' => $app->wp_debug_enabled ?? false,
                'wp_maintenance_mode' => $app->wp_maintenance_mode ?? false,
                'security_hardened' => $app->security_hardened ?? false,
                'installed_at' => $app->installed_at?->format('d.m.Y'),
            ],
            'plugins' => $plugins,
            'themes' => $themes,
            'users' => $users,
            'cron' => $cron,
            'stagings' => $stagings,
            'action_log' => $actionLog,
        ]);
    }

    public function update(Request $request, InstalledApp $app): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'version' => ['nullable', 'string', 'regex:/^\d+\.\d+(\.\d+)?$/'],
        ]);

        // WpCliService::coreUpdate başarılı olursa app DB satırı güncellenir.
        $result = $this->wpCli->coreUpdate($app, $validated['version'] ?? null);

        if (! $result['success']) {
            return back()->with('error',
                'Güncelleme başarısız oldu: '.($result['stderr'] ?: 'WP-CLI core update hatası')
            );
        }

        $app->refresh();
        return back()->with('success', "{$app->site_title} → v{$app->wp_version} güncellendi.");
    }

    public function toggleAutoUpdate(Request $request, InstalledApp $app): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $config = $app->config_overrides ?? [];
        $config['auto_update'] = ! ($config['auto_update'] ?? false);
        $app->update(['config_overrides' => $config]);

        return back()->with('success', $config['auto_update']
            ? 'Otomatik güncelleme açık.'
            : 'Otomatik güncelleme kapalı.');
    }

    public function loginAsAdmin(Request $request, InstalledApp $app): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $adminLogin = $app->admin_username ?: 'admin';

        // WP 5.6+ Application Passwords API üzerinden tek-kullanımlık token üret.
        // wp user application-password create <user> "ONOXSOFT Panel SSO" --porcelain
        $result = $this->wpCli->createApplicationPassword(
            $app,
            $adminLogin,
            'ONOXSOFT Panel SSO '.now()->format('Ymd-His')
        );

        if (! $result['success'] || empty($result['password'])) {
            // Fallback: wp-admin'e yönlendir (kullanıcı normal şifreyle giriş yapsın)
            return redirect()->away(rtrim($app->install_url, '/').'/wp-admin/')
                ->with('warning',
                    'SSO için application password üretilemedi (WP 5.6+ gerekiyor). '
                    .'Yönetici şifrenizle giriş yapın.'
                );
        }

        // Audit log — token oluşturuldu
        WpActionLog::create([
            'installed_app_id' => $app->id,
            'triggered_by' => $request->user()?->id,
            'action' => 'sso.application-password-issued',
            'parameters' => [
                'admin_login' => $adminLogin,
                'panel_user_id' => $request->user()?->id,
                'ip' => $request->ip(),
            ],
            'success' => true,
            'output' => 'Application password issued for SSO login',
            'duration_ms' => 0,
            'executed_at' => now(),
        ]);

        // WP /wp-login.php application_password destekler (WP 5.6+).
        // Düz wp-admin'e yönlendir + tarayıcıya HTTP Basic Auth credentials geçir.
        // WP REST /wp-json/wp/v2/users/me ile token doğrulanır.
        // Güvenli yol: wp-admin'e redirect, kullanıcıdan manuel adımı kaldırmak için
        // application_password'ü query string'de **yollamayız** (server log leak riski).
        // Yerine: kullanıcının session'ına one-shot token koyup proxy endpoint üzerinden enjekte et.
        // MVP'de: token'i flash session'a koyup wp-admin'e yönlendir; frontend toast'ta gösterilir.
        session()->flash('wp_sso_credentials', [
            'login' => $adminLogin,
            'app_password' => $result['password'],  // Tek kullanımlık (WP tarafında revoke edilebilir)
            'expires_in' => 600,                    // İstemcide 10 dk sonra unutulur
        ]);

        return redirect()->away(rtrim($app->install_url, '/').'/wp-admin/');
    }

    /**
     * Legacy "clone" route — eski UI'lardan geliyor. Yeni Toolkit UI doğrudan
     * `createStaging` action'ını kullanır; bu metot backward-compat shim.
     */
    public function clone(Request $request, InstalledApp $app): RedirectResponse
    {
        /** @var Account $account */
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'target_subdomain' => ['required', 'string', 'min:3', 'max:30', 'regex:/^[a-z0-9-]+$/'],
        ]);

        try {
            $stagingApp = $this->staging->createStaging($app, $validated['target_subdomain']);

            return redirect()
                ->route('customer.wp.staging', $app->id)
                ->with('success', "Staging clone hazır: {$stagingApp->install_url}");
        } catch (\Throwable $e) {
            return back()->with('error',
                "Staging clone başarısız: {$e->getMessage()}");
        }
    }

    // ─── Plugins ─────────────────────────────────────────────────────────────

    public function plugins(Request $request, InstalledApp $app): Response
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $plugins = $this->wpCli->plugins($app);

        return Inertia::render('Customer/WordPress/Show', [
            'site' => $this->siteArray($app),
            'plugins' => $plugins,
        ]);
    }

    public function pluginInstall(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'slug' => ['required', 'string', 'regex:/^[a-z0-9-]+$/'],
            'activate' => ['boolean'],
        ]);

        $result = $this->wpCli->installPlugin($app, $validated['slug'], $validated['activate'] ?? true);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success']
                ? "'{$validated['slug']}' eklentisi kuruldu."
                : "Kurulum başarısız: {$result['stderr']}");
    }

    public function pluginActivate(Request $request, InstalledApp $app, string $slug): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->activatePlugin($app, $slug);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? "'{$slug}' eklentisi aktif edildi." : "Hata: {$result['stderr']}");
    }

    public function pluginDeactivate(Request $request, InstalledApp $app, string $slug): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->deactivatePlugin($app, $slug);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? "'{$slug}' eklentisi devre dışı bırakıldı." : "Hata: {$result['stderr']}");
    }

    public function pluginUpdate(Request $request, InstalledApp $app, string $slug): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->updatePlugin($app, $slug);
        $label = $slug === 'all' ? 'Tüm eklentiler' : "'{$slug}'";

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? "{$label} güncellendi." : "Hata: {$result['stderr']}");
    }

    public function pluginDelete(Request $request, InstalledApp $app, string $slug): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->deletePlugin($app, $slug);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? "'{$slug}' eklentisi silindi." : "Hata: {$result['stderr']}");
    }

    // ─── Themes ──────────────────────────────────────────────────────────────

    public function themes(Request $request, InstalledApp $app): Response
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        return Inertia::render('Customer/WordPress/Show', [
            'site' => $this->siteArray($app),
            'themes' => $this->wpCli->themes($app),
        ]);
    }

    public function themeActivate(Request $request, InstalledApp $app, string $slug): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->activateTheme($app, $slug);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? "'{$slug}' teması aktif edildi." : "Hata: {$result['stderr']}");
    }

    public function themeDelete(Request $request, InstalledApp $app, string $slug): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->deleteTheme($app, $slug);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? "'{$slug}' teması silindi." : "Hata: {$result['stderr']}");
    }

    // ─── Users ───────────────────────────────────────────────────────────────

    public function users(Request $request, InstalledApp $app): Response
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        return Inertia::render('Customer/WordPress/Show', [
            'site' => $this->siteArray($app),
            'users' => $this->wpCli->users($app),
        ]);
    }

    public function userCreate(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'login' => ['required', 'string', 'min:3', 'max:60'],
            'email' => ['required', 'email'],
            'role' => ['required', 'string', 'in:administrator,editor,author,contributor,subscriber'],
            'password' => ['required', 'string', 'min:8'],
        ]);

        $result = $this->wpCli->createUser($app, $validated);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success']
                ? "Kullanıcı '{$validated['login']}' oluşturuldu."
                : "Kullanıcı oluşturulamadı: {$result['stderr']}");
    }

    public function userDelete(Request $request, InstalledApp $app, int $userId): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->deleteUser($app, $userId);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? 'Kullanıcı silindi.' : "Hata: {$result['stderr']}");
    }

    public function userResetPassword(Request $request, InstalledApp $app, int $userId): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'password' => ['required', 'string', 'min:8'],
        ]);

        $result = $this->wpCli->resetUserPassword($app, $userId, $validated['password']);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? 'Şifre sıfırlandı.' : "Hata: {$result['stderr']}");
    }

    // ─── Settings / Tools ────────────────────────────────────────────────────

    public function debug(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'enabled' => ['required', 'boolean'],
            'debug_log' => ['boolean'],
            'debug_display' => ['boolean'],
        ]);

        $result = $this->wpCli->setDebug(
            $app,
            (bool) $validated['enabled'],
            (bool) ($validated['debug_log'] ?? true),
            (bool) ($validated['debug_display'] ?? false),
        );

        return back()->with($result['success'] ? 'success' : 'error',
            $validated['enabled'] ? 'Debug modu açıldı.' : 'Debug modu kapatıldı.');
    }

    public function maintenance(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'enabled' => ['required', 'boolean'],
            'message' => ['nullable', 'string', 'max:500'],
        ]);

        $result = $this->wpCli->setMaintenance(
            $app,
            (bool) $validated['enabled'],
            $validated['message'] ?? '',
        );

        return back()->with($result['success'] ? 'success' : 'error',
            $validated['enabled'] ? 'Bakım modu açıldı.' : 'Bakım modu kapatıldı.');
    }

    public function harden(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $result = $this->wpCli->harden($app);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success']
                ? 'Güvenlik sertleştirmesi uygulandı.'
                : 'Sertleştirme kısmen başarısız oldu.');
    }

    public function searchReplace(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'search' => ['required', 'string'],
            'replace' => ['required', 'string'],
            'dry_run' => ['boolean'],
        ]);

        $result = $this->wpCli->searchReplace(
            $app,
            $validated['search'],
            $validated['replace'],
            (bool) ($validated['dry_run'] ?? true),
        );

        return back()->with($result['success'] ? 'success' : 'error',
            $validated['dry_run']
                ? "Kuru çalıştırma tamamlandı: {$result['output']}"
                : 'Search-replace tamamlandı.');
    }

    public function dbExport(Request $request, InstalledApp $app): RedirectResponse|BinaryFileResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $filePath = $this->wpCli->dbExport($app);

        if (file_exists($filePath)) {
            return response()->download($filePath)->deleteFileAfterSend();
        }

        return back()->with('success', 'DB export başlatıldı. Dosya hazır olduğunda bildirim alacaksınız.');
    }

    public function cron(Request $request, InstalledApp $app): Response
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        return Inertia::render('Customer/WordPress/Show', [
            'site' => $this->siteArray($app),
            'cron' => $this->wpCli->cron($app),
        ]);
    }

    public function runCron(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $hook = $request->input('hook', '');
        $result = $this->wpCli->runCron($app, $hook);

        return back()->with($result['success'] ? 'success' : 'error',
            $result['success'] ? 'Cron başarıyla çalıştırıldı.' : "Hata: {$result['stderr']}");
    }

    // ─── Staging ─────────────────────────────────────────────────────────────

    public function staging(Request $request, InstalledApp $app): Response
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $stagings = InstalledApp::where('is_staging_of', $app->id)
            ->whereNull('deleted_at')
            ->with('domain:id,name')
            ->orderByDesc('installed_at')
            ->get()
            ->map(fn ($s) => [
                'id' => $s->id,
                'staging_label' => $s->staging_label,
                'install_url' => $s->install_url,
                'status' => $s->status,
                'installed_at' => $s->installed_at?->format('d.m.Y H:i'),
                'is_staging' => true,
            ]);

        return Inertia::render('Customer/WordPress/Staging', [
            'site' => $this->siteArray($app),
            'stagings' => $stagings,
        ]);
    }

    public function createStaging(Request $request, InstalledApp $app): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        $this->authorizeApp($app, $account);

        $validated = $request->validate([
            'staging_label' => ['required', 'string', 'min:3', 'max:30', 'regex:/^[a-z0-9-]+$/'],
        ]);

        try {
            $stagingApp = $this->staging->createStaging($app, $validated['staging_label']);

            return redirect()
                ->route('customer.wp.staging', $app->id)
                ->with('success', "Staging '{$stagingApp->install_url}' oluşturuldu.");
        } catch (\Throwable $e) {
            return back()->with('error', "Staging oluşturulamadı: {$e->getMessage()}");
        }
    }

    public function pushStaging(Request $request, InstalledApp $stagingApp): RedirectResponse
    {
        // Staging'in production'ını bul, account kontrolü yap
        $account = $request->attributes->get('customer_account');
        if ($stagingApp->account_id !== $account->id) {
            abort(403);
        }
        if ($stagingApp->is_staging_of === null) {
            abort(422, 'Bu app bir staging değil.');
        }

        $validated = $request->validate([
            'include_db' => ['boolean'],
            'include_files' => ['boolean'],
            'exclude_uploads' => ['boolean'],
        ]);

        try {
            $result = $this->staging->pushToProduction($stagingApp, $validated);

            return back()->with('success', $result['message']);
        } catch (\Throwable $e) {
            return back()->with('error', "Push başarısız: {$e->getMessage()}");
        }
    }

    public function deleteStaging(Request $request, InstalledApp $stagingApp): RedirectResponse
    {
        $account = $request->attributes->get('customer_account');
        if ($stagingApp->account_id !== $account->id) {
            abort(403);
        }
        if ($stagingApp->is_staging_of === null) {
            abort(422, 'Bu app bir staging değil.');
        }

        $productionId = $stagingApp->is_staging_of;

        try {
            $this->staging->deleteStaging($stagingApp);

            return redirect()
                ->route('customer.wp.staging', $productionId)
                ->with('success', 'Staging silindi.');
        } catch (\Throwable $e) {
            return back()->with('error', "Silme başarısız: {$e->getMessage()}");
        }
    }

    // ─── Private ─────────────────────────────────────────────────────────────

    private function authorizeApp(InstalledApp $app, Account $account): void
    {
        if ($app->account_id !== $account->id) {
            abort(403);
        }
        if (! in_array($app->app_type, ['wordpress', 'woocommerce'], true)) {
            abort(404);
        }
    }

    /** @return array<string, mixed> */
    private function siteArray(InstalledApp $app): array
    {
        $app->loadMissing('domain:id,name');

        return [
            'id' => $app->id,
            'site_title' => $app->site_title,
            'install_url' => $app->install_url,
            'version' => $app->version,
            'wp_version' => $app->wp_version,
            'app_type' => $app->app_type,
            'domain_name' => $app->domain?->name,
            'admin_username' => $app->admin_username,
            'admin_email' => $app->admin_email,
            'language' => $app->language,
            'updates_available' => $app->updates_available,
            'latest_available_version' => $app->latest_available_version,
            'auto_update' => $app->config_overrides['auto_update'] ?? false,
            'auto_update_core' => $app->auto_update_core ?? 'minor',
            'auto_update_plugins' => $app->auto_update_plugins ?? false,
            'auto_update_themes' => $app->auto_update_themes ?? false,
            'wp_debug_enabled' => $app->wp_debug_enabled ?? false,
            'wp_maintenance_mode' => $app->wp_maintenance_mode ?? false,
            'security_hardened' => $app->security_hardened ?? false,
            'installed_at' => $app->installed_at?->format('d.m.Y'),
        ];
    }
}
