<?php
/**
 * Mirasvit
 *
 * This source file is subject to the Mirasvit Software License, which is available at https://mirasvit.com/license/.
 * Do not edit or add to this file if you wish to upgrade the to newer versions in the future.
 * If you wish to customize this module for your needs.
 * Please refer to http://www.magentocommerce.com for more information.
 *
 * @category  Mirasvit
 * @package   mirasvit/module-rma
 * @version   2.0.61-beta7
 * @copyright Copyright (C) 2019 Mirasvit (https://mirasvit.com/)
 */


namespace Mirasvit\Rma\Service\Attachment;

use Magento\Framework\Exception\LocalizedException;

/**
 *  We put here only methods directly connected with Attachment properties
 */
class AttachmentManagement implements \Mirasvit\Rma\Api\Service\Attachment\AttachmentManagementInterface
{
    private $attachmentFactory;
    private $urlManager;
    private $searchCriteriaBuilder;
    private $request;
    private $attachmentRepository;
    private $config;

    public function __construct(
        \Mirasvit\Rma\Model\AttachmentFactory $attachmentFactory,
        \Magento\Framework\Url $urlManager,
        \Magento\Framework\Api\SearchCriteriaBuilder $searchCriteriaBuilder,
        \Magento\Framework\App\RequestInterface $request,
        \Mirasvit\Rma\Api\Repository\AttachmentRepositoryInterface $attachmentRepository,
        \Mirasvit\Rma\Api\Config\AttachmentConfigInterface $config
    ) {
        $this->attachmentFactory     = $attachmentFactory;
        $this->urlManager            = $urlManager;
        $this->searchCriteriaBuilder = $searchCriteriaBuilder;
        $this->request               = $request;
        $this->attachmentRepository  = $attachmentRepository;
        $this->config                = $config;
    }

    /**
     * {@inheritdoc}
     */
    public function getAttachmentsByMessage(\Mirasvit\Rma\Api\Data\MessageInterface $message)
    {
        $searchCriteria = $this->searchCriteriaBuilder
            ->addFilter('item_id', $message->getId())
            ->addFilter('item_type', 'message')
            ->create();

        return $this->attachmentRepository->getList($searchCriteria)->getItems();
    }

    /**
     * {@inheritdoc}
     */
    public function saveAttachments(
        $itemType,
        $itemId,
        $field = 'attachment'
    ) {
        /** @var \Zend\Stdlib\Parameters $filesData */
        $filesData = $this->request->getFiles();
        $allowedFileExtensions = $this->config->getFileAllowedExtensions();
        $fileSizeLimit = (float)$this->config->getFileSizeLimit() * 1024 * 1024;

        if (!$this->hasAttachments($field)) {
            return false;
        }
        $i = 0;
        $error = false;
        $files = $filesData->toArray();
        foreach ($files[$field] as $index => $fileInfo) {
            if ($fileInfo['name'] == '' || !empty($fileInfo['is_saved']) || UPLOAD_ERR_OK !== $fileInfo['error']) {
                $error = true;
                continue;
            }

            $type = $fileInfo['type'];
            $size = $fileInfo['size'];
            $ext  = pathinfo($fileInfo['name'], PATHINFO_EXTENSION);

            if (count($allowedFileExtensions) && !in_array(strtolower($ext), $allowedFileExtensions)) {
                $error = true;
                continue;
            }

            if ($fileSizeLimit && $size > $fileSizeLimit) {
                $error = true;
                continue;
            }

            $this->_saveFile($itemType, $itemId, $fileInfo['name'], $fileInfo['tmp_name'], $type, $size);
            ++$i;
            $fileInfo['is_saved'] = 1;
        }
        if ($error) {
            throw new LocalizedException(__('Error. Uploaded file does not match requirements.'));
        }

        return true;
    }

    /**
     * @param string $itemType
     * @param int    $itemId
     * @param string $name
     * @param string $tmpName
     * @param string $fileType
     * @param string $size
     * @param bool   $isReplace
     * @return void
     */
    protected function _saveFile($itemType, $itemId, $name, $tmpName, $fileType, $size, $isReplace = false)
    {
        /** @var \Mirasvit\Rma\Model\Attachment $attachment */
        $attachment = false;
        if ($isReplace) {
            $attachment = $this->getAttachment($itemType, $itemId);
        }

        if (!$attachment) {
            $attachment = $this->attachmentRepository->create();
        }
        set_error_handler(function() { /* ignore errors */ });
        //@tofix - need to check for max upload size and alert error
        $body = file_get_contents(addslashes($tmpName));
        restore_error_handler();

        $attachment
            ->setItemType($itemType)
            ->setItemId($itemId)
            ->setName($name)
            ->setSize($size)
            ->setBody($body)
            ->setType($fileType)
            ->save();

    }


    /**
     * {@inheritdoc}
     */
    public function saveAttachment($itemType, $itemId, $field = false)
    {
        if (!$this->hasAttachments($field)) {
            $fileData = $this->request->getParam($field);
            if (isset($fileData['delete']) && $fileData['delete']) {
                $attachment = $this->getAttachment($itemType, $itemId);
                $attachment->delete();

                return true;
            }

            return false;
        }
        /** @var \Zend\Stdlib\Parameters $filesData */
        $filesData = $this->request->getFiles();
        $files = $filesData->toArray();
        $this->_saveFile(
            $itemType,
            $itemId,
            $files[$field]['name'],
            $files[$field]['tmp_name'],
            $files[$field]['type'],
            $files[$field]['size'],
            true
        );

        return true;
    }

    /**
     * {@inheritdoc}
     */
    public function getAttachments($itemType, $itemId)
    {
        $searchCriteria = $this->searchCriteriaBuilder
            ->addFilter('item_id', $itemId)
            ->addFilter('item_type', $itemType)
            ->create();

        return $this->attachmentRepository->getList($searchCriteria)->getItems();
    }

    /**
     * {@inheritdoc}
     */
    public function hasAttachments($field = 'attachment')
    {
        /** @var \Zend\Stdlib\Parameters $filesData */
        $filesData = $this->request->getFiles();
        $files = $filesData->toArray();

        return !empty($files[$field]) && (!empty($files[$field]['name']) || !empty($files[$field][0]['name']));
    }

    /**
     * {@inheritdoc}
     */
    public function getAttachment($itemType, $itemId)
    {
        $items = $this->getAttachments($itemType, $itemId);

        return array_shift($items);
    }

    /**
     * {@inheritdoc}
     */
    public function getUrl($attachment)
    {
        return $this->urlManager->getUrl('rma/attachment/download', ['uid' => $attachment->getUid()]);
    }

    /**
     * @param \Mirasvit\Helpdesk\Api\Service\EmailInterface $email
     * @param \Mirasvit\Rma\Api\Data\MessageInterface       $message
     * @return void
     */
    public function copyEmailAttachments($email, $message)
    {
        foreach ($email->getAttachments() as $emailAttachment) {
            $this->attachmentFactory->create()
                ->setEntityId($message->getId())
                ->setEntityType('COMMENT')
                ->setName($emailAttachment->getName())
                ->setSize($emailAttachment->getSize())
                ->setBody($emailAttachment->getBody())
                ->setType($emailAttachment->getType())
                ->save();
        }
    }
}