<?php

declare(strict_types=1);

namespace Seka\Vzdelavanie\Services\Pouzivatel\Testovanie;

use Illuminate\Support\Facades\Auth;
use Seka\Vzdelavanie\Models\Pouzivatel\Testovanie\Test;
use Seka\Vzdelavanie\Models\Pouzivatel\Testovanie\Otazka;
use Seka\Vzdelavanie\Models\Pouzivatel\Testovanie\Odpoved;
use Seka\Vzdelavanie\Events\Testovanie\Frontend\TestVyhodnotenie;
use Seka\Vzdelavanie\Services\Pouzivatel\Testovanie\Exceptions\TestUzBolVyhodnotenyException;

/**
 * Class VyhodnotenieTestu
 *
 * @package Seka\Vzdelavanie\Services\Pouzivatel\Testovanie
 */
final class VyhodnotenieTestu
{
    /**
     * @param \Seka\Vzdelavanie\Models\Pouzivatel\Testovanie\Test $test
     *
     * @return \Seka\Vzdelavanie\Models\Pouzivatel\Testovanie\Test
     * @throws \Seka\Vzdelavanie\Services\Pouzivatel\Testovanie\Exceptions\TestUzBolVyhodnotenyException
     * @throws \Throwable
     */
    public static function vyhodnotenie(Test $test): Test
    {
        $pocetOtazokBezOdpovede = 0;
        $pocetSpravneZodpovedanychOtazok = 0;
        $pocetNespravneZodpovedanychOtazok = 0;

        if (true === $test->jeVyhodnoteny()) {
            throw new TestUzBolVyhodnotenyException();
        }

        $test->otazky()->each(function (Otazka $otazka) use (&$pocetSpravneZodpovedanychOtazok, &$pocetNespravneZodpovedanychOtazok, &$pocetOtazokBezOdpovede) {
            $spravneZodpovedanaOtazka = false;
            $pocetSpravnychOdpovedi = 0;
            $pocetNespravnychOdpovedi = 0;
            $zodpovedanaOtazka = false;

            $otazka
                ->odpovede()
                ->each(
                    function (Odpoved $odpoved) use (&$pocetSpravnychOdpovedi, &$pocetNespravnychOdpovedi, &$spravneZodpovedanaOtazka, &$zodpovedanaOtazka) {
                        if ($odpoved->jeZvolena()) {
                            if ($odpoved->jeSpravna()) {
                                $pocetSpravnychOdpovedi = ++$pocetSpravnychOdpovedi;
                            } else {
                                $pocetNespravnychOdpovedi = ++$pocetNespravnychOdpovedi;
                            }

                            $zodpovedanaOtazka = true;
                        } else {
                            if ($odpoved->jeSpravna()) {
                                $pocetNespravnychOdpovedi = ++$pocetNespravnychOdpovedi;
                            }
                        }
                    }
                );

            if ($pocetNespravnychOdpovedi === 0) {
                $spravneZodpovedanaOtazka = VyhodnotenieOtazky::vyhodnot($otazka, $pocetSpravnychOdpovedi);
            }

            if ($pocetNespravnychOdpovedi > 0 && $zodpovedanaOtazka === true) {
                $pocetNespravneZodpovedanychOtazok = ++$pocetNespravneZodpovedanychOtazok;
            }

            if (true === $spravneZodpovedanaOtazka) {
                $pocetSpravneZodpovedanychOtazok = ++$pocetSpravneZodpovedanychOtazok;
            }

            if (false === $zodpovedanaOtazka) {
                $pocetOtazokBezOdpovede = ++$pocetOtazokBezOdpovede;
            }
        });

        $test->fill([
            'pocet_otazok_bez_odpovede' => $pocetOtazokBezOdpovede,
            'casova_znacka_vyhodnotenia' => now(),
            'pocet_spravne_zodpovedanych_otazok' => $pocetSpravneZodpovedanychOtazok,
            'pocet_nespravne_zodpovedanych_otazok' => $pocetNespravneZodpovedanychOtazok,
        ])->saveOrFail();

        // zaznamenat udalost vyhodnotenia testu
        event(new TestVyhodnotenie($test, Auth::user()));

        return $test->refresh();
    }
}
