<?php
declare(strict_types=1);
namespace FiloBlu\Refilo\Model\Importer;

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\Input\InputInterface;

abstract class AbstractImporter
{
    /**
     * @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 InputInterface|null $input
     * @throws Exception
     * @throws LocalizedException
     */
    public function import(InputInterface $input = null)
    {
        $this->preExecute($input);
        $this->execute($input);
        $this->postExecute($input);
    }

    /**
     * @throws Exception
     * @throws LocalizedException
     */
    abstract public function preExecute(InputInterface $input = null);

    /**
     * @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(InputInterface $input = null);

    /**
     *
     */
    abstract public function postExecute(InputInterface $input = null);

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