<?php

namespace Leadlion\Autogedal\Observer;

use AllowDynamicProperties;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Event\Observer;
use Magento\CatalogImportExport\Model\Import\Product as ImportProduct;
use Magento\Framework\Filesystem\DirectoryList;
use Magento\Framework\App\ObjectManager;
use finfo;
use Magento\Framework\App\Filesystem\DirectoryList as DiList;

#[AllowDynamicProperties] class ImportPdfAttachments implements ObserverInterface
{
    const URL_KEY_ATTRIBUTE_CODE = 'url_key';
    const PDF_ATTACHMENT = 'pdf_attachment';
    const ATTACHMENTS_PATH = 'mageplaza/product_attachments/attachment_file';

    /**
     * @var array
     */
    protected $import;

    /**
     * @var DirectoryList
     */
    protected $directoryList;
    protected $mageplazaHelper;
    protected $uploader;
    protected $_fileUploader;
    protected $_mediaDirectory;

    /**
     * AfterImportDataObserver constructor.
     * @param DirectoryList $directoryList
     */
    public function __construct(
        DirectoryList $directoryList,
        \Mageplaza\ProductAttachments\Helper\Data $mageplazaHelper,
        \Magento\Framework\App\ResourceConnection $resource,
        \Leadlion\Autogedal\Model\Pdf\UploaderFactory $uploader,
        \Magento\Framework\Filesystem $filesystem
    ) {
        $this->uploader = $uploader;
        $this->directoryList = $directoryList;
        $this->mageplazaHelper = $mageplazaHelper;
        $this->resource = $resource;
        $this->_mediaDirectory = $filesystem->getDirectoryWrite(DiList::ROOT);
    }

    /**
     * @param Observer $observer
     */
    public function execute(Observer $observer)
    {
        try {
            $connection = $this->resource->getConnection();
            $attachmentsTable = $this->resource->getTableName('mageplaza_productattachments_file');
            $attachmentsProdsTable = $this->resource->getTableName('mageplaza_productattachments_file_product');
            $this->import = $observer->getEvent()->getAdapter();

            if ($products = $observer->getEvent()->getBunch()) {
                $products = $this->prepareProducts($products);
                foreach ($products as $product) {
                    if (isset($product[self::PDF_ATTACHMENT]) &&
                        $product[self::PDF_ATTACHMENT]
                    ) {
                        $fileName = trim($product[self::PDF_ATTACHMENT]);
                        $res = $this->_getUploader()->move($fileName, true);
                        if (isset($res['name'])) {
                            $filename = $res['name'];
                            $select = $connection->select();
                            $select->from(
                                ['e' => $attachmentsTable],
                                ['file_id', 'name']
                            )->where(
                                'e.name = ?',
                                $filename
                            );
                            $rowExist = $connection->fetchAll($select);
                            if (empty($rowExist)) {
                                $conditions = [
                                    'type' => Magento\CatalogRule\Model\Rule\Condition\Combine::class,
                                    'aggregator' => 'all',
                                    'value' => '1',
                                    'new_child' => ''
                                ];
                                $label = pathinfo($filename, PATHINFO_FILENAME);

                                $m2PdfInfo = [
                                    'label' => $label,
                                    'name' => $filename,
                                    'status' => 1,
                                    'store_ids' => 0,
                                    'customer_group' => '0,1,2,3,4',
                                    'size' => $res['size'],
                                    'file_path' => $filename,
                                    'file_icon_path' => null,
                                    'customer_login' => 0,
                                    'is_buyer' => 0,
                                    'file_action' => 1,
                                    'priority' => 99,
                                    'position' => 1,
                                    'is_grid' => 0,
                                    'conditions_serialized' => $this->mageplazaHelper->serialize($conditions)
                                ];

                                $connection->insertOnDuplicate($attachmentsTable, $m2PdfInfo);
                                $lastInsertedId = $connection->lastInsertId($attachmentsTable);
        
                                $connection->insertOnDuplicate(
                                    $attachmentsProdsTable,
                                    [
                                        'entity_id' => $product['entity_id'],
                                        'file_id' => $lastInsertedId
                                    ]
                                );
                                $this->addLogWriteln(__('PDF attachment imported for product %1', $product[ImportProduct::COL_SKU]), 'info');
                            } elseif (isset($rowExist[0])) {
                                $connection->insertOnDuplicate(
                                    $attachmentsProdsTable,
                                    [
                                        'entity_id' => $product['entity_id'],
                                        'file_id' => $rowExist[0]['file_id']
                                    ]
                                );
                                $this->addLogWriteln(__('PDF attachment imported for product %1', $product[ImportProduct::COL_SKU]), 'info');
                            }
                        }
                    }
                }
            }
        } catch (\Exception $e) {
            $this->addLogWriteln($e->getMessage(), 'error');
        }
    }

    protected function _getUploader()
    {
        if ($this->_fileUploader === null) {
            $this->_fileUploader = $this->uploader->create();

            $this->_fileUploader->init();

            $dirConfig = DiList::getDefaultConfig();
            $dirAddon = $dirConfig[DiList::MEDIA][DiList::PATH];

            $tmpPath = $dirAddon . '/' . $this->_mediaDirectory->getRelativePath('import');

            if (!$this->_fileUploader->setTmpDir($tmpPath)) {
                throw new LocalizedException(
                    __('File directory \'%1\' is not readable.', $tmpPath)
                );
            }
            $destinationDir = self::ATTACHMENTS_PATH;
            $destinationPath = $dirAddon . '/' . $this->_mediaDirectory->getRelativePath($destinationDir);

            $this->_mediaDirectory->create($destinationPath);
            if (!$this->_fileUploader->setDestDir($destinationPath)) {
                throw new LocalizedException(
                    __('File directory \'%1\' is not writable.', $destinationPath)
                );
            }
        }
        return $this->_fileUploader;
    }

    /**
     * @param array $rowData
     * @return array|null
     */
    private function getProductId(array $rowData)
    {
        $newSku = $this->import->getNewSku($rowData[ImportProduct::COL_SKU]);
        if (empty($newSku) || !isset($newSku['entity_id'])) {
            return null;
        }
        if ($this->import->getRowScope($rowData) == ImportProduct::SCOPE_STORE
            && empty($rowData[self::URL_KEY_ATTRIBUTE_CODE])) {
            return null;
        }
        $rowData['entity_id'] = $newSku['entity_id'];
        return $rowData['entity_id'];
    }

    /**
     * @param $debugData
     * @param null $type
     */
    private function addLogWriteln($debugData, $type = null)
    {
        if (method_exists($this->import, 'addLogWriteln')
            && method_exists($this->import, 'getOutput')
        ) {
            $this->import->addLogWriteln(
                $debugData,
                $this->import->getOutput(),
                $type
            );
        }
    }

    /**
     * @param $rows
     * @return mixed
     */
    protected function prepareProducts($rows)
    {
        foreach ($rows as &$row) {
            $row['entity_id'] = $this->getProductId($row);
        }

        return $rows;
    }
}
