<?php
/**
 * Mageplaza
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Mageplaza.com license that is
 * available through the world-wide-web at this URL:
 * https://www.mageplaza.com/LICENSE.txt
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade this extension to newer
 * version in the future.
 *
 * @category    Mageplaza
 * @package     Mageplaza_Faqs
 * @copyright   Copyright (c) Mageplaza (http://www.mageplaza.com/)
 * @license     https://www.mageplaza.com/LICENSE.txt
 */

namespace Mageplaza\Faqs\Model\Export;

use Exception;
use Magento\Framework\Data\Collection as DataCollection;
use Zend_Db_Expr;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Model\AbstractModel;
use Magento\ImportExport\Model\Export;
use Magento\ImportExport\Model\Export\AbstractEntity;
use Magento\ImportExport\Model\Export\Factory;
use Magento\ImportExport\Model\ResourceModel\CollectionByPagesIteratorFactory;
use Magento\Store\Model\StoreManagerInterface;
use Mageplaza\Faqs\Model\ResourceModel\Article\Collection;

/**
 * Class Article
 * @package Mageplaza\Faqs\Model\Export
 */
class Article extends AbstractEntity
{

    /**
     * Permanent entity columns
     *
     * @var string[]
     */
    protected $_permanentAttributes = [
        AttributeCollection::ARTICLE_ID,
        AttributeCollection::NAME,
        AttributeCollection::AUTHOR_NAME,
        AttributeCollection::AUTHOR_EMAIL,
        AttributeCollection::STATUS,
        AttributeCollection::VISIBILITY,
        AttributeCollection::ARTICLE_CONTENT,
        AttributeCollection::CATEGORIES,
        AttributeCollection::TAGS,
        AttributeCollection::PRODUCTS,
        AttributeCollection::RELATED_ARTICLES,
        AttributeCollection::STORE_ID,
        AttributeCollection::POSITIVES,
        AttributeCollection::NEGATIVES,
        AttributeCollection::VIEWS,
        AttributeCollection::POSITION,
        AttributeCollection::ICON_TYPE,
        AttributeCollection::ICON,
        AttributeCollection::ICON_CUSTOM_PATH,
        AttributeCollection::ICON_CUSTOM_WIDTH,
        AttributeCollection::ICON_CUSTOM_HEIGHT,
        AttributeCollection::URL_KEY,
        AttributeCollection::IN_RSS,
        AttributeCollection::EMAIL_NOTIFY,
        AttributeCollection::META_TITLE,
        AttributeCollection::META_DESCRIPTION,
        AttributeCollection::META_KEYWORDS,
        AttributeCollection::META_ROBOTS
    ];

    protected $_filterAttributes = [
        AttributeCollection::NAME,
        AttributeCollection::AUTHOR_NAME,
        AttributeCollection::AUTHOR_EMAIL,
        AttributeCollection::STATUS,
        AttributeCollection::VISIBILITY,
        AttributeCollection::ARTICLE_CONTENT,
        AttributeCollection::STORE_ID,
        AttributeCollection::URL_KEY,
        AttributeCollection::META_TITLE,
        AttributeCollection::META_DESCRIPTION,
        AttributeCollection::META_KEYWORDS
    ];

    /**
     * Attribute collection name
     */
    const ATTRIBUTE_COLLECTION_NAME = AttributeCollection::class;

    /**
     * @var Collection
     */
    protected $articleCollection;

    /**
     * Account constructor.
     *
     * @param ScopeConfigInterface $scopeConfig
     * @param StoreManagerInterface $storeManager
     * @param Factory $collectionFactory
     * @param CollectionByPagesIteratorFactory $resourceColFactory
     * @param Collection $articleCollection
     * @param array $data
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        StoreManagerInterface $storeManager,
        Factory $collectionFactory,
        CollectionByPagesIteratorFactory $resourceColFactory,
        Collection $articleCollection,
        array $data = []
    ) {
        $this->articleCollection = $articleCollection;

        parent::__construct($scopeConfig, $storeManager, $collectionFactory, $resourceColFactory, $data);
    }

    /**
     * @return string
     * @throws LocalizedException
     */
    public function export()
    {
        $filters      = $this->_parameters;
        $columns      = $this->_getHeaderColumns();
        $collection   = $this->_getEntityCollection();
        $exportFilter = $filters[Export::FILTER_ELEMENT_GROUP];
        foreach ($exportFilter as $field => $filter) {
            if (in_array($field, $columns, true)) {
                if ($filter || $filter === '0') {
                    if ($field === AttributeCollection::STORE_ID) {
                        $collection->addFieldToFilter(
                            [$field, $field, $field, $field],
                            [
                                ['like' => $filter],
                                ['like' => "%,{$filter}"],
                                ['like' => "{$filter},%"],
                                ['like' => "%,{$filter},%"]
                            ]
                        );
                    } else {
                        $collection->addFieldToFilter(
                            $field,
                            ['like' => "%{$filter}%"]
                        );
                    }
                }
            }
        }

        $this->getWriter()->setHeaderCols($columns);

        $this->_exportCollectionByPages($collection);

        return $this->getWriter()->getContents();
    }

    /**
     * @param AbstractModel $item
     *
     * @throws LocalizedException
     */
    public function exportItem($item)
    {
        $this->getWriter()->writeRow($item->getData());
    }

    /**
     * @return string
     */
    public function getEntityTypeCode()
    {
        return 'mp_faqs_articles';
    }

    /**
     * @return array|string[]
     * @throws LocalizedException
     */
    protected function _getHeaderColumns()
    {
        $filters = $this->_parameters;
        if (!isset($filters[Export::FILTER_ELEMENT_SKIP])) {
            return $this->_permanentAttributes;
        }

        $skip = $filters[Export::FILTER_ELEMENT_SKIP];

        if (count($skip) === count($this->_permanentAttributes)) {
            throw new LocalizedException(__('There is no data for the export.'));
        }

        return array_diff($this->_permanentAttributes, $skip);
    }

    /**
     * @return AbstractDb|Collection
     */
    protected function _getEntityCollection()
    {
        $articleCollection = $this->articleCollection;
        $articleCollection->getSelect()->joinLeft(
            ['category' => $articleCollection->getTable('mageplaza_faqs_article_category')],
            'main_table.article_id = category.article_id',
            ['category_id']
        )->joinLeft(
            ['tag' => $articleCollection->getTable('mageplaza_faqs_article_tag')],
            'main_table.article_id = tag.article_id',
            ['tag_id']
        )->joinLeft(
            ['product' => $articleCollection->getTable('mageplaza_faqs_article_product')],
            'main_table.article_id = product.article_id',
            ['entity_id']
        )->joinLeft(
            ['related_article' => $articleCollection->getTable('mageplaza_faqs_article_article')],
            'main_table.article_id = related_article.article_id',
            ['related_article_id']
        )->columns([
            'categories' => new Zend_Db_Expr('GROUP_CONCAT(DISTINCT `category`.`category_id`)')
        ])->columns([
            'tags' => new Zend_Db_Expr('GROUP_CONCAT(DISTINCT `tag`.`tag_id`)')
        ])->columns([
            'products' => new Zend_Db_Expr('GROUP_CONCAT(DISTINCT `product`.`entity_id`)')
        ])->columns([
            'related_articles' => new Zend_Db_Expr('GROUP_CONCAT(DISTINCT `related_article`.`related_article_id`)')
        ])->group(['main_table.article_id']);

        $articleCollection->addFilterToMap('store_ids', 'main_table.store_ids');
        $articleCollection->addFilterToMap('visibility', 'main_table.visibility');

        return $articleCollection;
    }

    /**
     * @return DataCollection|mixed
     * @throws Exception
     */
    public function getAttributeCollection()
    {
        return $this->_attributeCollection->buildAttributes($this->_filterAttributes);
    }
}
