<?php

namespace App\Livewire;

use App\Models\Park;
use App\Models\ParkArea;
use Livewire\Component;
use Illuminate\Support\Collection;

class ParkAreaReorderComponent extends Component
{
    public Park $park;
    public ?int $parentId = null;
    public array $areas = [];

    public function mount(Park $park, ?int $parentId = null): void
    {
        $this->park = $park;
        $this->parentId = $parentId;
        $this->loadAreas();
    }

    /**
     * Load areas for the current context (either top-level or within a parent).
     */
    protected function loadAreas(): void
    {
        $query = $this->park->areas()
            ->where('parent_id', $this->parentId)
            ->orderBy('position')
            ->select(['id', 'name', 'position', 'closing_date']);

        $this->areas = $query->get()
            ->map(fn ($area) => [
                'id' => $area->id,
                'name' => $area->name,
                'position' => $area->position,
                'is_closed' => !is_null($area->closing_date),
                'has_children' => $area->hasChildren(),
            ])
            ->toArray();
    }

    /**
     * Handle reordering of areas.
     */
    public function reorder(array $orderedIds): void
    {
        // Validate that all IDs belong to this park and parent context
        $validIds = $this->park->areas()
            ->where('parent_id', $this->parentId)
            ->pluck('id')
            ->toArray();

        $orderedIds = array_values(array_intersect($orderedIds, $validIds));

        // Update positions
        foreach ($orderedIds as $position => $id) {
            ParkArea::where('id', $id)->update(['position' => $position]);
        }

        $this->loadAreas();
        $this->dispatch('areas-reordered');
    }

    /**
     * Move an area to a new parent.
     */
    public function moveToParent(int $areaId, ?int $newParentId): void
    {
        $area = $this->park->areas()->findOrFail($areaId);
        
        // Prevent circular references
        if ($newParentId === $area->id) {
            return;
        }

        // If moving to a new parent, validate it exists and belongs to this park
        if ($newParentId) {
            $newParent = $this->park->areas()->findOrFail($newParentId);
            
            // Prevent moving to own descendant
            $ancestorIds = Collection::make();
            $current = $newParent;
            while ($current) {
                if ($ancestorIds->contains($current->id)) {
                    return; // Circular reference detected
                }
                $ancestorIds->push($current->id);
                if ($current->id === $area->id) {
                    return; // Would create circular reference
                }
                $current = $current->parent;
            }
        }

        // Get the next position in the new parent context
        $maxPosition = $this->park->areas()
            ->where('parent_id', $newParentId)
            ->max('position');

        $area->update([
            'parent_id' => $newParentId,
            'position' => ($maxPosition ?? -1) + 1,
        ]);

        // Reorder the old parent's remaining areas to close gaps
        $this->park->areas()
            ->where('parent_id', $this->parentId)
            ->where('position', '>', $area->position)
            ->decrement('position');

        $this->loadAreas();
        $this->dispatch('area-moved');
    }

    public function render()
    {
        return view('livewire.park-area-reorder-component', [
            'parentArea' => $this->parentId 
                ? $this->park->areas()->find($this->parentId) 
                : null,
        ]);
    }
}