<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Model\Exporter;

use FiloBlu\Core\Model\Configuration;
use FiloBlu\Refilo\Model\Adapter\Mongo;
use InvalidArgumentException;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Serialize\SerializerInterface;
use Magento\Search\Model\ResourceModel\Query\CollectionFactory;
use Magento\Search\Model\SearchCollectionFactory;
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Model\StoreManagerInterface;
use MongoDB\Driver\Exception\Exception;
use Symfony\Component\Console\Output\OutputInterface;
use Zend_Db;

/**
 *
 */
class SearchTerms extends AbstractExporter
{
    /**
     * @var \FiloBlu\Refilo\Model\Exporter\SearchTermExportableInterface
     */
    private $termExportable;
    /**
     * @var \FiloBlu\Refilo\Model\Exporter\SearchTermAdapterInterface
     */
    private $searchTermAdapter;
    /**
     * @var \Magento\Search\Model\ResourceModel\Query\CollectionFactory
     */
    private $searchCollectionFactory;

    /**
     * Search constructor.
     * @param ScopeConfigInterface $scopeConfig
     * @param Mongo $mongo
     * @param Configuration $coreConfiguration
     * @param \Magento\Search\Model\ResourceModel\Query\CollectionFactory $searchCollectionFactory
     * @param \FiloBlu\Refilo\Model\Exporter\SearchTermExportableInterface $termExportable
     * @param \FiloBlu\Refilo\Model\Exporter\SearchTermAdapterInterface $searchTermAdapter
     */
    public function __construct(
        ScopeConfigInterface $scopeConfig,
        Mongo $mongo,
        Configuration $coreConfiguration,
        CollectionFactory $searchCollectionFactory,
        SearchTermExportableInterface $termExportable,
        SearchTermAdapterInterface $searchTermAdapter
    ) {
        parent::__construct($mongo, $coreConfiguration, $scopeConfig);
        $this->termExportable = $termExportable;
        $this->searchTermAdapter = $searchTermAdapter;
        $this->searchCollectionFactory = $searchCollectionFactory;
    }

    /**
     * @return iterable
     */
    public function getCollections(): iterable
    {
        yield 'search';
    }

    /**
     * @throws Exception
     * @throws LocalizedException
     */
    public function preExecute(OutputInterface $output = null)
    {
        if ($this->getCoreConfiguration()->isMultiDomain()) {
            foreach ($this->getCoreConfiguration()->getWebsiteMapping() as $map) {
                $this->getConnection()->dropCollection(
                    'search',
                    $map->getProjectId()
                );
            }

            return;
        }

        $this->getConnection()->dropCollection(
            'search',
            $this->getDatabase()
        );
    }

    /**
     * @throws LocalizedException
     */
    public function execute(OutputInterface $output = null)
    {
        $projectIds = [];

        if ($this->getCoreConfiguration()->isMultiDomain()) {
            $projectIds = $this->getCoreConfiguration()->getProjectIds();
        } else {
            $projectIds[] = $this->getDatabase();
        }

        $bulkData = [];

        foreach ($this->getSearchTerms() as $searchTerm) {
            if (!$this->termExportable->canExport($searchTerm)) {
                continue;
            }

            $bulkData[] = $this->searchTermAdapter->adapt($searchTerm)->getData();
        }

        try {
            foreach ($projectIds as $projectId) {
                $this->getConnection()->update('_id', $bulkData, 'search', true, $projectId);
            }
        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

    /**
     * @return array
     */
    public function getSearchTerms(): array
    {
        return $this->searchCollectionFactory->create()->getItems();
    }
}
