<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Terminy\Http\Controllers\Frontend\Registracie;

use Elceka\Laravel\HashId\Hasher;
use Exception;
use Illuminate\Support\Facades\DB;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Log;
use Seka\Portal\Modul\Terminy\Entities\Udalost\Udalost;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Seka\Portal\Modul\Terminy\Actions\CreateRegistration;
use Seka\Portal\Modul\Terminy\Exceptions\TerminyException;
use Seka\Portal\Modul\Terminy\Exceptions\UdalostUzPrebieha;
use Seka\Portal\Modul\Terminy\Exceptions\UdalostSaUzKonala;
use Seka\Portal\Modul\Terminy\Entities\Registracia\Registracia;
use Seka\Portal\Modul\Terminy\Exceptions\NaUdalostNieJePovolenaRegistracia;
use Seka\Portal\Modul\Terminy\Exceptions\RegistraciaPouzivatelaNaUdalostNeexistuje;

/**
 * Class PouzivatelController
 *
 * @package Seka\Portal\Modul\Terminy\Http\Controllers\Frontend\Registracie
 */
final class PouzivatelController
{
    /**
     * @return \Illuminate\Contracts\View\View
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function index(): View
    {
        $registracie = Registracia::query()
            ->with('pouzivatel', 'vytvoril', 'pracovisko', 'udalost')
            ->wherePouzivatelId(auth()->user()->getAuthIdentifier())
            ->orderByDesc('id')
            ->paginate();

        return view('Terminy::pages.udalosti.registracie.frontend.pouzivatel')
            ->withRegistracie($registracie);
    }

    /**
     * @param \Seka\Portal\Modul\Terminy\Actions\CreateRegistration $createRegistration
     * @param int                                      $udalostId
     *
     * @return \Illuminate\Http\RedirectResponse
     * @throws \Illuminate\Contracts\Container\BindingResolutionException|\Throwable
     */
    public function create(CreateRegistration $createRegistration, int $udalostId)
    {
        try {
            /** @var Udalost $udalost */
            $udalost = Udalost::query()
                ->zverejnena()
                ->findOrFail($udalostId);

            if ($udalost->maVytvoreneMoznosti()) {
                return redirect()
                    ->route(
                        'modul.terminy.frontend.registracie.pouzivatel.selectOptions',
                        ['mtUdalostId' => Hasher::encode($udalostId)]);
            }

            $pouzivatel = auth()->user();
            $pracovisko = auth()->user()->pracovisko;
            $registracia = new Registracia();
            $registracia->pouzivatel()->associate($pouzivatel);

            DB::beginTransaction();
            $createRegistration::execute($udalost, $pouzivatel, $pracovisko, $registracia);
            DB::commit();

            flash()->overlay('Registrácia používateľa na udalosť bola úspešná.', 'Hlásenie')->success();
        } catch (ModelNotFoundException $e) {
            flash()->overlay('Udalosť nebola nájdená.', 'Hlásenie')->warning();
        } catch (TerminyException $e) {
            flash()->overlay($e->getMessage(), 'Hlásenie')->warning();
        } catch (Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            flash()->overlay('Chyba', 'Hlásenie')->error();
        }

        return redirect()->back();
    }

    public function selectOptions(int $udalostId)
    {
        $udalost = Udalost::query()
            ->zverejnena()
            ->findOrFail($udalostId);

        return view('Terminy::pages.udalosti.registracie.frontend.volba_moznosti')
            ->withUdalost($udalost);
    }

    /**
     * @param int $udalostId
     *
     * @return \Illuminate\Http\RedirectResponse
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    public function delete(int $udalostId)
    {
        try {
            /** @var Udalost $udalost */
            $udalost = Udalost::query()
                ->zverejnena()
                ->findOrFail($udalostId);

            if (false === $udalost->jePovolenaRegistracia()) {
                throw new NaUdalostNieJePovolenaRegistracia();
            }

            if ($udalost->skoncila) {
                throw new UdalostSaUzKonala();
            }

            if (true === $udalost->prebieha) {
                throw new UdalostUzPrebieha();
            }

            $registracia = $udalost->registracie()
                ->where('pouzivatel_id', auth()->user()->getAuthIdentifier())
                ->first();

            if (is_null($registracia) || (!$registracia instanceof Registracia)) {
                throw new RegistraciaPouzivatelaNaUdalostNeexistuje();
            }

            DB::beginTransaction();
            $registracia->delete();
            DB::commit();

            flash()->overlay('Zrušenie vašej registrácie na udalosť bolo úspešné.', 'Hlásenie')->success();
        } catch (TerminyException $e) {
            flash()->overlay('Vaša registrácia na udalosť neexistuje.', 'Hlásenie')->warning();
        } catch (Exception $e) {
            DB::rollBack();
            Log::error($e->getMessage(), $e->getTrace());
            flash()->overlay('Chyba', 'Hlásenie')->error();
        } finally {
            return redirect()->back();
        }
    }
}
