<?php

namespace App\Livewire;

use App\Models\Ride;
use App\Models\Park;
use App\Models\Operator;
use App\Enums\RideCategory;
use App\Enums\RideStatus;
use Livewire\Component;
use Livewire\Attributes\Url;
use Illuminate\Support\Facades\Cache;

class RidesFilters extends Component
{
    // URL-bound filter properties for deep linking
    #[Url(as: 'category')]
    public ?string $selectedCategory = null;

    #[Url(as: 'status')]
    public ?string $selectedStatus = null;

    #[Url(as: 'manufacturer')]
    public ?int $selectedManufacturer = null;

    #[Url(as: 'park')]
    public ?int $selectedPark = null;

    #[Url(as: 'year_min')]
    public ?int $minOpeningYear = null;

    #[Url(as: 'year_max')]
    public ?int $maxOpeningYear = null;

    #[Url(as: 'height_min')]
    public ?int $minHeight = null;

    #[Url(as: 'height_max')]
    public ?int $maxHeight = null;

    // Filter options (cached)
    public array $categories = [];
    public array $statuses = [];
    public array $manufacturers = [];
    public array $parks = [];
    public array $yearRange = [];
    public array $heightRange = [];

    // UI state
    public bool $showAdvancedFilters = false;
    public int $activeFiltersCount = 0;

    /**
     * Component initialization
     */
    public function mount(): void
    {
        $this->loadFilterOptions();
        $this->calculateActiveFiltersCount();
    }

    /**
     * Load filter options with caching
     */
    protected function loadFilterOptions(): void
    {
        // Categories from enum
        $this->categories = $this->remember(
            'categories',
            fn() => collect(RideCategory::cases())
                ->map(fn($case) => [
                    'value' => $case->value,
                    'label' => $case->name,
                    'count' => Ride::where('category', $case->value)->count()
                ])
                ->filter(fn($item) => $item['count'] > 0)
                ->values()
                ->toArray(),
            3600 // 1-hour cache
        );

        // Statuses from enum
        $this->statuses = $this->remember(
            'statuses',
            fn() => collect(RideStatus::cases())
                ->map(fn($case) => [
                    'value' => $case->value,
                    'label' => $case->name,
                    'count' => Ride::where('status', $case->value)->count()
                ])
                ->filter(fn($item) => $item['count'] > 0)
                ->values()
                ->toArray(),
            3600
        );

        // Manufacturers (Operators that have manufactured rides)
        $this->manufacturers = $this->remember(
            'manufacturers',
            fn() => Operator::select('id', 'name')
                ->whereHas('manufacturedRides')
                ->withCount('manufacturedRides')
                ->orderBy('name')
                ->get()
                ->map(fn($operator) => [
                    'value' => $operator->id,
                    'label' => $operator->name,
                    'count' => $operator->manufactured_rides_count
                ])
                ->toArray(),
            3600
        );

        // Parks that have rides
        $this->parks = $this->remember(
            'parks',
            fn() => Park::select('id', 'name')
                ->whereHas('rides')
                ->withCount('rides')
                ->orderBy('name')
                ->get()
                ->map(fn($park) => [
                    'value' => $park->id,
                    'label' => $park->name,
                    'count' => $park->rides_count
                ])
                ->toArray(),
            3600
        );

        // Year range
        $this->yearRange = $this->remember(
            'year_range',
            function() {
                $years = Ride::whereNotNull('opening_year')
                    ->selectRaw('MIN(opening_year) as min_year, MAX(opening_year) as max_year')
                    ->first();
                
                return [
                    'min' => $years->min_year ?? 1900,
                    'max' => $years->max_year ?? date('Y')
                ];
            },
            3600
        );

        // Height range
        $this->heightRange = $this->remember(
            'height_range',
            function() {
                $heights = Ride::whereNotNull('height_requirement')
                    ->selectRaw('MIN(height_requirement) as min_height, MAX(height_requirement) as max_height')
                    ->first();
                
                return [
                    'min' => $heights->min_height ?? 0,
                    'max' => $heights->max_height ?? 200
                ];
            },
            3600
        );
    }

    /**
     * Calculate number of active filters
     */
    protected function calculateActiveFiltersCount(): void
    {
        $this->activeFiltersCount = collect([
            $this->selectedCategory,
            $this->selectedStatus,
            $this->selectedManufacturer,
            $this->selectedPark,
            $this->minOpeningYear,
            $this->maxOpeningYear,
            $this->minHeight,
            $this->maxHeight
        ])->filter()->count();
    }

    /**
     * Apply category filter
     */
    public function setCategory(?string $category): void
    {
        $this->selectedCategory = $category === $this->selectedCategory ? null : $category;
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Apply status filter
     */
    public function setStatus(?string $status): void
    {
        $this->selectedStatus = $status === $this->selectedStatus ? null : $status;
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Apply manufacturer filter
     */
    public function setManufacturer(?int $manufacturerId): void
    {
        $this->selectedManufacturer = $manufacturerId === $this->selectedManufacturer ? null : $manufacturerId;
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Apply park filter
     */
    public function setPark(?int $parkId): void
    {
        $this->selectedPark = $parkId === $this->selectedPark ? null : $parkId;
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Update year range filters
     */
    public function updateYearRange(): void
    {
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Update height range filters
     */
    public function updateHeightRange(): void
    {
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Toggle advanced filters visibility
     */
    public function toggleAdvancedFilters(): void
    {
        $this->showAdvancedFilters = !$this->showAdvancedFilters;
    }

    /**
     * Clear all filters
     */
    public function clearAllFilters(): void
    {
        $this->selectedCategory = null;
        $this->selectedStatus = null;
        $this->selectedManufacturer = null;
        $this->selectedPark = null;
        $this->minOpeningYear = null;
        $this->maxOpeningYear = null;
        $this->minHeight = null;
        $this->maxHeight = null;
        
        $this->calculateActiveFiltersCount();
        $this->dispatch('filters-updated', $this->getActiveFilters());
    }

    /**
     * Get active filters for parent component
     */
    public function getActiveFilters(): array
    {
        return array_filter([
            'category' => $this->selectedCategory,
            'status' => $this->selectedStatus,
            'manufacturer_id' => $this->selectedManufacturer,
            'park_id' => $this->selectedPark,
            'min_opening_year' => $this->minOpeningYear,
            'max_opening_year' => $this->maxOpeningYear,
            'min_height' => $this->minHeight,
            'max_height' => $this->maxHeight,
        ]);
    }

    /**
     * Get filter summary for display
     */
    public function getFilterSummary(): array
    {
        $summary = [];

        if ($this->selectedCategory) {
            $category = collect($this->categories)->firstWhere('value', $this->selectedCategory);
            $summary[] = 'Category: ' . ($category['label'] ?? $this->selectedCategory);
        }

        if ($this->selectedStatus) {
            $status = collect($this->statuses)->firstWhere('value', $this->selectedStatus);
            $summary[] = 'Status: ' . ($status['label'] ?? $this->selectedStatus);
        }

        if ($this->selectedManufacturer) {
            $manufacturer = collect($this->manufacturers)->firstWhere('value', $this->selectedManufacturer);
            $summary[] = 'Manufacturer: ' . ($manufacturer['label'] ?? 'Unknown');
        }

        if ($this->selectedPark) {
            $park = collect($this->parks)->firstWhere('value', $this->selectedPark);
            $summary[] = 'Park: ' . ($park['label'] ?? 'Unknown');
        }

        if ($this->minOpeningYear || $this->maxOpeningYear) {
            $yearText = 'Year: ';
            if ($this->minOpeningYear && $this->maxOpeningYear) {
                $yearText .= $this->minOpeningYear . '-' . $this->maxOpeningYear;
            } elseif ($this->minOpeningYear) {
                $yearText .= 'After ' . $this->minOpeningYear;
            } else {
                $yearText .= 'Before ' . $this->maxOpeningYear;
            }
            $summary[] = $yearText;
        }

        if ($this->minHeight || $this->maxHeight) {
            $heightText = 'Height: ';
            if ($this->minHeight && $this->maxHeight) {
                $heightText .= $this->minHeight . '-' . $this->maxHeight . 'cm';
            } elseif ($this->minHeight) {
                $heightText .= 'Min ' . $this->minHeight . 'cm';
            } else {
                $heightText .= 'Max ' . $this->maxHeight . 'cm';
            }
            $summary[] = $heightText;
        }

        return $summary;
    }

    /**
     * Render the component
     */
    public function render()
    {
        return view('livewire.rides-filters');
    }

    /**
     * Get cache key for this component
     */
    protected function getCacheKey(string $suffix = ''): string
    {
        return 'thrillwiki.' . class_basename(static::class) . '.' . $suffix;
    }

    /**
     * Remember data with caching
     */
    protected function remember(string $key, $callback, int $ttl = 3600)
    {
        return Cache::remember($this->getCacheKey($key), $ttl, $callback);
    }

    /**
     * Invalidate component cache
     */
    protected function invalidateCache(string $key = null): void
    {
        if ($key) {
            Cache::forget($this->getCacheKey($key));
        } else {
            // Clear all cache for this component
            Cache::flush();
        }
    }
}