<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Statistiky\Repositories\Eloquent\Transformers;

use League\Fractal\TransformerAbstract;
use Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam;
use Seka\Portal\Modul\Statistiky\Exceptions\NeznamiDruhUdajovZaznamuException;
use Seka\Portal\Modul\Statistiky\Entities\Zaznam\Enums\DruhEmisnejKontrolyEnum;
use Seka\Portal\Modul\Statistiky\Entities\Zaznam\Enums\StavEmisnejKontrolyEnum;
use Seka\Portal\Modul\Statistiky\Entities\Zaznam\Enums\HodnotenieEmisnejKontrolyEnum;
use Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\UdajePreTypZaznamuPracovisko;
use Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\UdajePreTypZaznamuPouzivatel;

/**
 * Class ZaznamDataTableTransformer
 *
 * @package Seka\Portal\Modul\Statistiky\Repositories\Eloquent\Transformers
 */
final class ZaznamDataTableTransformer extends TransformerAbstract
{
    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     * @throws \Seka\Portal\Modul\Statistiky\Exceptions\NeznamiDruhUdajovZaznamuException
     */
    public function transform(Zaznam $model): array
    {
        if ($model->udaje instanceof UdajePreTypZaznamuPracovisko) {
            return $this->transformUdajePreTypZaznamuPracovisko($model);
        }

        if ($model->udaje instanceof UdajePreTypZaznamuPouzivatel) {
            return $this->transformUdajePreTypZaznamuPouzivatel($model);
        }

        throw new NeznamiDruhUdajovZaznamuException('Neznami druh udajov zaznamu.');
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePreTypZaznamuPracovisko(Zaznam $model): array
    {
        $out = [
            'zoznamPoctuKontrolPodlaStavu' => [],
            'zoznamPoctuKontrolPodlaDruhuAHodnotenia' => [],
            'zoznamPoctuKontrolPodlaKategorieVozidla' => [],
            'zoznamPoctuKontrolAObratuPodlaSubjektuFakturacie' => [],
            'zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla' => [],
        ];
        $out = array_merge($out, $this->transformUdajePekZoznamPoctuKontrolPodlaStavu($model));
        $out = array_merge($out, $this->transformUdajePekZoznamPoctuKontrolPodlaDruhuAHodnotenia($model));
        $out = array_merge($out, $this->transformUdajePekZoznamPoctuKontrolPodlaKategorieVozidla($model));
        $out = array_merge($out, $this->transformUdajePekZoznamPoctuKontrolAObratuPodlaSubjektuFakturacie($model));
        $out = array_merge($out, $this->transformUdajePekZoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla($model));

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePreTypZaznamuPouzivatel(Zaznam $model): array
    {
        $out = [
            'zoznamPoctuKontrolSObratom' => [],
            'zoznamPoctuKontrolPodlaDruhu' => [],
            'zoznamPoctuKontrolPodlaStavu' => [],
            'zoznamPoctuKontrolPodlaHodnotenia' => [],
            'zoznamPoctuKontrolPodlaKategorieVozidla' => [],
            'zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla' => [],
        ];
        $out = array_merge($out, $this->transformUdajeTekZoznamPoctuKontrolSObratom($model));
        $out = array_merge($out, $this->transformUdajeTekZoznamPoctuKontrolPodlaDruhu($model));
        $out = array_merge($out, $this->transformUdajeTekZoznamPoctuKontrolPodlaStavu($model));
        $out = array_merge($out, $this->transformUdajeTekZoznamPoctuKontrolPodlaHodnotenia($model));
        $out = array_merge($out, $this->transformUdajeTekZoznamPoctuKontrolPodlaKategorieVozidla($model));
        $out = array_merge($out, $this->transformUdajeTekZoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla($model));

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePekZoznamPoctuKontrolPodlaDruhuAHodnotenia(Zaznam $model): array
    {
        foreach (DruhEmisnejKontrolyEnum::toArray() as $k => $v) {
            $out['zoznamPoctuKontrolPodlaDruhuAHodnotenia'][] = [
                'druh' => $k,
                'label' => $v,
                'data' => $this->addStructure(),
            ];
        }

        foreach ($model->udaje->zoznamPoctuKontrolPodlaDruhuAHodnotenia() as $item) {
            foreach ($out['zoznamPoctuKontrolPodlaDruhuAHodnotenia'] as &$druh) {
                if ($druh['druh'] === $item->druh()->value) {
                    if (empty($druh['data']) || is_array($druh['data'])) {
                        $druh['data'] = new PocetKontrolPodlaDruhuAHodnoteniaDataTableRow($item);
                    } else {
                        $druh['data']->add($item);
                    }
                }
            }
        }

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePekZoznamPoctuKontrolPodlaKategorieVozidla(Zaznam $model): array
    {
        $out['zoznamPoctuKontrolPodlaKategorieVozidla'] = [];

        /** @var \Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\PocetKontrolPodlaKategorieVozidla $item */
        foreach ($model->udaje->zoznamPoctuKontrolPodlaKategorieVozidla() as $item) {
            $out['zoznamPoctuKontrolPodlaKategorieVozidla'][] = [
                'label' => $item->kategoria(),
                'data' => [
                    'pocet' => $item->pocet(),
                ],
            ];
        }

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePekZoznamPoctuKontrolAObratuPodlaSubjektuFakturacie(Zaznam $model): array
    {
        $out['zoznamPoctuKontrolAObratuPodlaSubjektuFakturacie'] = [];

        /** @var \Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\PocetKontrolPodlaObratuASubjektuFakturacie $item */
        foreach ($model->udaje->zoznamPoctuKontrolAObratuPodlaSubjektuFakturacie() as $item) {
            $out['zoznamPoctuKontrolAObratuPodlaSubjektuFakturacie'][] = [
                'label' => $item->nazovSubjektu(),
                'data' => [
                    'pocet' => $item->pocet(),
                    'obrat' => $item->obrat(),
                ],
            ];
        }

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePekZoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla(Zaznam $model)
    {
        $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla'] = [];

        /** @var \Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\PocetKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla $item */
        foreach ($model->udaje->zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla() as $item) {
            $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla'][] = [
                'label' => sprintf('%s/%s', $item->druhPaliva()->label, $item->emisnySystem()->label),
                'data' => [
                    'pocet' => $item->pocet(),
                ],
            ];
        }

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajePekZoznamPoctuKontrolPodlaStavu(Zaznam $model): array
    {
        $out['zoznamPoctuKontrolPodlaStavu'] = [];

        /** @var \Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\PocetKontrolPodlaStavu $item */
        foreach ($model->udaje->zoznamPoctuKontrolPodlaStavu() as $item) {
            $out['zoznamPoctuKontrolPodlaStavu'][] = [
                'label' => ucfirst($item->stav()->label),
                'data' => [
                    'pocet' => $item->pocet(),
                ],
            ];
        }

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajeTekZoznamPoctuKontrolSObratom(Zaznam $model): array
    {
        $out['zoznamPoctuKontrolSObratom'] = [
            'stlpce' => [],
            'udaje' => [],
        ];

        foreach ($model->udaje->zoznamPoctuKontrolSObratom() as $item) {
            $out['zoznamPoctuKontrolSObratom']['stlpce'] = [
                [
                    'title' => 'Technik',
                    'data' => 'technik',
                ],
                [
                    'title' => 'Počet',
                    'data' => 'pocet',
                ],
                [
                    'title' => 'Obrat',
                    'data' => 'obrat',
                ],
            ];
            $out['zoznamPoctuKontrolSObratom']['udaje'][0]['technik'] = $model->subjekt->nazov();
            $out['zoznamPoctuKontrolSObratom']['udaje'][0]['pocet'] = $item->pocet();
            $out['zoznamPoctuKontrolSObratom']['udaje'][0]['obrat'] = $item->obrat();
        }

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajeTekZoznamPoctuKontrolPodlaDruhu(Zaznam $model): array
    {
        $spolu = 0;
        $out['zoznamPoctuKontrolPodlaDruhu'] = [
            'stlpce' => [
                [
                    'title' => 'Technik',
                    'data' => 'technik',
                ],
            ],
            'udaje' => [],
        ];

        foreach (DruhEmisnejKontrolyEnum::toArray() as $value => $label) {
            $out['zoznamPoctuKontrolPodlaDruhu']['stlpce'][] = [
                'title' => ucfirst($label),
                'data' => mb_strtolower($value),
            ];

            $out['zoznamPoctuKontrolPodlaDruhu']['udaje'][0][mb_strtolower($value)] = 0;
        }

        foreach ($model->udaje->zoznamPoctuKontrolPodlaDruhu() as $item) {
            $out['zoznamPoctuKontrolPodlaDruhu']['stlpce'][] = [
                'title' => ucfirst($item->druh()->label),
                'data' => mb_strtolower($item->druh()->value),
            ];
            $out['zoznamPoctuKontrolPodlaDruhu']['udaje'][0]['technik'] = $model->subjekt->nazov();
            $out['zoznamPoctuKontrolPodlaDruhu']['udaje'][0][mb_strtolower($item->druh()->value)] = $item->pocet();
            $spolu += $item->pocet();
        }

        $out['zoznamPoctuKontrolPodlaDruhu']['stlpce'][] = ['title' => 'Spolu', 'data' => 'spolu'];
        $out['zoznamPoctuKontrolPodlaDruhu']['udaje'][0]['spolu'] = $spolu;

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajeTekZoznamPoctuKontrolPodlaStavu(Zaznam $model): array
    {
        $spolu = 0;
        $out['zoznamPoctuKontrolPodlaStavu'] = [
            'stlpce' => [
                [
                    'title' => 'Technik',
                    'data' => 'technik',
                ],
            ],
            'udaje' => [],
        ];

        foreach (StavEmisnejKontrolyEnum::toArray() as $value => $label) {
            $out['zoznamPoctuKontrolPodlaStavu']['stlpce'][] = [
                'title' => ucfirst($label),
                'data' => mb_strtolower($value),
            ];

            $out['zoznamPoctuKontrolPodlaStavu']['udaje'][0][mb_strtolower($value)] = 0;
        }

        foreach ($model->udaje->zoznamPoctuKontrolPodlaStavu() as $item) {
            $out['zoznamPoctuKontrolPodlaStavu']['stlpce'][] = [
                'title' => ucfirst($item->stav()->label),
                'data' => mb_strtolower($item->stav()->value),
            ];
            $out['zoznamPoctuKontrolPodlaStavu']['udaje'][0]['technik'] = $model->subjekt->nazov();
            $out['zoznamPoctuKontrolPodlaStavu']['udaje'][0][mb_strtolower($item->stav()->value)] = $item->pocet();
            $spolu += $item->pocet();
        }

        $out['zoznamPoctuKontrolPodlaStavu']['stlpce'][] = ['title' => 'Spolu', 'data' => 'spolu'];
        $out['zoznamPoctuKontrolPodlaStavu']['udaje'][0]['spolu'] = $spolu;

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajeTekZoznamPoctuKontrolPodlaHodnotenia(Zaznam $model): array
    {
        $spolu = 0;
        $out['zoznamPoctuKontrolPodlaHodnotenia'] = [
            'stlpce' => [
                [
                    'title' => 'Technik',
                    'data' => 'technik',
                ],
            ],
            'udaje' => [],
        ];

        foreach (HodnotenieEmisnejKontrolyEnum::toArray() as $value => $label) {
            $out['zoznamPoctuKontrolPodlaHodnotenia']['stlpce'][] = [
                'title' => ucfirst($label),
                'data' => mb_strtolower($value),
            ];

            $out['zoznamPoctuKontrolPodlaHodnotenia']['udaje'][0][mb_strtolower($value)] = 0;
        }

        foreach ($model->udaje->zoznamPoctuKontrolPodlaHodnotenia() as $item) {
            $out['zoznamPoctuKontrolPodlaHodnotenia']['stlpce'][] = [
                'title' => ucfirst($item->hodnotenie()->label),
                'data' => mb_strtolower($item->hodnotenie()->value),
            ];
            $out['zoznamPoctuKontrolPodlaHodnotenia']['udaje'][0]['technik'] = $model->subjekt->nazov();
            $out['zoznamPoctuKontrolPodlaHodnotenia']['udaje'][0][mb_strtolower($item->hodnotenie()->value)] = $item->pocet();
            $spolu += $item->pocet();
        }

        $out['zoznamPoctuKontrolPodlaHodnotenia']['stlpce'][] = ['title' => 'Spolu', 'data' => 'spolu'];
        $out['zoznamPoctuKontrolPodlaHodnotenia']['udaje'][0]['spolu'] = $spolu;

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajeTekZoznamPoctuKontrolPodlaKategorieVozidla(Zaznam $model): array
    {
        $spolu = 0;
        $out['zoznamPoctuKontrolPodlaKategorieVozidla'] = [
            'stlpce' => [
                [
                    'title' => 'Technik',
                    'data' => 'technik',
                ],
            ],
            'udaje' => [],
        ];

        /** @var \Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\PocetKontrolPodlaKategorieVozidla $item */
        foreach ($model->udaje->zoznamPoctuKontrolPodlaKategorieVozidla() as $item) {
            $out['zoznamPoctuKontrolPodlaKategorieVozidla']['stlpce'][] = [
                'title' => $item->kategoria(),
                'data' => mb_strtolower($item->kategoria()),
                'defaultContent' => '0',
            ];
            $out['zoznamPoctuKontrolPodlaKategorieVozidla']['udaje'][0]['technik'] = $model->subjekt->nazov();
            $out['zoznamPoctuKontrolPodlaKategorieVozidla']['udaje'][0][mb_strtolower($item->kategoria())] = $item->pocet();
            $spolu += $item->pocet();
        }

        $out['zoznamPoctuKontrolPodlaKategorieVozidla']['stlpce'][] = ['title' => 'Spolu', 'data' => 'spolu'];
        $out['zoznamPoctuKontrolPodlaKategorieVozidla']['udaje'][0]['spolu'] = $spolu;

        return $out;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Zaznam\Zaznam $model
     *
     * @return array
     */
    private function transformUdajeTekZoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla(Zaznam $model)
    {
        $spolu = 0;

        $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla'] = [
            'stlpce' => [
                [
                    'title' => 'Technik',
                    'data' => 'technik',
                ],
            ],
            'udaje' => [],
        ];

        /** @var \Seka\Portal\Modul\Statistiky\Entities\Zaznam\ValueObjects\PocetKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla $item */
        foreach ($model->udaje->zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla() as $item) {
            $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla']['stlpce'][] = [
                'title' => mb_strtoupper(sprintf('%s/%s', $item->druhPaliva()->label, $item->emisnySystem()->label)),
                'data' => mb_strtoupper($item->druhPaliva()->value . '_' . $item->emisnySystem()->value),
                'defaultContent' => '0',
            ];
            $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla']['udaje'][0]['technik'] = $model->subjekt->nazov();
            $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla']['udaje'][0][mb_strtoupper($item->druhPaliva()->value . '_' . $item->emisnySystem()->value)] = $item->pocet();
            $spolu += $item->pocet();
        }

        $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla']['stlpce'][] = ['title' => 'Spolu', 'data' => 'spolu'];
        $out['zoznamPoctuKontrolPodlaDruhuPalivaAEmisnehoSystemuVozidla']['udaje'][0]['spolu'] = $spolu;

        return $out;
    }

    /**
     * @return array
     */
    private function addStructure()
    {
        $o = ['hodnotenia' => []];

        foreach (HodnotenieEmisnejKontrolyEnum::toValues() as $h) {
            $o['hodnotenia'][$h] = 0;
            $o['spolu'] = 0;
        }

        return $o;
    }
}
