<?php

declare(strict_types=1);

namespace App\Http\Controllers\Admin;

use App\Domain\PluginSdk\Services\MarketplaceClient;
use App\Domain\PluginSdk\Services\MockMarketplaceClient;
use App\Domain\PluginSdk\Services\PluginManager;
use App\Http\Controllers\Controller;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Inertia\Inertia;
use Inertia\Response as InertiaResponse;

/**
 * Admin: Plugin Marketplace & Manager (Phase 4)
 *
 * - Kurulu plugin listesi  (Installed.vue)
 * - Marketplace listesi    (Marketplace.vue)
 * - Marketplace plugin detayı + rating + screenshot  (MarketplaceShow.vue)
 * - Kurulu plugin detayı + ayarlar  (Show.vue)
 * - install / update / uninstall / toggle / rate
 * - Vendor portal placeholder  (Vendor.vue)
 */
class PluginController extends Controller
{
    public function __construct(
        private PluginManager $manager,
        private MarketplaceClient $marketplace,
    ) {}

    /**
     * Kurulu pluginleri listele (eski Index — geriye dönük yönlendirme).
     */
    public function index(): InertiaResponse
    {
        return $this->installed();
    }

    /**
     * "Installed" — kurulu pluginler ayrı, zenginleştirilmiş liste.
     */
    public function installed(): InertiaResponse
    {
        $plugins = $this->manager->enabledList();

        // Marketplace'ten "latest_version" alıp update badge'ı için işaretle (best-effort).
        // 5 dakika cache — kurulu plugin sayfası her açılışta marketplace'i yormasın.
        $latestBySlug = Cache::remember('plugin_marketplace.latest_versions', 300, function () {
            $map = [];
            try {
                foreach ($this->marketplace->listPlugins() as $p) {
                    $map[$p['slug']] = $p['latest_version'] ?? $p['version'];
                }
            } catch (\Throwable $e) {
                // Marketplace down — boş cache döner, update kolonu görünmez
            }
            return $map;
        });

        $plugins = $plugins->map(function ($row) use ($latestBySlug) {
            $row->latest_version = $latestBySlug[$row->slug] ?? null;
            $row->update_available = $row->latest_version
                && version_compare($row->latest_version, $row->version, '>');

            return $row;
        });

        return Inertia::render('Admin/Plugins/Installed', [
            'plugins' => $plugins,
        ]);
    }

    /**
     * Marketplace'den plugin listesi.
     */
    public function marketplace(Request $request): InertiaResponse
    {
        $filters = $request->only(['category', 'search', 'sort']);

        $plugins = $this->marketplace->listPlugins($filters);

        $installedSlugs = DB::table('installed_plugins')
            ->pluck('version', 'slug')
            ->toArray();

        $plugins = array_map(function ($p) use ($installedSlugs) {
            $p['installed'] = isset($installedSlugs[$p['slug']]);
            $p['installed_version'] = $installedSlugs[$p['slug']] ?? null;

            return $p;
        }, $plugins);

        $categories = array_merge(['' => 'Tümü'], MarketplaceClient::categories());

        return Inertia::render('Admin/Plugins/Marketplace', [
            'plugins' => $plugins,
            'categories' => $categories,
            'filters' => $filters,
            'isMock' => $this->isMockEnabled(),
        ]);
    }

    /**
     * Marketplace plugin detay — screenshots, changelog, ratings.
     */
    public function marketplaceShow(string $slug): InertiaResponse
    {
        $plugin = $this->marketplace->getPlugin($slug);

        if (! $plugin) {
            abort(404, "Marketplace'de plugin bulunamadı: {$slug}");
        }

        $installed = DB::table('installed_plugins')
            ->where('slug', $slug)
            ->first(['version', 'installed_at']);

        $plugin['installed'] = $installed !== null;
        $plugin['installed_version'] = $installed?->version;

        $ratings = $this->marketplace->getRatings($slug);

        return Inertia::render('Admin/Plugins/MarketplaceShow', [
            'plugin' => $plugin,
            'ratings' => $ratings,
            'isMock' => $this->isMockEnabled(),
        ]);
    }

    /**
     * Kurulu plugin detay sayfası (eski).
     */
    public function show(string $slug): InertiaResponse
    {
        $plugin = DB::table('installed_plugins')->where('slug', $slug)->first();

        if (! $plugin) {
            abort(404, "Plugin bulunamadı: {$slug}");
        }

        $manifest = json_decode($plugin->manifest, true) ?? [];
        $plugin->manifest = $manifest;
        $plugin->config = $plugin->config ? json_decode($plugin->config, true) : [];

        return Inertia::render('Admin/Plugins/Show', [
            'plugin' => $plugin,
        ]);
    }

    /**
     * Vendor portal placeholder — marketplace.onox.com.tr'a link.
     */
    public function vendor(): InertiaResponse
    {
        return Inertia::render('Admin/Plugins/Vendor', [
            'vendorPortalUrl' => rtrim(
                config('services.marketplace.url', 'https://marketplace.onox.com.tr'),
                '/'
            ).'/vendor',
        ]);
    }

    /**
     * Marketplace'den plugin kur.
     */
    public function install(Request $request, string $slug): RedirectResponse
    {
        $request->validate([
            'version' => 'nullable|string|max:30',
        ]);

        try {
            $result = $this->manager->installFromMarketplace($slug, $request->input('version'));

            return redirect()
                ->route('admin.plugins.installed')
                ->with('success', "'{$result['name']}' v{$result['version']} başarıyla kuruldu.");
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    /**
     * Plugin'i yeni sürüme güncelle (marketplace'ten).
     */
    public function update(Request $request, string $slug): RedirectResponse
    {
        $request->validate([
            'version' => 'nullable|string|max:30',
        ]);

        try {
            $result = $this->manager->update($slug, $request->input('version'));

            return back()->with(
                'success',
                "'{$result['name']}' v{$result['from']} → v{$result['to']} güncellendi."
            );
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    /**
     * Plugin'e rating gönder (1-5 yıldız + opsiyonel yorum).
     */
    public function rate(Request $request, string $slug): RedirectResponse
    {
        $data = $request->validate([
            'stars' => 'required|integer|min:1|max:5',
            'comment' => 'nullable|string|max:1000',
        ]);

        $result = $this->marketplace->submitRating($slug, $data['stars'], $data['comment'] ?? null);

        return back()->with(
            $result['ok'] ? 'success' : 'error',
            $result['message'] ?? ($result['ok'] ? 'Rating gönderildi.' : 'Rating gönderilemedi.')
        );
    }

    /**
     * Zip dosyasından plugin yükle.
     */
    public function uploadInstall(Request $request): RedirectResponse
    {
        $request->validate([
            'zip' => 'required|file|mimes:zip|max:51200', // 50 MB
        ]);

        $zipPath = $request->file('zip')->store('plugin-uploads', 'local');
        $fullPath = storage_path('app/'.$zipPath);

        try {
            $result = $this->manager->installFromFile($fullPath);

            return redirect()
                ->route('admin.plugins.installed')
                ->with('success', "'{$result['name']}' v{$result['version']} başarıyla kuruldu.");
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        } finally {
            if (file_exists($fullPath)) {
                unlink($fullPath);
            }
        }
    }

    /**
     * Plugin kaldır.
     */
    public function uninstall(string $slug): RedirectResponse
    {
        try {
            $this->manager->uninstall($slug);

            return redirect()
                ->route('admin.plugins.installed')
                ->with('success', "Plugin '{$slug}' başarıyla kaldırıldı.");
        } catch (\RuntimeException $e) {
            return back()->with('error', $e->getMessage());
        }
    }

    /**
     * Plugin etkinleştir/devre dışı bırak.
     */
    public function toggle(string $slug): RedirectResponse
    {
        $plugin = DB::table('installed_plugins')->where('slug', $slug)->first();

        if (! $plugin) {
            abort(404);
        }

        if ($plugin->enabled) {
            $this->manager->disable($slug);
            $msg = "Plugin '{$slug}' devre dışı bırakıldı.";
        } else {
            $this->manager->enable($slug);
            $msg = "Plugin '{$slug}' etkinleştirildi.";
        }

        return back()->with('success', $msg);
    }

    /**
     * Plugin ayarlarını güncelle.
     */
    public function settingsUpdate(Request $request, string $slug): RedirectResponse
    {
        $plugin = DB::table('installed_plugins')->where('slug', $slug)->first();

        if (! $plugin) {
            abort(404);
        }

        $manifest = json_decode($plugin->manifest, true) ?? [];
        $settingsSchema = $manifest['settings_schema'] ?? [];

        // Build validation rules from schema
        $rules = [];
        foreach ($settingsSchema as $key => $field) {
            $rule = [];
            if (! empty($field['required'])) {
                $rule[] = 'required';
            } else {
                $rule[] = 'nullable';
            }
            if (($field['type'] ?? '') === 'boolean') {
                $rule[] = 'boolean';
            } elseif (($field['type'] ?? '') === 'number') {
                $rule[] = 'numeric';
            } else {
                $rule[] = 'string';
                $rule[] = 'max:1024';
            }
            $rules[$key] = implode('|', $rule);
        }

        $validated = $request->validate($rules);

        $existing = $plugin->config ? json_decode($plugin->config, true) : [];
        $merged = array_merge($existing, $validated);

        DB::table('installed_plugins')
            ->where('slug', $slug)
            ->update(['config' => json_encode($merged), 'updated_at' => now()]);

        return back()->with('success', 'Plugin ayarları kaydedildi.');
    }

    /**
     * UI banner için — gerçek marketplace mı yoksa mock mu kullanılıyor?
     * Service container binding ile aynı koşul (AppServiceProvider).
     */
    private function isMockEnabled(): bool
    {
        return $this->marketplace instanceof MockMarketplaceClient
            || ! config('services.marketplace.enabled', true)
            || app()->environment('local', 'testing');
    }
}
