<?php

namespace App\Http\Controllers;

use App\Enums\EventStatus;
use App\Models\Category;
use App\Models\Event;
use App\Models\Venue;
use Illuminate\Http\Request;
use Illuminate\View\View;

/**
 * Rutas públicas de marketing y descubrimiento de eventos.
 *
 * - `index`: home con carrusel y tarjetas de eventos próximos.
 * - `events`: listado filtrable / paginado (AJAX devuelve partial de rejilla).
 * - `eventShow`: ficha del evento publicado y punto de entrada al checkout.
 *
 * Los métodos estáticos (`carouselSlides`, `experienceSteps`, etc.) centralizan contenido reutilizable en vistas auth/landing.
 */
class LandingController extends Controller
{
    private const DEFAULT_EVENT_CARD_IMAGE = 'https://images.unsplash.com/photo-1476480862121-37bf2288b672?w=600&q=80';

    /**
     * @return array<int, array<string, mixed>>
     */
    public static function featuredEvents(): array
    {
        return [
            [
                'title' => '5K Comedor de la Kennedy',
                'href' => 'https://www.regiticket.com/event/comedor-de-la-kennedy-5k/',
                'image' => 'https://www.regiticket.com/wp-content/uploads/Oficial-Kennedy.jpeg',
                'month' => 'Jun',
                'day' => '7',
                'datetime_attr' => '2026-06-07',
                'time_label' => '6:00 AM – 10:00 AM',
                'featured' => true,
                'price' => '$25.00 – $40.00',
                'stock' => '750 entradas restantes',
            ],
            [
                'title' => '5K El Faro',
                'href' => 'https://www.regiticket.com/event/5k-el-faro/',
                'image' => 'https://www.regiticket.com/wp-content/uploads/El-Faro-Flyer-portada.jpg',
                'month' => 'Jun',
                'day' => '20',
                'datetime_attr' => '2026-06-20',
                'time_label' => '3:00 PM – 6:00 PM',
                'featured' => false,
                'price' => '$25.00',
                'stock' => '285 entradas restantes',
            ],
            [
                'title' => 'CSILO 5K / 21K',
                'href' => 'https://www.regiticket.com/event/csilo-5k-21k-2/',
                'image' => 'https://www.regiticket.com/wp-content/uploads/CSILO-Flyer-Oficiale-1080x1080.jpg.jpeg',
                'month' => 'Ago',
                'day' => '9',
                'datetime_attr' => '2026-08-09',
                'time_label' => '5:30 AM – 10:00 AM',
                'featured' => true,
                'price' => '$15.00 – $45.00',
                'stock' => '3.041 entradas restantes',
            ],
            [
                'title' => 'Ponce Vip Weekend Pass 5K + 21K',
                'href' => 'https://www.regiticket.com/event/ponce-vip-weekend-pass-5k-21k/',
                'image' => 'https://www.regiticket.com/wp-content/uploads/WhatsApp-Image-2026-02-24-at-4.27.12-PM.jpeg',
                'month' => 'Nov',
                'day' => '14',
                'datetime_attr' => '2026-11-14',
                'time_label' => 'noviembre 14 | 5:00 AM – noviembre 15 | 10:00 AM',
                'featured' => true,
                'price' => '$65.00 – $75.00',
                'stock' => '190 entradas restantes',
            ],
            [
                'title' => 'Ponce 5K',
                'href' => 'https://www.regiticket.com/event/ponce-5k/',
                'image' => 'https://www.regiticket.com/wp-content/uploads/Ponce-5k-Minimalista-copia.jpg',
                'month' => 'Nov',
                'day' => '14',
                'datetime_attr' => '2026-11-14',
                'time_label' => '6:00 AM – 11:00 AM',
                'featured' => true,
                'price' => '$20.00 – $30.00',
                'stock' => '419 entradas restantes',
            ],
            [
                'title' => 'Ponce Half 2.0 (21K)',
                'href' => 'https://www.regiticket.com/event/ponce-half-2-0/',
                'image' => 'https://www.regiticket.com/wp-content/uploads/Ponce-Half-20-Minimalista-copia.jpg',
                'month' => 'Nov',
                'day' => '15',
                'datetime_attr' => '2026-11-15',
                'time_label' => '5:30 AM – 11:00 AM',
                'featured' => true,
                'price' => '$30.00 – $45.00',
                'stock' => '376 entradas restantes',
            ],
        ];
    }

    /**
     * Slides del hero (misma primera imagen que fondo en login / registro / cuenta).
     *
     * @return array<int, array{title: string, subtitle: string, image: string}>
     */
    public static function carouselSlides(): array
    {
        return [
            [
                'title' => 'Eventos que mueven tu mundo',
                'subtitle' => 'Carreras, experiencias y comunidad. Entradas seguras con Regiticket.',
                'image' => 'https://images.unsplash.com/photo-1452626038306-9aae5e071dd3?w=1920&q=80',
            ],
            [
                'title' => 'Tu próxima meta empieza aquí',
                'subtitle' => '5K, 21K y experiencias únicas. Reserva en segundos.',
                'image' => 'https://images.unsplash.com/photo-1476480862121-37bf2288b672?w=1920&q=80',
            ],
            [
                'title' => 'Plataforma profesional de ticketing',
                'subtitle' => 'Organizadores y corredores conectados en un solo lugar.',
                'image' => 'https://images.unsplash.com/photo-1552674605-db6ffd4facb5?w=1920&q=80',
            ],
        ];
    }

    /** Primera slide del carrusel (fondo auth / cuenta). */
    public static function authHeroBackdropUrl(): string
    {
        $slides = self::carouselSlides();

        return $slides[0]['image'] ?? '';
    }

    /**
     * Pasos de experiencia (imágenes branding regiticket.com, tonos rojos).
     *
     * @return array<int, array{title: string, image: string}>
     */
    public static function experienceSteps(): array
    {
        return [
            ['title' => 'Busca tu evento favorito', 'image' => 'https://www.regiticket.com/wp-content/uploads/2023/06/serv-1a-1.webp'],
            ['title' => 'Compra tu entrada o Registro', 'image' => 'https://www.regiticket.com/wp-content/uploads/2023/06/serv-2a-1.webp'],
            ['title' => 'Recibe un email con tu código QR', 'image' => 'https://www.regiticket.com/wp-content/uploads/2023/06/serv-3a-1.webp'],
            ['title' => 'Asiste al evento y presenta tu QR', 'image' => 'https://www.regiticket.com/wp-content/uploads/2023/06/serv-4a-1.webp'],
            ['title' => 'Disfruta tu evento.', 'image' => 'https://www.regiticket.com/wp-content/uploads/2023/06/serv-5a-1.webp'],
        ];
    }

    /**
     * Home pública: hasta 6 eventos próximos presentados como tarjetas.
     */
    public function index(): View
    {
        $listingCols = Event::publicListingSchema();

        $eventsQuery = Event::query()
            ->publicListing()
            ->with([
                'venue',
                'category',
                'ticketTypes' => static fn ($q) => $q->where('is_active', true),
            ])
            ->where('start_date', '>=', now()->startOfDay());

        if ($listingCols['is_featured']) {
            $eventsQuery->orderByDesc('is_featured');
        }

        $realEvents = $eventsQuery->orderBy('start_date')
            ->limit(6)
            ->get();

        $presentedEvents = $realEvents->map(fn (Event $event) => $this->presentEventCard($event))->all();

        return view('landing.index', [
            'events' => $presentedEvents,
            'carouselSlides' => self::carouselSlides(),
            'experienceSteps' => self::experienceSteps(),
        ]);
    }

    /**
     * Directorio de eventos con filtros (texto, categoría, sede, fechas, destacados, incluir pasados).
     */
    public function events(Request $request): View
    {
        $filters = $request->validate([
            'q' => ['nullable', 'string', 'max:120'],
            'category_id' => ['nullable', 'integer', 'exists:categories,id'],
            'venue_id' => ['nullable', 'integer', 'exists:venues,id'],
            'date_from' => ['nullable', 'date'],
            'date_to' => ['nullable', 'date'],
            'destacados' => ['nullable', 'boolean'],
            'pasados' => ['nullable', 'boolean'],
        ]);

        if (! empty($filters['date_from']) && ! empty($filters['date_to'])) {
            $request->validate([
                'date_to' => ['after_or_equal:date_from'],
            ]);
        }

        $listingCols = Event::publicListingSchema();

        $query = Event::query()
            ->publicListing()
            ->with([
                'venue',
                'category',
                'ticketTypes' => static fn ($q) => $q->where('is_active', true),
            ])
            ->when(! $request->boolean('pasados'), static fn ($q) => $q->where('start_date', '>=', now()->startOfDay()))
            ->when($filters['q'] ?? null, static function ($q, string $term): void {
                $like = '%'.addcslashes($term, '%_\\').'%';
                $q->where('title', 'like', $like);
            })
            ->when($filters['category_id'] ?? null, static fn ($q, int $id) => $q->where('category_id', $id))
            ->when($filters['venue_id'] ?? null, static fn ($q, int $id) => $q->where('venue_id', $id))
            ->when($filters['date_from'] ?? null, static fn ($q, string $d) => $q->whereDate('start_date', '>=', $d))
            ->when($filters['date_to'] ?? null, static fn ($q, string $d) => $q->whereDate('start_date', '<=', $d))
            ->when(
                $request->boolean('destacados') && $listingCols['is_featured'],
                static fn ($q) => $q->where('is_featured', true)
            )
            ->orderBy('start_date');

        $coverUrl = $this->publicEventsCoverImageUrl(clone $query, $listingCols);

        $events = $query->paginate(12)->withQueryString();

        $cardRows = $events->getCollection()->map(fn (Event $event) => $this->presentEventCard($event))->all();

        $events->setCollection(collect($cardRows));

        $filterCategories = Category::query()
            ->whereHas('events', static fn ($q) => $q->publicListing())
            ->orderBy('name')
            ->get(['id', 'name']);

        $filterVenues = Venue::query()
            ->whereHas('events', static fn ($q) => $q->publicListing())
            ->orderBy('name')
            ->get(['id', 'name']);

        if ($request->ajax()) {
            return view('landing.partials.events-grid', [
                'events' => $events,
            ]);
        }

        return view('landing.events', [
            'coverImageUrl' => $coverUrl,
            'events' => $events,
            'filterCategories' => $filterCategories,
            'filterVenues' => $filterVenues,
            'filters' => $filters,
        ]);
    }

    /**
     * Detalle de un evento publicado: datos para landing y configuración del checkout (Alpine).
     */
    public function eventShow(Event $event): View
    {
        abort_unless($event->status === EventStatus::Published, 404);

        $event->load(['venue', 'category', 'ticketTypes' => static fn ($q) => $q->where('is_active', true)->orderBy('name')]);

        return view('landing.event-show', [
            'event' => $event,
            'card' => $this->presentEventCard($event),
        ]);
    }

    /**
     * Imagen de portada: prioriza evento destacado con portada; si no, cualquier listado con imagen.
     *
     * @param  array{hide_from_listings: bool, is_featured: bool, featured_image_path: bool}  $listingCols
     */
    private function publicEventsCoverImageUrl($baseQuery, array $listingCols): string
    {
        if (! $listingCols['featured_image_path']) {
            return self::carouselSlides()[0]['image'] ?? self::DEFAULT_EVENT_CARD_IMAGE;
        }

        $q = (clone $baseQuery)
            ->whereNotNull('featured_image_path')
            ->where('featured_image_path', '!=', '');

        if ($listingCols['is_featured']) {
            $q->orderByDesc('is_featured');
        }

        $pick = $q->orderBy('start_date')->first(['featured_image_path']);

        if ($pick?->featured_image_path) {
            return asset($pick->featured_image_path);
        }

        return self::carouselSlides()[0]['image'] ?? self::DEFAULT_EVENT_CARD_IMAGE;
    }

    /**
     * @return array{title: string, href: string, image: string, month: string, day: string, datetime_attr: string, time_label: string, featured: bool, price: string, stock: string}
     */
    private function presentEventCard(Event $event): array
    {
        $tz = $event->timezone ?: config('app.timezone');
        $start = $event->start_date?->copy()->timezone($tz);
        $end = $event->end_date?->copy()->timezone($tz);

        $locale = app()->getLocale() === 'es' ? 'es' : 'en';
        if ($start) {
            $start->locale($locale);
        }
        if ($end) {
            $end->locale($locale);
        }

        $path = Event::publicListingSchema()['featured_image_path']
            ? $event->featured_image_path
            : null;
        $image = ($path && $path !== '')
            ? asset($path)
            : self::DEFAULT_EVENT_CARD_IMAGE;

        $timeLabel = match (true) {
            $start && $end => $start->isoFormat('D MMM, HH:mm').' – '.$end->isoFormat('D MMM, HH:mm'),
            $start !== null => $start->isoFormat('D MMM YYYY, HH:mm'),
            default => '—',
        };

        $types = $event->relationLoaded('ticketTypes')
            ? $event->ticketTypes
            : $event->ticketTypes()->where('is_active', true)->get();

        $amounts = $types->map(static function ($t): float {
            $p = $t->sale_price ?? $t->price;

            return (float) $p;
        })->filter(static fn (float $p) => $p > 0)->values();

        $priceStr = '';
        if ($amounts->isNotEmpty()) {
            $min = $amounts->min();
            $max = $amounts->max();
            $fmt = static fn (float $v) => '$'.number_format($v, 2);
            $priceStr = $min === $max ? $fmt($min) : $fmt($min).' – '.$fmt($max);
        }

        $month = $start ? mb_convert_case($start->isoFormat('MMM'), MB_CASE_TITLE, 'UTF-8') : '—';
        $day = $start ? $start->format('j') : '—';
        $datetimeAttr = $start ? $start->toDateString() : '';

        return [
            'title' => $event->title,
            'href' => route('landing.event.show', ['event' => $event->slug]),
            'image' => $image,
            'month' => $month,
            'day' => $day,
            'datetime_attr' => $datetimeAttr,
            'time_label' => $timeLabel,
            'featured' => Event::publicListingSchema()['is_featured'] && (bool) $event->is_featured,
            'price' => $priceStr,
            'stock' => __('Disponibilidad según tipo de entrada'),
        ];
    }
}
