<?php

declare(strict_types=1);

namespace Seka\Portal\Modul\Statistiky\Console;

use Carbon\Carbon;
use Exception;
use Illuminate\Console\Command;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use InvalidArgumentException;
use Seka\Portal\Modul\Statistiky\Entities\Import\Enums\StavEnum;
use Seka\Portal\Modul\Statistiky\Entities\Import\Import;
use Seka\Portal\Modul\Statistiky\Entities\Import\ValueObjects\Subor;
use Seka\Portal\Modul\Statistiky\Services\Import\File;
use Seka\Portal\Modul\Statistiky\Services\Import\ImportDataServiceContract;

/**
 * Class ImportZaznamovCommand
 *
 * @package Seka\Portal\Modul\Statistiky\Console
 */
final class ImportZaznamovCommand extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'statistiky:import 
    {cesta : Cesta k umiestneniu suborov alebo jedneho suboru pre import} 
    {presunutdo? : Cesta pre presunutie naimportovaneho suboru} 
    {--pocet=5 : Pocet suborov, ktore budu importovane, bez spacifikacie budu importovane vsetky subory} 
    {--typ=xlsx : Typ suborov pre import, moze byt xlsx alebo csv}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Import statistik technikov a pracovisk emisnych kontrol';

    /**
     * @var \Illuminate\Support\Collection
     */
    protected Collection $zoznam;

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

    /**
     * @param \Seka\Portal\Modul\Statistiky\Services\Import\ImportDataServiceContract $importService
     *
     * @return int
     */
    public function handle(ImportDataServiceContract $importService): int
    {
        $kamPresunut = '';

        try {
            $subory = new Collection();
            $cesta = base_path($this->argument('cesta'));
            $presunutSuborPoImporte = (bool)$this->argument('presunutdo');
            $kamPresunut = base_path($this->argument('presunutdo'));
            $pocetSuborovPreImport = (int)$this->option('pocet') ?? 100;
            $typSuboruPreimport = mb_strtolower($this->option('typ') ?? 'xlsx');

            if (File::isFile($cesta)) {
                $subory->add(new File($cesta));
            }

            if (File::isDir($cesta)) {
                $subory = $subory->merge(
                    array_map(
                        function ($fileName) use ($cesta) {
                            return new File($cesta . DIRECTORY_SEPARATOR . $fileName);
                        },
                        array_filter(
                            array_diff(scandir($cesta, SCANDIR_SORT_ASCENDING), ['.', '..']),
                            function ($f) use ($typSuboruPreimport) {
                                if ($typSuboruPreimport === mb_strtolower(pathinfo($f, PATHINFO_EXTENSION))) {
                                    return true;
                                }

                                return false;
                            }
                        )
                    )
                );
            }

            if ($subory->isEmpty()) {
                throw new InvalidArgumentException('Neboli najdene ziadne subory pre importovanie!');
            }

            if ($presunutSuborPoImporte && !File::isDir($kamPresunut)) {
                throw new InvalidArgumentException(
                    'Adresar pre presunutie importovanych suborov nie je adresarom alebo neexistuje!'
                );
            }
        } catch (Exception $e) {
            $this->output->newLine(2);
            $this->output->error($e->getMessage());
            Log::error($sprava = 'Chyba pri importe udajov zo suboru.', $e->getTrace());

            $this->createImportLog(
                StavEnum::NEUSPESNY,
                new Subor('žiadny súbor', '-', $kamPresunut, 0),
                $sprava
            );

            return 0;
        }

        /** @var \Seka\Portal\Modul\Statistiky\Services\Import\File $subor */
        foreach ($subory->filter(function ($s) {
            return !File::isEmpty($s->fileName());
        })->take($pocetSuborovPreImport) as $subor) {
            $suborImport = new Subor($subor->name(), $subor->path(), $kamPresunut, $subor->size());

            if (File::isEmpty($subor->fileName())) {
                $this->createImportLog(
                    StavEnum::PRERUSENY,
                    $suborImport,
                    sprintf('Subor "%s" neobsahuje ziadny obsah.', $subor->name())
                );

                continue;
            }

            try {
                $subor->check();
            } catch (InvalidArgumentException $e) {
                $sprava = sprintf('Subor "%s" neexistuje alebo neobsahuje ziadne udaje.', $subor->name());

                $this->createImportLog(StavEnum::NEUSPESNY, $suborImport, $sprava);

                Log::alert($sprava, $e->getTrace());

                continue;
            }

            $this->line(sprintf('Zaciatok importu zo suboru "%s"...', $subor->name()));

            try {
                $importService->execute($subor);

                if ($presunutSuborPoImporte) {
                    $subor->move($kamPresunut);
                }

                $this->output->newLine(2);
                $this->output->success('Import prebehol uspesne!');

                $sprava = sprintf('Udaje zo suboru "%s" boli naimportovane.', $subor->name());
                $this->createImportLog(StavEnum::DOKONCENY, $suborImport, $sprava);

                Log::info($sprava);
            } catch (Exception $e) {
                $sprava = sprintf('Udaje zo suboru "%s" neboli naimportovane.', $subor->name());
                $this->createImportLog(StavEnum::NEUSPESNY, $suborImport, $sprava);

                Log::alert($sprava, $e->getTrace());

                $this->output->newLine(2);
                $this->output->error(['Import nebol uspesny!', $sprava, json_encode($e->getTrace())]);

                continue;
            }
        }

        return 1;
    }

    /**
     * @param \Seka\Portal\Modul\Statistiky\Entities\Import\Enums\StavEnum          $stav
     * @param \Seka\Portal\Modul\Statistiky\Entities\Import\ValueObjects\Subor|null $subor
     * @param string|null                                                           $sprava
     */
    private function createImportLog(StavEnum $stav, ?Subor $subor, ?string $sprava)
    {
        $import = new Import();
        $import->stav = $stav;
        $import->subor = $subor;
        $import->sprava = $sprava;
        $import->datum_cas_akcie = Carbon::now();
        $import->save();
    }
}
