<?php
declare(strict_types=1);

namespace Autogedal\BlackFriday\Model\Config\Backend;

use Autogedal\BlackFriday\Model\SkuList;
use Magento\Config\Model\Config\Backend\File\RequestData\RequestDataInterface;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Config\Value;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Filesystem\Driver\File as FileDriver;
use Magento\Framework\Message\ManagerInterface;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Registry;

/**
 * Upload of the Black Friday SKU list. The file is read right away into autogedal_blackfriday_sku and not kept;
 * the config value keeps only the file name and the import date.
 */
class SkuFile extends Value
{
    private const MAX_FILE_SIZE = 5 * 1024 * 1024;   // ~5 MB: far above 50.000 SKUs, protects the memory of the request

    public function __construct(
        Context $context,
        Registry $registry,
        ScopeConfigInterface $config,
        TypeListInterface $cacheTypeList,
        private readonly RequestDataInterface $requestData,
        private readonly SkuList $skuList,
        private readonly FileDriver $fileDriver,
        private readonly ManagerInterface $messageManager,
        ?AbstractResource $resource = null,
        ?AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
    }

    public function beforeSave()
    {
        $tmpName = $this->requestData->getTmpName($this->getPath());
        if (!$tmpName) {
            $this->setValue($this->getOldValue());   // nothing uploaded: the current list stays
            return parent::beforeSave();
        }
        $name = (string)$this->requestData->getName($this->getPath());
        if (!preg_match('/\.(csv|txt)$/i', $name)) {
            throw new LocalizedException(__('Fisierul trebuie sa fie CSV (o singura coloana cu SKU-uri).'));
        }

        $size = (int)($this->fileDriver->stat($tmpName)['size'] ?? 0);
        if ($size > self::MAX_FILE_SIZE) {
            throw new LocalizedException(__('Fisierul are %1 MB; limita este 5 MB. Lista nu a fost modificata.', round($size / 1048576, 1)));
        }
        $result = $this->skuList->importCsv((string)$this->fileDriver->fileGetContents($tmpName), $name);
        $message = __('Lista Black Friday a fost incarcata: %1 SKU-uri importate.', $result['imported']);
        if ($result['invalid']) {
            $message .= ' ' . __(
                '%1 randuri ignorate (mai lungi de %2 caractere): %3',
                count($result['invalid']),
                SkuList::MAX_SKU_LENGTH,
                implode(', ', array_slice($result['invalid'], 0, 10))
            );
        }
        if ($result['missing']) {
            $message .= ' ' . __(
                '%1 SKU-uri nu exista in catalog: %2%3',
                count($result['missing']),
                implode(', ', array_slice($result['missing'], 0, 30)),
                count($result['missing']) > 30 ? ' ...' : ''
            );
        }
        if ($result['missing'] || $result['invalid']) {
            $this->messageManager->addWarningMessage($message);
        } else {
            $this->messageManager->addSuccessMessage($message);
        }
        $this->setValue($name . ' (' . date('Y-m-d H:i') . ')');
        return parent::beforeSave();
    }
}
