<?php

declare(strict_types=1);

namespace Seka\Vzdelavanie\Commands\Console;

use Exception;
use Illuminate\Console\Command;
use PhpOffice\PhpSpreadsheet\IOFactory;
use Illuminate\Database\Eloquent\Builder;
use PhpOffice\PhpSpreadsheet\Worksheet\Row;
use Seka\Vzdelavanie\Enums\ModelStatusEnum;
use Seka\Vzdelavanie\Models\Testovanie\Test;
use Seka\Vzdelavanie\Models\Testovanie\Otazka;
use Seka\Vzdelavanie\Models\Testovanie\Odpoved;
use Seka\Vzdelavanie\Models\Testovanie\HodnotenieOdpovedeEnum;
use Seka\Vzdelavanie\Models\Testovanie\DruhSpravnejOdpovedeEnum;

final class ImportTestov extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'import:testy {subor}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Import otazok a odpovedi testov';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     *
     */
    public function handle()
    {
        try {
            $pocetZverejnenychOtazokTestu = 3;
            $subor = sprintf('%s%s%s', base_path(), DIRECTORY_SEPARATOR, $this->argument('subor'));
            $reader = IOFactory::load($subor);
            $nazvyZositov = $reader->getSheetNames();
            $nazvyZositov = $this->vratMultidimenzionalnePole($nazvyZositov);

            $this->output->title('Zoznam zositov (typov testov):');
            $this->output->table(['Nazov'], $nazvyZositov);

            // zneplatnenie existujucich testov
            Test::query()->where('stav', ModelStatusEnum::PUBLIKOVANE()->value)->take(5)->each(function (Test $test) {
                $test
                    ->setAttribute('stav', ModelStatusEnum::NEPUBLIKOVANE()->value)
                    ->setAttribute('popis', $test->popis . PHP_EOL . PHP_EOL . 'Zneplatnený pri importe nových testov ' . date('d.m.Y H:i:s'))
                    ->save();
            });

            foreach ($reader->getWorksheetIterator() as $sheet) {
                $test = new Test();
                $test->setAttribute('nazov', ucfirst($sheet->getTitle()));
                $test->setAttribute('popis', 'Test obsahuje otázky a odpovede kategórie ' . $sheet->getTitle());
                $test->setAttribute('stav', ModelStatusEnum::PUBLIKOVANE());
                $test->save();
                $test = $test->fresh();

                foreach ($sheet->getRowIterator() as $row) {
                    if ($row->getRowIndex() == 1) {
                        continue;
                    }

                    $this->importOtazokAOdpovedi($test, $row);
                }

                $pocetZverejnenychOtazokTestu = $test->otazky()->where(function (Builder $query) {
                    $query->where('stav', ModelStatusEnum::PUBLIKOVANE()->value);
                })->count();

                $test->setAttribute('pocet_otazok', (int) ($pocetZverejnenychOtazokTestu / 2));
                $test->save();
            }
        } catch (Exception $e) {
            $this->output->error($e->getMessage());
        }
    }

    /**
     * @param \Seka\Vzdelavanie\Models\Testovanie\Test $test
     * @param \PhpOffice\PhpSpreadsheet\Worksheet\Row  $row
     *
     * @return void
     */
    private function importOtazokAOdpovedi(Test $test, Row $row): void
    {
        /** @var Otazka $otazka */
        $otazka = null;
        /** @var Odpoved $odpoved */
        $odpoved = null;

        foreach ($iterator = $row->getCellIterator() as $cell) {
            if ($cell->getColumn() == 'A') {
                continue;
            }

            if ($this->jeStavOtazky($cell->getColumn())) {
                $otazka = new Otazka();
                $otazka->setAttribute('stav', ModelStatusEnum::PUBLIKOVANE());
            }

            if (is_null($cell->getValue())) {
                continue;
            }

            if ($this->jeOtazka($cell->getColumn())) {
                $otazka->setAttribute('znenie', $cell->getValue());
                $otazka->setAttribute('druh_spravnej_odpovede', DruhSpravnejOdpovedeEnum::JEDNA());
                $test->otazky()->save($otazka);

                continue;
            }

            if ($this->jeOdpoved($cell->getColumn())) {
                $odpoved = (new Odpoved())->fill([
                    'znenie' => $cell->getValue(),
                    'stav' => ModelStatusEnum::PUBLIKOVANE(),
                ]);

                continue;
            }

            if ($this->jeHodnotenie($cell->getColumn())) {
                $odpoved->setAttribute('hodnotenie', ((bool) $cell->getValue()) ? HodnotenieOdpovedeEnum::SPRAVNA() : HodnotenieOdpovedeEnum::NESPRAVNA());
                $otazka->odpovede()->save($odpoved);

                continue;
            }
        }
    }

    private function jeStavOtazky(string $stlpec): bool
    {
        $stavOtazky = ['B'];

        return in_array($stlpec, $stavOtazky);
    }

    /**
     * @param string $stlpec
     * @return bool
     */
    private function jeOtazka(string $stlpec): bool
    {
        $otazka = ['C'];

        return in_array($stlpec, $otazka);
    }

    /**
     * @param string $stlpec
     * @return bool
     */
    private function jeOdpoved(string $stlpec): bool
    {
        $znenieOdpovede = ['D', 'F', 'H', 'J', 'L', 'N', 'P', 'R', 'T'];

        return in_array($stlpec, $znenieOdpovede);
    }

    /**
     * @param string $stlpec
     * @return bool
     */
    private function jeHodnotenie(string $stlpec): bool
    {
        $hodnotenieOdpovede = ['E', 'G', 'I', 'K', 'M', 'O', 'Q', 'S', 'U'];

        return in_array($stlpec, $hodnotenieOdpovede);
    }

    /**
     * @param array $pole
     * @return array
     */
    private function vratMultidimenzionalnePole(array $pole)
    {
        $polozky = [];

        foreach ($pole as $polozka) {
            $polozky[] = [$polozka];
        }

        return $polozky;
    }
}
