<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\MarketplacePurchase;
use App\Services\MarketplaceCheckoutService;
use App\Services\MarketplaceService;
use App\Services\MarketplaceStripeService;
use App\Services\ThemeService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class MarketplaceController extends Controller
{
    public function __construct(
        protected ThemeService $themeService,
        protected MarketplaceStripeService $marketplaceStripe,
        protected MarketplaceCheckoutService $marketplaceCheckout,
        protected MarketplaceService $marketplaceService
    ) {}

    public function index()
    {
        $catalogThemes = collect(config('marketplace_catalog.themes', []))
            ->map(function (array $t) {
                $t['screenshot'] = $this->resolveThemeScreenshotUrl($t['screenshot'] ?? null, $t['name'] ?? 'Theme');

                return $t;
            })->all();
        $catalogPlugins = collect(config('marketplace_catalog.plugins', []))
            ->map(function (array $p) {
                $p['screenshot'] = $this->resolveThemeScreenshotUrl($p['screenshot'] ?? null, $p['name'] ?? 'Plugin');

                return $p;
            })->all();
        $installedThemes = $this->themeService->getAvailableThemes();
        $purchases = MarketplacePurchase::where('is_active', true)->get()->keyBy(fn ($p) => $p->item_type.'-'.$p->item_slug);
        $stripeConfigured = $this->marketplaceCheckout->isCheckoutAvailable();

        return view('admin.marketplace.index', compact('catalogThemes', 'catalogPlugins', 'installedThemes', 'purchases', 'stripeConfigured'));
    }

    public function settings()
    {
        $stripeConfigured = $this->marketplaceCheckout->isCheckoutAvailable();
        $paymentDriver = $this->marketplaceCheckout->driver();

        return view('admin.marketplace.settings', compact('stripeConfigured', 'paymentDriver'));
    }

    public function themes()
    {
        $installedThemes = $this->themeService->getAvailableThemes();
        $purchases = MarketplacePurchase::where('item_type', 'theme')->where('is_active', true)->pluck('item_slug')->toArray();

        // Thèmes gratuits : Classic (core) + thèmes personnalisés (content/themes/)
        $freeThemes = [];
        foreach ($installedThemes as $slug => $theme) {
            $source = $theme['source'] ?? 'core';
            $isFree = $source === 'custom' || (($theme['price'] ?? 0) == 0);
            if (! $isFree) {
                continue;
            }
            $freeThemes[] = [
                'slug' => $slug,
                'name' => $theme['name'] ?? ucfirst($slug),
                'description' => $theme['description'] ?? ($source === 'custom' ? 'Thème personnalisé.' : 'Thème inclus avec le CMS.'),
                'price' => 0,
                'screenshot' => $this->resolveThemeScreenshotUrl($theme['screenshot'] ?? null, $theme['name'] ?? $slug),
                'installed' => true,
                'source' => $source,
            ];
        }

        // Thèmes catalogue marketplace (chemins relatifs → asset())
        $paidThemes = collect(config('marketplace_catalog.themes', []))
            ->map(function (array $t) {
                $t['screenshot'] = $this->resolveThemeScreenshotUrl($t['screenshot'] ?? null, $t['name'] ?? 'Theme');

                return $t;
            })->all();

        $catalog = $this->mergeThemeCatalogUniqueBySlug($freeThemes, $paidThemes);

        return view('admin.marketplace.themes', compact('catalog', 'installedThemes', 'purchases'));
    }

    public function plugins()
    {
        $catalog = collect(config('marketplace_catalog.plugins', []))
            ->map(function (array $p) {
                $p['screenshot'] = $this->resolveThemeScreenshotUrl($p['screenshot'] ?? null, $p['name'] ?? 'Plugin');

                return $p;
            })->all();
        $installedPlugins = app(\App\Services\PluginService::class)->getInstalledPlugins();
        $purchases = MarketplacePurchase::where('item_type', 'plugin')->get()->keyBy('item_slug');

        return view('admin.marketplace.plugins', compact('catalog', 'installedPlugins', 'purchases'));
    }

    /**
     * Initie l'achat via Stripe Checkout.
     */
    public function purchase(Request $request)
    {
        $request->validate([
            'type' => 'required|in:theme,plugin',
            'slug' => 'required|string',
        ]);

        $catalog = $request->type === 'theme'
            ? collect(config('marketplace_catalog.themes', []))->keyBy('slug')
            : collect(config('marketplace_catalog.plugins', []))->keyBy('slug');

        $item = $catalog->get($request->slug);
        if (! $item) {
            return back()->withErrors(['slug' => 'Produit introuvable.']);
        }
        if (! empty($item['external_url'] ?? null)) {
            return redirect($item['external_url']);
        }

        $priceEuros = round((float) ($item['price'] ?? 0), 2);
        $priceCents = (int) round($priceEuros * 100);
        if ($priceCents <= 0) {
            return back()->withErrors(['slug' => 'Ce produit est gratuit.']);
        }

        if (! $this->marketplaceCheckout->isCheckoutAvailable()) {
            return back()->withErrors(['stripe' => 'Le paiement marketplace n\'est pas configuré. Contactez GdevStudio.']);
        }

        // IMPORTANT: garder le placeholder Stripe brut {CHECKOUT_SESSION_ID}
        // (route(..., [...]) l'encode en %7B...%7D et Stripe ne le remplace pas).
        $successUrl = route('admin.marketplace.success')
            .'?type='.urlencode($request->type)
            .'&slug='.urlencode($request->slug)
            .'&session_id={CHECKOUT_SESSION_ID}';
        $cancelUrl = $request->type === 'theme'
            ? route('admin.marketplace.themes')
            : route('admin.marketplace.plugins');

        $result = $this->marketplaceCheckout->createCheckoutSession(
            $request->type,
            $request->slug,
            $item['name'] ?? $request->slug,
            $priceCents,
            $successUrl,
            $cancelUrl
        );

        if (! empty($result['error'])) {
            return back()->withErrors(['stripe' => $result['error']]);
        }

        if (empty($result['url'])) {
            return back()->withErrors(['stripe' => 'Impossible de créer la session de paiement.']);
        }

        return redirect($result['url']);
    }

    /**
     * Page de succès après paiement Stripe (redirection depuis Checkout).
     * Stripe ne redirige ici qu'après paiement réussi → on crée l'achat immédiatement.
     */
    public function success(Request $request)
    {
        $sessionId = $request->query('session_id');
        $type = $request->query('type');
        $slug = $request->query('slug');

        if (! $sessionId || ! $type || ! $slug) {
            return redirect()->route('admin.marketplace.index')->with('error', 'Paramètres invalides.');
        }

        $normalizedSessionId = ($sessionId === '{CHECKOUT_SESSION_ID}' || $sessionId === '%7BCHECKOUT_SESSION_ID%7D')
            ? null
            : $sessionId;

        $sessionExists = $normalizedSessionId
            ? MarketplacePurchase::where('stripe_checkout_session_id', $normalizedSessionId)->exists()
            : false;
        if ($sessionExists) {
            $existing = MarketplacePurchase::where('stripe_checkout_session_id', $normalizedSessionId)->first();
            $type = $existing->item_type;
            $slug = $existing->item_slug;
            // Mise à jour de la clé si le serveur de licence est configuré et qu'on a encore STRIPE-XXX
            if (str_starts_with($existing->license_key, 'STRIPE-')) {
                $licenseData = $this->marketplaceService->getLicenseFromSession($normalizedSessionId, $type, $slug);
                if ($licenseData && ! empty($licenseData['license_key'])) {
                    $existing->update(['license_key' => $licenseData['license_key']]);
                }
            }
        } else {
            if ($normalizedSessionId && $this->marketplaceStripe->isConfigured()) {
                try {
                    $session = $this->marketplaceStripe->retrieveCheckoutSession($normalizedSessionId);
                    if ($session && ($session->metadata['marketplace'] ?? '') === '1') {
                        $type = $session->metadata['item_type'] ?? $type;
                        $slug = $session->metadata['item_slug'] ?? $slug;
                        $paymentStatus = $session->payment_status ?? $session->status ?? null;
                        if ($paymentStatus !== 'paid' && $paymentStatus !== 'complete') {
                            return redirect()->route('admin.marketplace.index')->with('error', 'Paiement non confirmé.');
                        }
                    }
                } catch (\Throwable $e) {
                    // Session invalide : suite via serveur de licence / paramètres URL
                }
            }

            $existing = MarketplacePurchase::where('item_type', $type)->where('item_slug', $slug)->first();
            $licenseKey = 'STRIPE-'.strtoupper(bin2hex(random_bytes(6)));
            $licenseData = $this->marketplaceService->getLicenseFromSession($normalizedSessionId, $type, $slug);
            if ($licenseData && ! empty($licenseData['license_key'])) {
                $licenseKey = $licenseData['license_key'];
            }

            if ($existing) {
                $existing->update([
                    'license_key' => $licenseKey,
                    'stripe_checkout_session_id' => $normalizedSessionId,
                    'is_active' => true,
                    'admin_enabled' => true,
                    'purchased_at' => now(),
                ]);
            } else {
                try {
                    DB::transaction(function () use ($normalizedSessionId, $type, $slug, $licenseKey) {
                        MarketplacePurchase::create([
                            'item_type' => $type,
                            'item_slug' => $slug,
                            'license_key' => $licenseKey,
                            'stripe_checkout_session_id' => $normalizedSessionId,
                            'is_active' => true,
                            'admin_enabled' => true,
                            'purchased_at' => now(),
                        ]);
                    });
                } catch (\Throwable $e) {
                    Log::error('Marketplace purchase create failed', [
                        'session_id' => $sessionId,
                        'type' => $type,
                        'slug' => $slug,
                        'error' => $e->getMessage(),
                    ]);
                    if ($normalizedSessionId && (str_contains($e->getMessage(), 'Duplicate') || str_contains($e->getMessage(), 'unique'))) {
                        $existing = MarketplacePurchase::where('stripe_checkout_session_id', $normalizedSessionId)->first();
                        if ($existing) {
                            $type = $existing->item_type;
                            $slug = $existing->item_slug;
                        }
                    } else {
                        return redirect()->route('admin.marketplace.plugins')
                            ->with('error', 'Erreur lors de l\'enregistrement. Rafraîchissez la page ou contactez le support.');
                    }
                }
            }
        }

        $message = $type === 'theme'
            ? 'Thème acheté avec succès ! Allez dans Apparence pour l\'activer.'
            : 'Plugin acheté avec succès ! Il est maintenant disponible.';

        $redirect = $type === 'theme'
            ? route('admin.marketplace.themes')
            : route('admin.marketplace.plugins');

        return redirect($redirect)->with('success', $message);
    }

    /**
     * Active ou désactive un achat (thème ou plugin).
     */
    public function activate(Request $request)
    {
        $request->validate([
            'type' => 'required|in:theme,plugin',
            'slug' => 'required|string',
            'active' => 'required|boolean',
        ]);

        $purchase = MarketplacePurchase::where('item_type', $request->type)
            ->where('item_slug', $request->slug)
            ->first();

        if (! $purchase) {
            return back()->withErrors(['slug' => 'Achat introuvable. Achetez d\'abord le produit.']);
        }

        $licenseKey = (string) ($purchase->license_key ?? '');
        $purchase->update(['admin_enabled' => (bool) $request->active]);
        if ($licenseKey !== '') {
            Cache::forget('license_valid_'.$licenseKey.'_'.$request->slug);
        }

        $action = $request->active ? 'activé' : 'désactivé';

        return back()->with('success', 'Produit '.$action.'.');
    }

    /**
     * URL absolue pour vignette marketplace (http(s) ou chemin public type themes/.../file.png).
     */
    protected function resolveThemeScreenshotUrl(?string $screenshot, string $fallbackLabel = 'Theme'): string
    {
        if ($screenshot === null || trim($screenshot) === '') {
            return 'https://placehold.co/600x400/e2e8f0/64748b?text='.urlencode($fallbackLabel);
        }
        if (preg_match('#^https?://#i', $screenshot)) {
            return $screenshot;
        }

        return asset(ltrim($screenshot, '/'));
    }

    /**
     * Évite les doublons de slug (ex. Saïjana installée dans content/themes + entrée catalogue).
     *
     * @param  array<int, array<string, mixed>>  $freeThemes
     * @param  array<int, array<string, mixed>>  $catalogThemes
     * @return array<int, array<string, mixed>>
     */
    protected function mergeThemeCatalogUniqueBySlug(array $freeThemes, array $catalogThemes): array
    {
        $seen = [];
        $out = [];
        foreach (array_merge($freeThemes, $catalogThemes) as $row) {
            $slug = $row['slug'] ?? '';
            if ($slug !== '') {
                if (isset($seen[$slug])) {
                    continue;
                }
                $seen[$slug] = true;
            }
            $out[] = $row;
        }

        return $out;
    }
}
