<?php

namespace App\Livewire;

use App\Models\Ride;
use App\Models\Park;
use App\Models\ParkArea;
use App\Models\RideModel;
use App\Models\Designer;
use App\Models\Manufacturer;
use App\Enums\RideCategory;
use App\Enums\RideStatus;
use Livewire\Component;
use Illuminate\Validation\Rules\Enum;

class RideFormComponent extends Component
{
    public ?Ride $ride = null;

    /** @var array<string, mixed> */
    public array $state = [];

    /** @var array<string, mixed>|null */
    public ?array $coasterStats = null;

    /** @var int|null */
    public ?int $parkId = null;

    protected function rules(): array
    {
        return [
            'state.name' => ['required', 'string', 'max:255'],
            'state.park_id' => ['required', 'exists:parks,id'],
            'state.park_area_id' => ['nullable', 'exists:park_areas,id'],
            'state.manufacturer_id' => ['nullable', 'exists:manufacturers,id'],
            'state.designer_id' => ['nullable', 'exists:designers,id'],
            'state.ride_model_id' => ['nullable', 'exists:ride_models,id'],
            'state.category' => ['required', new Enum(RideCategory::class)],
            'state.status' => ['required', new Enum(RideStatus::class)],
            'state.post_closing_status' => ['nullable', new Enum(RideStatus::class)],
            'state.description' => ['nullable', 'string'],
            'state.opening_date' => ['nullable', 'date'],
            'state.closing_date' => ['nullable', 'date'],
            'state.status_since' => ['nullable', 'date'],
            'state.min_height_in' => ['nullable', 'integer', 'min:0'],
            'state.max_height_in' => ['nullable', 'integer', 'min:0'],
            'state.capacity_per_hour' => ['nullable', 'integer', 'min:0'],
            'state.ride_duration_seconds' => ['nullable', 'integer', 'min:0'],
        ];
    }

    public function mount(?Ride $ride = null): void
    {
        $this->ride = $ride;
        
        if ($ride) {
            $this->state = $ride->only([
                'name', 'park_id', 'park_area_id', 'manufacturer_id',
                'designer_id', 'ride_model_id', 'category', 'status',
                'post_closing_status', 'description', 'opening_date',
                'closing_date', 'status_since', 'min_height_in',
                'max_height_in', 'capacity_per_hour', 'ride_duration_seconds',
            ]);

            $this->parkId = $ride->park_id;
            
            if ($ride->coasterStats) {
                $this->coasterStats = $ride->coasterStats->toArray();
            }
        }
    }

    public function updated(string $field): void
    {
        $this->validateOnly($field);

        if ($field === 'state.category') {
            $this->coasterStats = $this->state['category'] === RideCategory::ROLLER_COASTER->value
                ? ($this->coasterStats ?? [])
                : null;
        }
    }

    public function save(): void
    {
        $this->validate();

        if (!$this->ride) {
            $this->ride = new Ride();
        }

        $this->ride->fill($this->state)->save();

        // Handle coaster stats if applicable
        if ($this->state['category'] === RideCategory::ROLLER_COASTER->value && $this->coasterStats) {
            $this->ride->coasterStats()->updateOrCreate(
                ['ride_id' => $this->ride->id],
                $this->coasterStats
            );
        } elseif ($this->ride->coasterStats) {
            $this->ride->coasterStats->delete();
        }

        session()->flash('message', 'Ride saved successfully.');
        
        $this->redirect(route('rides.show', $this->ride));
    }

    public function getParksProperty()
    {
        return Park::orderBy('name')->get();
    }

    public function getParkAreasProperty()
    {
        return $this->parkId
            ? ParkArea::where('park_id', $this->parkId)->orderBy('name')->get()
            : collect();
    }

    public function getManufacturersProperty()
    {
        return Manufacturer::orderBy('name')->get();
    }

    public function getDesignersProperty()
    {
        return Designer::orderBy('name')->get();
    }

    public function getRideModelsProperty()
    {
        return RideModel::orderBy('name')->get();
    }

    public function render()
    {
        return view('livewire.ride-form');
    }
}