<?php
declare(strict_types=1);

namespace Autogedal\EanTools\Model;

use Magento\Framework\App\Filesystem\DirectoryList;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\File\UploaderFactory;
use Magento\Framework\Filesystem;
use Throwable;

class UploadHandler
{
    private const TMP_PATH = ResultStorage::BASE_PATH . '/_uploads';
    private const ALLOWED_EXTENSIONS = ['csv', 'txt', 'xlsx'];

    public function __construct(
        private readonly UploaderFactory $uploaderFactory,
        private readonly Filesystem $filesystem
    ) {
    }

    public function handle(string $fieldId, string $label): array
    {
        try {
            $uploader = $this->uploaderFactory->create(['fileId' => $fieldId]);
        } catch (Throwable) {
            throw new LocalizedException(__('No file was uploaded for "%1".', $label));
        }

        $uploader->setAllowedExtensions(self::ALLOWED_EXTENSIONS);
        $uploader->setAllowRenameFiles(true);
        $uploader->setFilesDispersion(false);
        $uploader->setAllowCreateFolders(true);

        $directory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);
        $directory->create(self::TMP_PATH);
        $absoluteTmp = $directory->getAbsolutePath(self::TMP_PATH);

        try {
            $result = $uploader->save($absoluteTmp);
        } catch (Throwable $e) {
            throw new LocalizedException(
                __('The "%1" file could not be uploaded: %2', $label, $e->getMessage())
            );
        }

        if (!isset($result['file'])) {
            throw new LocalizedException(__('The "%1" file could not be uploaded.', $label));
        }

        $savedName = (string)$result['file'];
        $originalName = isset($result['name']) ? (string)$result['name'] : '';

        return [
            'path' => $directory->getAbsolutePath(self::TMP_PATH . '/' . $savedName),
            'name' => $originalName !== '' ? $originalName : $savedName,
        ];
    }

    public function cleanup(array $paths): void
    {
        $directory = $this->filesystem->getDirectoryWrite(DirectoryList::VAR_DIR);

        foreach ($paths as $path) {
            try {
                $relative = $directory->getRelativePath($path);
                $isTemporaryFile = str_starts_with($relative, self::TMP_PATH . '/')
                    && $directory->isFile($relative);

                if ($isTemporaryFile) {
                    $directory->delete($relative);
                }
            } catch (Throwable) {
                continue;
            }
        }
    }
}
