<?php

namespace FiloBlu\Flow\Model\From;

use Exception;
use FiloBlu\Flow\Exception\BlockingException;
use FiloBlu\Flow\Exception\NonBlockingException;
use FiloBlu\Flow\Helper\Data;
use FiloBlu\Flow\Model\Processor;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ProductMetadataInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\ObjectManagerInterface;
use Magento\Framework\Registry;
use Magento\Cms\Model\BlockFactory;

/**
 * Class Eavs
 * @package FiloBlu\Flow\Model\From
 */
class Sizeguide extends AbstractFrom
{
    /**
     * @var ScopeConfigInterface|null
     */
    protected $_scopeConfig;
    /**
     * @var ProductMetadataInterface
     */
    protected $_productMetadata;
    /**
     * @var ObjectManagerInterface
     */
    protected $objectManager;
    /**
     * @var Data
     */
    protected $helper_flow;
    /**
     * @var ResourceConnection
     */
    protected $resourceConnection;
    /**
     * @var BlockFactory
     */
    private $blockFactory;

    private $tableRows = [];

    private $inboundFile;

    /**
     * Eavs constructor.
     * @param ScopeConfigInterface $scopeConfig
     * @param Context $context
     * @param Registry $registry
     * @param Data $helperFlow
     * @param ObjectManagerInterface $objectManager
     * @param ProductMetadataInterface $productMetadata
     * @param ResourceConnection $resourceConnection
     * @param AbstractResource|null $resource
     * @param AbstractDb|null $resourceCollection
     * @param array $data
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        Context $context,
        Registry $registry,
        Data $helperFlow,
        ObjectManagerInterface $objectManager,
        ProductMetadataInterface $productMetadata,
        ResourceConnection $resourceConnection,
        AbstractResource $resource = null,
        AbstractDb $resourceCollection = null,
        BlockFactory $blockFactory,

        array $data = []
    ) {
        $this->helper_flow = $helperFlow;

        $this->_scopeConfig = $scopeConfig;
        $this->_productMetadata = $productMetadata;
        $this->objectManager = $objectManager;
        $this->resourceConnection = $resourceConnection;
        $this->blockFactory = $blockFactory;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    /**
     * @return void
     */
    public function _construct()
    {
        $this->_init(\FiloBlu\Flow\Model\ResourceModel\From\Sizeguide::class, 'meta_id');
    }

    public function processFileRows($file)
    {
        $this->inboundFile = $file;
        $fileId = $file->getId();
        $connection = $this->resourceConnection->getConnection();
        $errorCount = 0;

        $rows = $this->getCollection()
            ->addFieldToFilter('meta_file', $fileId)
            ->addFieldToFilter('meta_processed', 0)
            ->setOrder('row_number,meta_id', 'ASC');

        if(count($rows) > 0 ) {
            foreach ($rows as $sizeguideRows => $sizeguideRow) {

                if($sizeguideRow->getRowNumber() == 0) {
                    $this->tableRows['header'][] = $sizeguideRow->getRow();
                }
                else {
                    $this->tableRows[$sizeguideRow->getRowNumber()][] = $sizeguideRow->getRow();
                }
            }

            try {
                $status = $this->process();
            } catch (BlockingException $blockingException) {
                $status = Processor::META_PROCESSED_ERROR;
                throw new RuntimeException(
                    "processing error : {$blockingException->getMessage()}"
                );
            } catch (NonBlockingException $nonBlockingException) {
                $status = Processor::META_PROCESSED_ERROR;
                $this->_logger->error("FLOW: processing error : {$nonBlockingException->getMessage()}");
                $this->appendErrorMessage(
                    "processing error : {$nonBlockingException->getMessage()}"
                );
                $errorCount++;
            } catch (Exception $e) {
                $this->_logger->error("FLOW: processing error :{$e->getMessage()}");
                $this->appendErrorMessage("processing error : {$e->getMessage()}");
                $status = Processor::META_PROCESSED_ERROR;
            } finally {
                $now = date('Y-m-d H:i:s');
                $sizeguideTable = $this->getResource()->getMainTable();
                $connection->update(
                    $sizeguideTable,
                    [
                        'meta_processed' => $status,
                        "meta_process_time" => $now
                    ],
                    "meta_file = ".$file->getId()
                );

                $inboundTable = $file->getResource()->getMainTable();
                $connection->update(
                    $inboundTable,
                    [
                        'last_activity' => $now,
                        'errors' => $errorCount
                    ],
                    "id = ".$file->getId()
                );
            }
        }

        $file->setErrorCount($errorCount);
        $this->postProcess($file);

        // Al termine della fase process dell'import vengono inviate eventuali notifiche di errore via email
        $this->sendErrorNotifications($file);

        if ($errorCount > 0) {
            throw new RuntimeException("Encountered $errorCount errors while processing flow");
        }

        return $file;
    }

    /**
     * @return $this|bool|mixed
     * @throws Exception
     */
    public function process()
    {
        $channelConfig = $this->getChannel()->getChannelConfig()->_mappedData['config'];
        $styleContainerPlaceholder = $channelConfig['sizeguide_stylecontainer_placeholder'];
        $styleContainer = $channelConfig['sizeguide_style_container'];
        $tableTitlePlaceholder = $channelConfig['sizeguide_title_placeholder'];
        $tableTitle = $channelConfig['sizeguide_title'];
        $tableStylePlaceholder = $channelConfig['sizeguide_styletable_placeholder'];
        $tableStyle = $channelConfig['sizeguide_style_table'];
        $tableRowsPlaceholder = $channelConfig['sizeguide_rows_placeholder'];
        $tableBody = $channelConfig['sizeguide_html'];

        $tableRowsHtml = '';
        $counterRow = 1;
        foreach ($this->tableRows as $rowNumber => $rows) {
            if($rowNumber == 'header') {
                $styleRow = $channelConfig['sizeguide_style_row_header'];
            }
            else {
                $styleRow = $channelConfig['sizeguide_style_odd_rows'];
                if($rowNumber != 'header' && $rowNumber %2 == 0)
                    $styleRow = $channelConfig['sizeguide_style_even_rows'];
            }

            $tableRowsHtml .= '<tr '.$styleRow.'>';

            foreach($rows as $rowIndex => $row) {
                $tableRowsHtml .= $row;
                if(!next($rows)) {
                    $tableRowsHtml .= '</tr>';
                }
            }
            $counterRow++;
        }

        $fullTable = str_replace([$styleContainerPlaceholder,$tableTitlePlaceholder,$tableStylePlaceholder,$tableRowsPlaceholder],[$styleContainer,$tableTitle,$tableStyle,$tableRowsHtml],$tableBody);
        $filename_info = pathinfo($this->inboundFile->getName());
        $blockName = $filename_info['filename'];

        $cmsBlockData = [
            'title' => $blockName,
            'identifier' => $blockName,
            'content' => $fullTable,
            'is_active' => 1,
            'stores' => \Magento\Store\Model\Store::DEFAULT_STORE_ID,
            'sort_order' => 0
        ];

        try {
            $cmsBlock = $this->blockFactory->create()->load($blockName, 'identifier');
            if (!$cmsBlock->getId()) {
                $this->blockFactory->create()->setData($cmsBlockData)->save();
            } else {
                $cmsBlock->setContent($cmsBlockData['content'])->save();
            }
        }
        catch (Exception $e) {
            $this->_logger->error("Flow Size Guide Exception: ".$e->getMessage());
            $this->appendErrorMessage("Flow Size Guide Exception: ".$e->getMessage());
            return Processor::META_PROCESSED_ERROR;
        }

        return Processor::META_PROCESSED_SUCCESS;
    }

    /**
     * @param $file
     * @return bool|mixed
     */
    public function sendErrorNotifications($file)
    {
        return true;
    }
}
