<?php
/**
 * For the full copyright and license information, please view the
 * docs/licenses/LICENSE.txt file that was distributed with this source code.
 */

namespace PrestaShop\PrestaShop\Core\Import\File;

use PrestaShop\PrestaShop\Core\Import\ImportDirectory;
use PrestaShopBundle\Exception\FileUploadException;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Contracts\Translation\TranslatorInterface;

/**
 * FileUploader is responsible for uploading import files to import directory.
 */
final class FileUploader
{
    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var ImportDirectory
     */
    private $importDirectory;

    /**
     * @param TranslatorInterface $translator
     * @param ImportDirectory $importDirectory
     */
    public function __construct(
        TranslatorInterface $translator,
        ImportDirectory $importDirectory
    ) {
        $this->translator = $translator;
        $this->importDirectory = $importDirectory;
    }

    /**
     * Handle import file uploading to admin import/ directory.
     *
     * @param UploadedFile $uploadedFile
     *
     * @return File
     *
     * @throws FileUploadException
     */
    public function upload(UploadedFile $uploadedFile)
    {
        if ($error = $this->validateUploadedFile($uploadedFile)) {
            throw new FileUploadException($error);
        }

        $uploadedFileName = sprintf(
            '%s-%s',
            date('YmdHis'),
            $uploadedFile->getClientOriginalName()
        );

        try {
            $file = $uploadedFile->move(
                $this->importDirectory,
                $uploadedFileName
            );
        } catch (FileException) {
            $error = $this->translator->trans('An error occurred while uploading / copying the file.', [], 'Admin.Advparameters.Notification');

            throw new FileUploadException($error);
        }

        return $file;
    }

    /**
     * Check if uploaded file is valid.
     *
     * @param UploadedFile $uploadedFile
     *
     * @return string|false Returns error string on error or FALSE otherwise
     */
    protected function validateUploadedFile(UploadedFile $uploadedFile)
    {
        $error = false;

        switch ($uploadedFile->getError()) {
            case UPLOAD_ERR_INI_SIZE:
                $error = $this->translator->trans('The uploaded file exceeds the upload_max_filesize directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess.', [], 'Admin.Advparameters.Notification');

                break;
            case UPLOAD_ERR_FORM_SIZE:
                $message = $this->translator->trans('The uploaded file exceeds the post_max_size directive in php.ini. If your server configuration allows it, you may add a directive in your .htaccess, for example:', [], 'Admin.Advparameters.Notification');
                $error = sprintf('%s %s', $message, 'php_value post_max_size 20M');

                break;
            case UPLOAD_ERR_PARTIAL:
                $error = $this->translator->trans('The uploaded file was only partially uploaded.', [], 'Admin.Advparameters.Notification');

                break;
            case UPLOAD_ERR_NO_FILE:
                $error = $this->translator->trans('No file was uploaded.', [], 'Admin.Advparameters.Notification');

                break;
        }

        if ($error) {
            return $error;
        }

        if (!preg_match('#([^\.]*?)\.(csv|xls[xt]?|o[dt]s)$#is', $uploadedFile->getClientOriginalName())) {
            $error = $this->translator->trans('The extension of your file should be ".csv".', [], 'Admin.Advparameters.Notification');
        }

        return $error;
    }
}
