<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Terminy\Http\Controllers\Backend\Udalosti\Livewire\Components;

use Exception;
use Livewire\Component;
use Illuminate\Validation\Rule;
use Illuminate\Support\Facades\DB;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
use Illuminate\Database\Eloquent\Collection;
use Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Seka\Portal\Modul\Terminy\Entities\Udalost\StavUdalosti;
use Seka\Portal\Modul\Terminy\Entities\Udalost\DruhUdalosti;
use Seka\Portal\Modul\Terminy\Entities\Udalost\StavRegistracie;
use Seka\Portal\Modul\Terminy\Entities\Udalost\StavUpozornenia;
use Seka\Portal\Modul\Terminy\Entities\MiestoKonania\MiestoKonania;

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

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

    /**
     * @var \Illuminate\Database\Eloquent\Collection
     */
    public Collection $miestaKonania;

    /**
     * @param \Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost $udalost
     */
    public function mount(Udalost $udalost): void
    {
        $this->udalost = $udalost;
        $this->miestaKonania = MiestoKonania::all();
    }

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

    /**
     * Obnovit zneplatnenu udalost
     *
     * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse|void
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function restore()
    {
        try {
            $this->authorize('terminy.udalosti.upravit');

            if (!$this->udalost->trashed()) return;

            DB::beginTransaction();

            $this->udalost->restore();

            DB::commit();

            $this->udalost->refresh();

            flash()->overlay('Udalosť bola úspešne obnovená', 'Hlásenie')->success();

            return redirect()->route('modul.terminy.backend.udalosti.index');
        } catch (Exception $e) {
            DB::rollBack();

            Log::error($e->getMessage(), $e->getTrace());

            flash()->overlay('Udalosť sa nepodarilo obnoviť.', 'Hlásenie')->error();
        }
    }

    /**
     * Zneplatnit udalost
     *
     * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function trash()
    {
        try {
            $this->authorize('terminy.udalosti.odstranit');

            DB::beginTransaction();

            // soft delete
            $this->udalost->delete();

            DB::commit();

            flash()->overlay('Udalosť bola úspešne zneplatnená', 'Hlásenie')->success();

            return redirect()->route('modul.terminy.backend.udalosti.index');
        } catch (Exception $e) {
            DB::rollBack();

            Log::error($e->getMessage(), $e->getTrace());

            flash()->overlay('Udalosť nebola zneplatnená.', 'Hlásenie')->error();
        }
    }

    /**
     * Vytvorit novu alebo aktualizovat existujucu udalost
     *
     * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     * @throws \Throwable
     */
    public function save()
    {
        $this->validate();

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

            $existBeforeSave = $this->udalost->exists ?? false;

            // over opravnenia pouzivatela podla existencie udalosti
            if ($existBeforeSave) {
                $this->authorize('terminy.udalosti.upravit');
            } else {
                $this->authorize('terminy.udalosti.vytvorit');
            }

            DB::beginTransaction();

            $this->udalost->vytvoril()->associate(auth()->user());
            $this->udalost->miestoKonania()->associate(MiestoKonania::query()->findOrFail($this->udalost->miesto_konania_id));
            $this->udalost->save();
            $this->udalost->refresh();

            DB::commit();

            $message = $existBeforeSave ? 'Udalosť bola aktualizovaná' : 'Nová udalosť bola vytvorená';

            flash()->overlay($message, 'Hlásenie')->success();

            return redirect()->route('modul.terminy.backend.udalosti.index');
        } catch (Exception $e) {
            DB::rollBack();

            Log::error($e->getMessage(), $e->getTrace());

            flash()->overlay('Udalosť nebola úspešne uložená.', 'Hlásenie')->error();
        }
    }

    /**
     * @return \Illuminate\Routing\Redirector|\Illuminate\Http\RedirectResponse
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function cancel()
    {
        return redirect()->route('modul.terminy.backend.udalosti.index');
    }

    /**
     * @return void
     */
    public function toggleStavUpozornenia(): void
    {
        $this->udalost->upozornenie = $this->udalost->jePovoleneUpozornenie() ? StavUpozornenia::NEPOVOLENE() : StavUpozornenia::POVOLENE();
    }

    /**
     * Ak je udalost zneplatnena, tak formular je v rezime zneplatnenia
     *
     * @return bool
     */
    public function trashMode(): bool
    {
        return $this->udalost->trashed();
    }

    /**
     * Ak udalost existuje, tak formular je v rezime uprava
     *
     * @return bool
     */
    public function editMode(): bool
    {
        return $this->udalost->exists;
    }

    /**
     * @return array
     */
    public function rules(): array
    {
        return [
            'udalost.miesto_konania_id' => 'required|exists:terminy_udalost_miesta_konania,id',
            'udalost.nazov' => 'required|max:255',
            'udalost.datum_od' => 'required|date',
            'udalost.datum_do' => 'required|date|after_or_equal:udalost.datum_od',
            'udalost.kapacita' => 'required|numeric|min:1',
            'udalost.stav' => [
                'required',
                Rule::in(StavUdalosti::toValues()),
            ],
            'udalost.druh' => [
                'required',
                Rule::in(DruhUdalosti::toValues()),
            ],
            'udalost.registracia' => [
                'required',
                Rule::in(StavRegistracie::toValues()),
            ],
            'udalost.popis' => 'max:16384',
            'udalost.povolene_upozornenie' => 'required|boolean',
        ];
    }

    /**
     * @return string[]
     */
    public function messages(): array
    {
        return [
            'udalost.nazov.required' => 'Názov udalosti je povinný',
            'udalost.nazov.max' => 'Maximálny počet znakov názvu udalosti je :max',
            'udalost.datum_od.required' => 'Začiatok udalosti je povinný',
            'udalost.datum_od.date' => 'Začiatok udalosti musí byť dátum',
            'udalost.datum_do.required' => 'Ukončenie udalosti je povinné',
            'udalost.datum_do.date' => 'Ukončenie udalosti musí byť dátum',
            'udalost.datum_do.after_or_equal' => 'Ukončenie udalosti musí byť po jej začiatku',
            'udalost.miesto_konania_id.required' => 'Miesto konania sa vyžaduje',
            'udalost.miesto_konania_id.exists' => 'Miesto konania musí byť vytvorené',
            'udalost.kapacita.required' => 'Kapacita je vyžadovaná',
            'udalost.kapacita.numeric' => 'Kapacita musí byť číselnou hodnotou',
            'udalost.kapacita.min' => 'Minimálna hodnota kapacity je :min',
            'udalost.stav.required' => 'Stav udalosti je vyžadovaný',
            'udalost.stav.in' => 'Neznámi stav udalosti',
            'udalost.druh.required' => 'Druh udalosti je vyžadovaný',
            'udalost.druh.in' => 'Neznámi druh udalosti',
            'udalost.registracia.required' => 'Nastavenie stavu registrácie je vyžadované',
            'udalost.registracia.in' => 'Neznámi druh stavu registrácie',
            'udalost.popis.max' => 'Maximálny počet znakov popisu udalosti je :max',
            'udalost.povolene_upozornenie.required' => 'Stav upozornenia je vyžadovaný',
            'udalost.povolene_upozornenie.boolean' => 'Neznámi stav upozornenia',
        ];
    }
}
