<?php

declare(strict_types=1);

namespace External\PompoBundle\Util\AutomaticImport\KnizniWeb;

use External\PompoBundle\Exception\PompoException;
use KupShop\AdminBundle\Util\ActivityLog;
use KupShop\KupShopBundle\Util\FileUtil;
use KupShop\KupShopBundle\Util\System\PathFinder;

class KnizniWebUtil
{
    public function __construct(
        private KnizniWebAPI $api,
        private PathFinder $pathFinder,
        private ActivityLog $activityLog,
    ) {
    }

    public function requestNewFeed(KnizniWebTypeEnum $type): ?string
    {
        $dbcfg = \Settings::getDefault();

        $result = $this->api->requestNewFeed($type);

        $this->addActivityLog('Byla odeslána žádost o nový feed: '.$type->name, [
            'type' => $type->value,
            'result' => $result,
        ]);

        // ulozim si token pro dalsi feed
        if (!empty($result['token'])) {
            $config = $dbcfg->loadValue('knizniweb') ?: [];
            $config['tokens'][$type->value] = $result['token'];

            $dbcfg->saveValue('knizniweb', $config, false);
        }

        return !empty($result['token']) ? $result['token'] : null;
    }

    public function getFeedFile(KnizniWebTypeEnum $type, string $token, bool $withNewFeedRequest = true): ?string
    {
        $delay = false;

        if ($withNewFeedRequest) {
            $token = $this->requestNewFeed($type);
            $delay = true;
        }

        try {
            $file = $this->api->getFeedZipFile($token);
        } catch (PompoException $e) {
            if ($e->getCode() == '403' || $e->getCode() == '410') {
                return null;
            } else {
                throw $e;
            }
        }

        if (!$file || ($file['status'] ?? null) != 200) {
            $delay = true;
        }

        if ($delay) {
            $this->addActivityLog('Čekám na vygenerování XML: '.$type->name, [
                'type' => $type->value,
                'token' => $token,
            ]);

            $try = 1;
            do {
                sleep(60);
                $file = $this->api->getFeedZipFile($token);
            } while ($try++ < 6);

            $this->addActivityLog('Vygenerované XML - '.($file ? 'success' : 'timeout').': '.$type->name, [
                'type' => $type->value,
                'token' => $token,
                'file' => $file,
            ]);
        }

        $this->addActivityLog('Byly získány infromace o vygenerovaném feedu: '.$type->name, [
            'type' => $type->value,
            'token' => $token,
            'file' => $file,
        ]);

        if (empty($file['url'])) {
            return null;
        }

        $this->addActivityLog('Stahuji feed pro import: '.$type->name.' - '.$file['url']);

        $result = $this->zipDownloadAndUnzip($file['url'], $this->getFeedFolder($token))[0] ?? null;

        $this->addActivityLog('Byl stažen feed pro import: '.$type->name.' - '.$file['url'], [
            'result' => $result,
        ]);

        return $result;
    }

    public function cleanup(): array
    {
        $freshCache = [];

        foreach (scandir($this->pathFinder->getTmpDir()) as $file) {
            if (!str_starts_with($file, 'knizniweb')) {
                continue;
            }

            $filePath = $this->pathFinder->tmpPath($file);

            // pokud je to jeste fresh
            if ((time() - filemtime($filePath)) <= 1800) {
                $token = str_replace('knizniweb_', '', $file);

                $xmlFile = array_values(array_map(
                    fn ($x) => rtrim($filePath, '/').'/'.$x,
                    array_filter(scandir($filePath), fn ($x) => !empty($x) && !in_array($x, ['.', '..']))
                ));

                $freshCache[$token] = $xmlFile[0] ?? false;

                continue;
            }

            FileUtil::deleteDir($filePath);
        }

        return $freshCache;
    }

    private function getFeedFolder(string $token): string
    {
        return $this->pathFinder->tmpPath("knizniweb_{$token}");
    }

    private function zipDownloadAndUnzip(string $url, string $destination): array
    {
        $downloader = new \Downloader();
        $downloader->setMethod('curl');

        $tmpZip = $this->pathFinder->tmpPath('knizniweb.zip');

        // stahnu zip soubor
        $downloader->copyRemoteFile($url, $tmpZip);

        if (!file_exists($destination)) {
            mkdir($destination);
        }

        // unzipnu soubor do slozky
        $files = FileUtil::unzip($tmpZip, $destination);

        // smazu zip
        unlink($tmpZip);

        // vratim obsah slozky, kam jsem rozbalil zip
        return $files;
    }

    private function addActivityLog(string $message, array $data = [], string $severity = ActivityLog::SEVERITY_NOTICE): void
    {
        $this->activityLog->addActivityLog(
            $severity,
            ActivityLog::TYPE_IMPORT,
            'KnizniWeb: '.$message,
            $data
        );
    }
}
