<?php

namespace App\Livewire\Facilities;

use App\Domain\Facility\Models\Facility;
use App\Domain\Facility\Models\SpaceSegment;
use App\Domain\Facility\Services\SpaceLayoutService;
use App\Domain\Shared\Exceptions\DomainException;
use Livewire\Attributes\Layout;
use Livewire\Attributes\Locked;
use Livewire\Attributes\Title;
use Livewire\Component;

#[Layout('layouts.app')]
#[Title('إدارة تخطيط الملاعب')]
class SpaceLayoutManager extends Component
{
    /**
     * Resolved by route-model binding, which applies BranchScope — another
     * branch's facility 404s here rather than opening. Locked so the browser
     * cannot swap it for a different one on a later round-trip.
     */
    #[Locked]
    public Facility $facility;

    public array $layouts = [];

    // Form state
    public bool $showForm = false;

    /** Server-set from editLayout(); never bound in the view. */
    #[Locked]
    public ?int $editingLayoutId = null;
    public string $name = '';
    public string $name_ar = '';
    public string $layout_type = 'grid';
    public bool $is_recurring = true;
    public ?int $effective_day_of_week = 6;
    public ?string $effective_date = null;
    public string $start_time = '08:00';
    public string $end_time = '22:00';

    // Grid config
    public int $grid_rows = 2;
    public int $grid_columns = 3;

    // Lanes config
    public int $lane_count = 4;

    // Zones config
    public array $zone_definitions = [];

    public function mount(Facility $facility): void
    {
        $this->authorize('facilities.manage_layouts');
        $this->facility = $facility;
        $this->loadLayouts();
    }

    public function loadLayouts(): void
    {
        $this->layouts = $this->facility->layouts()
            ->with('segments')
            ->orderBy('is_recurring', 'desc')
            ->orderBy('effective_day_of_week')
            ->orderBy('start_time')
            ->get()
            ->toArray();
    }

    public function openCreateForm(): void
    {
        $this->resetForm();
        $this->showForm = true;
    }

    /**
     * Layouts are resolved through the facility's own relation, not by bare id.
     * save() writes facility_id back as $this->facility->id, so loading a
     * layout that belongs to another facility would re-parent it — and take its
     * segments with it — on the next save.
     */
    public function editLayout(int $id): void
    {
        $layout = $this->facility->layouts()->with('segments')->findOrFail($id);
        $this->editingLayoutId = $id;
        $this->name = $layout->name;
        $this->name_ar = $layout->name_ar;
        $this->layout_type = $layout->layout_type->value;
        $this->is_recurring = $layout->is_recurring;
        $this->effective_day_of_week = $layout->effective_day_of_week;
        $this->effective_date = $layout->effective_date?->format('Y-m-d');
        $this->start_time = $layout->start_time;
        $this->end_time = $layout->end_time;

        $config = $layout->layout_config;
        match ($this->layout_type) {
            'grid' => (function () use ($config) {
                $this->grid_rows = $config['rows'] ?? 2;
                $this->grid_columns = $config['columns'] ?? 3;
            })(),
            'lanes' => $this->lane_count = $config['lane_count'] ?? 4,
            'zones', 'custom' => $this->zone_definitions = $config['definitions'] ?? [],
            default => null,
        };

        $this->showForm = true;
    }

    public function save(SpaceLayoutService $service): void
    {
        $this->validate([
            'name' => 'required|string|max:255',
            'name_ar' => 'required|string|max:255',
            'layout_type' => 'required|in:grid,lanes,zones,custom',
            'start_time' => 'required|date_format:H:i',
            'end_time' => 'required|date_format:H:i|after:start_time',
        ]);

        $layoutConfig = match ($this->layout_type) {
            'grid' => ['rows' => $this->grid_rows, 'columns' => $this->grid_columns],
            'lanes' => ['lane_count' => $this->lane_count],
            'zones', 'custom' => ['definitions' => $this->zone_definitions],
            default => [],
        };

        $data = [
            'academy_id' => $this->facility->academy_id,
            'facility_id' => $this->facility->id,
            'name' => $this->name,
            'name_ar' => $this->name_ar,
            'layout_type' => $this->layout_type,
            'layout_config' => $layoutConfig,
            'is_recurring' => $this->is_recurring,
            'effective_day_of_week' => $this->is_recurring ? $this->effective_day_of_week : null,
            'effective_date' => !$this->is_recurring ? $this->effective_date : null,
            'start_time' => $this->start_time,
            'end_time' => $this->end_time,
        ];

        try {
            if ($this->editingLayoutId) {
                $layout = $this->facility->layouts()->findOrFail($this->editingLayoutId);
                $service->update($layout, $data);
                session()->flash('success', __('تم تحديث التخطيط بنجاح'));
            } else {
                $service->create($data, auth()->user());
                session()->flash('success', __('تم إنشاء التخطيط بنجاح'));
            }

            $this->showForm = false;
            $this->resetForm();
            $this->loadLayouts();
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    public function deleteLayout(int $id): void
    {
        try {
            $layout = $this->facility->layouts()->findOrFail($id);
            app(SpaceLayoutService::class)->delete($layout);
            session()->flash('success', __('تم حذف التخطيط'));
            $this->loadLayouts();
        } catch (DomainException $e) {
            session()->flash('error', $e->getMessage());
        }
    }

    /**
     * space_segments carries neither academy_id nor branch_id — it inherits
     * both from its layout. Resolving through the facility is therefore the
     * only thing standing between a browser-supplied id and any segment row in
     * the database.
     */
    public function toggleSegmentAvailability(int $segmentId): void
    {
        $segment = SpaceSegment::whereHas(
            'layout',
            fn ($q) => $q->where('facility_id', $this->facility->id)
        )->findOrFail($segmentId);

        $segment->update(['is_available' => !$segment->is_available]);
        $this->loadLayouts();
    }

    public function addZone(): void
    {
        $index = count($this->zone_definitions) + 1;
        $this->zone_definitions[] = [
            'code' => 'Z' . $index,
            'name' => 'Zone ' . $index,
            'name_ar' => 'منطقة ' . $index,
            'capacity' => null,
        ];
    }

    public function removeZone(int $index): void
    {
        unset($this->zone_definitions[$index]);
        $this->zone_definitions = array_values($this->zone_definitions);
    }

    private function resetForm(): void
    {
        $this->editingLayoutId = null;
        $this->name = '';
        $this->name_ar = '';
        $this->layout_type = 'grid';
        $this->is_recurring = true;
        $this->effective_day_of_week = 6;
        $this->effective_date = null;
        $this->start_time = '08:00';
        $this->end_time = '22:00';
        $this->grid_rows = 2;
        $this->grid_columns = 3;
        $this->lane_count = 4;
        $this->zone_definitions = [];
    }

    public function render()
    {
        return view('livewire.facilities.space-layout-manager');
    }
}
