<?php

declare(strict_types=1);

namespace FiloBlu\Refilo\Model\Exporter;

use FiloBlu\Core\Model\Configuration;
use FiloBlu\Refilo\Model\Adapter\Mongo;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\Exception\LocalizedException;
use MongoDB\Driver\Exception\Exception;
use RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;

/**
 * Class AbstractExporter
 * @package FiloBlu\Refilo\Model\Exporter
 */
abstract class AbstractExporter implements ExporterInterface
{
    /**
     * @var ScopeConfigInterface
     */
    protected $scopeConfig;
    /**
     * @var Mongo
     */
    private $mongo;
    /**
     * @var Configuration
     */
    private $coreConfiguration;

    /**
     * AbstractExporter constructor.
     * @param Mongo $mongo
     * @param Configuration $coreConfiguration
     * @param ScopeConfigInterface $scopeConfig
     */
    public function __construct(Mongo $mongo, Configuration $coreConfiguration, ScopeConfigInterface $scopeConfig)
    {
        $this->mongo = $mongo;
        $this->scopeConfig = $scopeConfig;
        $this->coreConfiguration = $coreConfiguration;
    }

    /**
     * @param OutputInterface|null $output
     * @throws Exception
     * @throws LocalizedException
     */
    public function export(OutputInterface $output = null) : void
    {
        $this->preExecute($output);
        $this->execute($output);
        $this->postExecute($output);
    }

    /**
     * @throws Exception
     * @throws LocalizedException
     */
    public function preExecute(OutputInterface $output = null)
    {
        $projectIds = [$this->getDatabase()];

        if ($this->getCoreConfiguration()->isMultiDomain()) {
            $projectIds = $this->getCoreConfiguration()->getProjectIds();
        }

        foreach ($projectIds as $projectId) {
            foreach ($this->getCollections() as $collection) {
                $this->mongo->dropCollection($collection, $projectId);
            }
        }
    }

    /**
     * @return mixed
     */
    public function getDatabase()
    {
        $database = $this->scopeConfig->getValue('mongo/general/mongo_general_database');

        if (!$database) {
            throw new RuntimeException('MongoDB is not configured');
        }

        return $database;
    }

    /**
     * @return Configuration
     */
    public function getCoreConfiguration(): Configuration
    {
        return $this->coreConfiguration;
    }

    abstract public function getCollections(): iterable;

    abstract public function execute(OutputInterface $output = null);

    /**
     *
     */
    public function postExecute(OutputInterface $output = null)
    {
        $projectIds = [$this->getDatabase()];

        if ($this->getCoreConfiguration()->isMultiDomain()) {
            $projectIds = $this->getCoreConfiguration()->getProjectIds();
        }

        foreach ($projectIds as $projectId) {
            $this->getConnection()->createWildIndex($this->getCollections(), $projectId);
        }
    }

    /**
     * @return Mongo
     */
    public function getConnection()
    {
        return $this->mongo;
    }

}
