<?php

/** @noinspection PhpUnhandledExceptionInspection */

namespace DefStudio\GameEngine\Http\Livewire\Awards;

use Livewire\WithFileUploads;
use Illuminate\Contracts\View\View;
use Livewire\TemporaryUploadedFile;
use LivewireUI\Modal\ModalComponent;
use Illuminate\Validation\Rules\File;
use DefStudio\GameEngine\Models\Award;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\ValidationException;
use DefStudio\GameEngine\Actions\Awards\SaveAward;
use DefStudio\GameEngine\Actions\Awards\StoreIconImage;
use DefStudio\GameEngine\Actions\Awards\RemoveIconImage;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use DefStudio\GameEngine\Http\Livewire\Concerns\ImprovedModal;
use DefStudio\GameEngine\Actions\Livewire\Sortable\UpdateOrder;

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

    /** @var Award */
    public $award;

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

    public array $rules = [
        'award.name' => 'required|string|max:255',
        'award.description' => 'nullable|string',
        'award.scope_type' => 'nullable|string',
        'award.scope_id' => 'nullable|numeric',
        'award.parent_id' => 'nullable|numeric',
    ];

    protected $listeners = [
        'award.saved' => '$refresh',
    ];

    /**
     * @param  class-string<Model>|null  $scope_class
     */
    public function mount(int $award_id = null, string $scope_class = null, int $scope_id = null, int $parent_id = null): void
    {
        if ($award_id) {
            $this->award = game_engine()->awardQuery()->findOrFail($award_id);
        } else {

            if ($parent_id) {
                /** @var Award $parent_award */
                $parent_award = game_engine()->awardQuery()->findOrFail($parent_id);
                $scope_class = $parent_award->scope_type;
                $scope_id = $parent_award->scope_id;
            }

            $this->award = game_engine()->awardQuery()->make()->forceFill([
                'scope_type' => $scope_class,
                'scope_id' => $scope_id,
                'parent_id' => $parent_id,
            ]);
        }

        if ($this->award->exists) {
            $this->authorize('update', $this->award);
        } else {
            $this->authorize('create', $this->award);
        }
    }

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

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

    public function remove_icon_image(): void
    {
        $this->icon_image = null;
        RemoveIconImage::run($this->award);
    }

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

        SaveAward::run($this->award);

        if ($this->icon_image !== null) {
            StoreIconImage::run($this->award, $this->icon_image);
        }

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

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

        $this->closeModal();
    }

    public function update_children_order(array $new_order): void
    {
        UpdateOrder::run($this->award->children, $new_order);
    }
}
