<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Terminy\Livewire\Backend\Udalosti\Components\MoznostiUdalosti\Components;

use Exception;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\View\View;
use Livewire\Component;
use Seka\Portal\Modul\Terminy\Entities\MoznostiUdalosti\MoznostUdalosti;
use Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost;
use Seka\Portal\Modul\Terminy\Entities\Udalost\ValueObjects\MoznostUdalostiValueObject;
use Seka\Portal\Modul\Terminy\Entities\Udalost\ValueObjects\ZoznamMoznostiUdalostiValueObject;

/**
 * Class Form
 *
 * @package Seka\Portal\Modul\Terminy\Livewire\Backend\Udalosti\Components\MoznostiUdalosti\Components
 */
final class Form extends Component
{
    use AuthorizesRequests;

    /**
     * @var \Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost
     */
    public Udalost $udalost;

    /**
     * @var \Seka\Portal\Modul\Terminy\Entities\MoznostiUdalosti\MoznostUdalosti
     */
    public MoznostUdalosti $moznostUdalosti;

    /**
     * @var array
     */
    public array $moznosti;

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost                  $udalost
     * @param \Seka\Portal\Modul\Terminy\Entities\MoznostiUdalosti\MoznostUdalosti $moznostUdalosti
     *
     * @return void
     */
    public function mount(Udalost $udalost, MoznostUdalosti $moznostUdalosti): void
    {
        $this->udalost = $udalost;
        $this->moznostUdalosti = $moznostUdalosti;
        $_moznosti = $udalost->moznosti->filter(
            function (ZoznamMoznostiUdalostiValueObject $zoznamMoznostiUdalostiValueObject) {
                return $zoznamMoznostiUdalostiValueObject->getKod() === $this->moznostUdalosti->kod;
            },
        );
        $this->moznosti = $_moznosti->isNotEmpty() ? collect($_moznosti->first()->getMoznosti())->toArray() : [];
    }

    /**
     * @return \Illuminate\View\View
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function render(): View
    {
        return view('Terminy::livewire.backend.udalosti.components.moznosti-udalosti.components.form');
    }

    /**
     * @return void
     */
    public function addMoznost(): void
    {
        $this->moznosti[] = (new MoznostUdalostiValueObject(''))->toArray();
    }

    /**
     * @param int $index
     *
     * @return void
     */
    public function removeMoznost(int $index): void
    {
        array_splice($this->moznosti, $index, 1);
    }

    /**
     * @return void
     */
    public function saveMoznosti(): void
    {
        $this->validate();

        try {
            $this->authorize('terminy');

            $moznosti = collect($this->moznosti)->map(function (array $data) {
                return new MoznostUdalostiValueObject($data['popis']);
            });
            $zoznamMoznosti = new ZoznamMoznostiUdalostiValueObject(
                $this->moznostUdalosti->nazov,
                $this->moznostUdalosti->kod,
                $moznosti->all(),
            );

            $exist = $this->udalost->moznosti->filter(
                function (ZoznamMoznostiUdalostiValueObject $zoznam) use ($zoznamMoznosti) {
                    return $zoznam->getKod() === $zoznamMoznosti->getKod();
                },
            )->isNotEmpty();

            if ($exist) {
                // ak su nejake polozky moznosti, tak aktualizuje zaznam
                if (count($zoznamMoznosti->getMoznosti()) > 0) {
                    $out = $this->udalost->moznosti->map(
                        function (ZoznamMoznostiUdalostiValueObject $zoznam) use ($zoznamMoznosti) {
                            if ($zoznam->getKod() === $zoznamMoznosti->getKod()) {
                                return $zoznamMoznosti;
                            }

                            return $zoznam;
                        },
                    );
                    // ak nie su polozky moznosti, tak odstrani zaznam
                } else {
                    $out = $this->udalost->moznosti->reject(
                        function (ZoznamMoznostiUdalostiValueObject $zoznam) use ($zoznamMoznosti) {
                            return $zoznam->getKod() === $zoznamMoznosti->getKod();
                        },
                    );
                }

                $this->udalost->moznosti = $out;
            } else {
                $this->udalost->moznosti->add($zoznamMoznosti);
            }

            $this->udalost->save();
            $this->udalost->refresh();

            flash()->success('Položky možností udalosti boli úspešne uložené.')->important();
        } catch (Exception $exc) {
            flash()->error('Nastala chyba počas ukladania položiek možností udalosti.')->important();
        }
    }

    /**
     * @return string[]
     */
    public function rules(): array
    {
        return [
            'moznosti.*.popis' => 'required',
        ];
    }

    /**
     * @return string[]
     */
    public function messages(): array
    {
        return [
            'moznosti.*.popis.required' => 'Popis možnosti udalosti je vyžadovaný',
        ];
    }
}
