<?php

namespace App\Livewire;

use App\Models\Park;
use App\Enums\ParkStatus;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Database\Eloquent\Builder;

class ParkListComponent extends Component
{
    use WithPagination;

    public string $search = '';
    public string $status = '';
    public string $sort = 'name';
    public string $direction = 'asc';
    public ?string $operator = null;
    public string $viewMode = 'grid';

    /** @var array<string, string> */
    public array $sortOptions = [
        'name' => 'Name',
        'opening_date' => 'Opening Date',
        'ride_count' => 'Ride Count',
        'coaster_count' => 'Coaster Count',
        'size_acres' => 'Size',
    ];

    protected $queryString = [
        'search' => ['except' => ''],
        'status' => ['except' => ''],
        'sort' => ['except' => 'name'],
        'direction' => ['except' => 'asc'],
        'operator' => ['except' => ''],
        'viewMode' => ['except' => 'grid'],
    ];

    public function mount(): void
    {
        $this->resetPage('parks-page');
    }

    public function updatedSearch(): void
    {
        $this->resetPage('parks-page');
    }

    public function updatedStatus(): void
    {
        $this->resetPage('parks-page');
    }

    public function updatedOperator(): void
    {
        $this->resetPage('parks-page');
    }

    public function updatedViewMode(): void
    {
        // No need to reset page when changing view mode
    }

    public function sortBy(string $field): void
    {
        if ($this->sort === $field) {
            $this->direction = $this->direction === 'asc' ? 'desc' : 'asc';
        } else {
            $this->sort = $field;
            $this->direction = 'asc';
        }
    }

    public function getStatusOptions(): array
    {
        return collect(ParkStatus::cases())
            ->mapWithKeys(fn (ParkStatus $status) => [$status->value => $status->label()])
            ->prepend('All Statuses', '')
            ->toArray();
    }

    public function getOperatorOptions(): array
    {
        return \App\Models\Operator::orderBy('name')
            ->pluck('name', 'id')
            ->prepend('All Operators', '')
            ->toArray();
    }

    public function render()
    {
        $query = Park::query()
            ->with(['operator', 'location'])
            ->when($this->search, function (Builder $query) {
                $query->where(function (Builder $q) {
                    $q->where('name', 'like', '%' . $this->search . '%')
                      ->orWhere('description', 'like', '%' . $this->search . '%');
                });
            })
            ->when($this->status, function (Builder $query) {
                $query->where('status', $this->status);
            })
            ->when($this->operator, function (Builder $query) {
                $query->where('operator_id', $this->operator);
            })
            ->when($this->sort === 'name', function (Builder $query) {
                $query->orderBy('name', $this->direction);
            })
            ->when($this->sort === 'opening_date', function (Builder $query) {
                $query->orderBy('opening_date', $this->direction)
                    ->orderBy('name', 'asc');
            })
            ->when($this->sort === 'ride_count', function (Builder $query) {
                $query->orderBy('ride_count', $this->direction)
                    ->orderBy('name', 'asc');
            })
            ->when($this->sort === 'coaster_count', function (Builder $query) {
                $query->orderBy('coaster_count', $this->direction)
                    ->orderBy('name', 'asc');
            })
            ->when($this->sort === 'size_acres', function (Builder $query) {
                $query->orderBy('size_acres', $this->direction)
                    ->orderBy('name', 'asc');
            });

        return view('livewire.park-list-component', [
            'parks' => $query->paginate(12, pageName: 'parks-page'),
            'statusOptions' => $this->getStatusOptions(),
            'operatorOptions' => $this->getOperatorOptions(),
            'viewMode' => $this->viewMode,
        ]);
    }
}