<?php

/** @noinspection PhpUnhandledExceptionInspection */

namespace DefStudio\GameEngine\Http\Livewire\Storytellings;

use Livewire\WithFileUploads;
use Illuminate\Contracts\View\View;
use Livewire\TemporaryUploadedFile;
use LivewireUI\Modal\ModalComponent;
use Illuminate\Validation\Rules\File;
use DefStudio\GameEngine\Enums\Feature;
use DefStudio\GameEngine\Models\Storytelling;
use Illuminate\Validation\ValidationException;
use DefStudio\GameEngine\Enums\StorytellingType;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use DefStudio\GameEngine\Exceptions\StorytellingException;
use DefStudio\GameEngine\Http\Livewire\Concerns\ImprovedModal;
use DefStudio\GameEngine\Actions\Storytellings\SaveStorytelling;
use DefStudio\GameEngine\Actions\Storytellings\StoreAvatarImage;
use DefStudio\GameEngine\Actions\Storytellings\RemoveAvatarImage;
use DefStudio\GameEngine\Actions\Storytellings\StoreBackgroundImage;
use DefStudio\GameEngine\Actions\Storytellings\RemoveBackgroundImage;

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

    /** @var Storytelling */
    public $storytelling;

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

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

    public array $rules = [
        'storytelling.text' => 'required|string',
        'storytelling.type' => 'required',
        'storytelling.target_id' => 'required',
        'storytelling.target_type' => 'required',
        'storytelling.avatar_position' => 'required|in:left,right',
    ];

    public function mount(int|null $storytelling_id = null, int|null $target_id = null, string|null $target_type = null, string|null $type = null): void
    {
        Feature::storytelling->enforce();

        throw_if($storytelling_id === null && ($target_id === null || $target_type === null), StorytellingException::must_be_bound_to_a_target());

        $this->storytelling = $storytelling_id !== null
            ? game_engine()->storytellingQuery()->findOrFail($storytelling_id)
            : game_engine()->storytellingQuery()->make()->forceFill(['target_id' => $target_id, 'target_type' => $target_type]);

        if ($type !== null) {
            $this->storytelling->type = StorytellingType::from($type);
        }

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

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

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

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

    public function remove_background(): void
    {
        $this->background_image = null;
        RemoveBackgroundImage::run($this->storytelling);
    }

    public function remove_avatar(): void
    {
        $this->avatar = null;
        RemoveAvatarImage::run($this->storytelling);
    }

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

        SaveStorytelling::run($this->storytelling);

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

        if ($this->avatar !== null) {
            StoreAvatarImage::run($this->storytelling, $this->avatar);
        }

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

        $this->emit('storytelling.saved', $this->storytelling->id);

        $this->closeModal();
    }
}
