<?php

/** @noinspection PhpUnhandledExceptionInspection */

namespace DefStudio\GameEngine\Http\Livewire\Maps;

use Livewire\WithFileUploads;
use Illuminate\Contracts\View\View;
use Livewire\TemporaryUploadedFile;
use DefStudio\GameEngine\Models\Map;
use LivewireUI\Modal\ModalComponent;
use Illuminate\Validation\Rules\File;
use DefStudio\GameEngine\Actions\Maps\SaveMap;
use Illuminate\Validation\ValidationException;
use DefStudio\GameEngine\Exceptions\MapException;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use DefStudio\GameEngine\Actions\Maps\StoreBackgroundImage;
use DefStudio\GameEngine\Http\Livewire\Concerns\ImprovedModal;
use DefStudio\GameEngine\Http\Livewire\Concerns\RedirectsBack;

class Edit extends ModalComponent
{
    use AuthorizesRequests;
    use RedirectsBack;
    use WithFileUploads;
    use ImprovedModal;

    /** @var Map */
    public $map;

    /** @var TemporaryUploadedFile|null */
    public $background_image = null;

    public bool $editing;

    public array $rules = [
        'map.story_id' => 'required',
        'map.title' => 'required|string|max:255',
        'map.description' => 'nullable|string',
    ];

    public function mount(int $story_id = null): void
    {
        /** @phpstan-ignore-next-line  */
        throw_if(!isset($this->map) && $story_id === null, MapException::must_be_bound_to_a_story());

        /** @phpstan-ignore-next-line */
        $this->map ??= game_engine()->mapQuery()->make();
        $this->map->story_id ??= $story_id;

        $this->editing = !$this->map->exists;

        $this->authorize('save', $this->map);
    }

    public function render(): View
    {
        return view('game-engine::livewire.admin.maps.edit');
    }

    public function updatedBackgroundImage(): void
    {
        try {
            $this->validate(['background_image' => File::image()]);
        } catch (ValidationException $validationException) {
            $this->background_image = null;
            throw $validationException;
        }
    }

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

        SaveMap::run($this->map);

        if ($this->background_image !== null) {
            StoreBackgroundImage::run($this->map, $this->background_image);
        }

        if ($this->map->wasRecentlyCreated) {
            $this->emit('map.created', $this->map->id);
        } else {
            $this->emit('map.updated', $this->map->id);
        }

        if ($this->isModal) {
            $this->closeModal();

            return;
        }

        if ($this->map->wasRecentlyCreated) {
            $this->redirect_back();
        } else {
            $this->editing = false;
        }
    }
}
