<?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\App\ResourceConnection;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Module\Manager;
use Magento\Store\Model\StoreManagerInterface;
use MongoDB\Driver\Exception\Exception;
use Symfony\Component\Console\Output\OutputInterface;
use Zend_Db;

/**
 * Class Storelocator
 * @package FiloBlu\Refilo\Model\Exporter
 */
class Storelocator extends AbstractExporter
{
    /**
     * @var ResourceConnection
     */
    private $resourceConnection;

    /**
     * @var StoreManagerInterface
     */
    private $storeManager;
    /**
     * @var \Magento\Framework\Module\Manager
     */
    private $moduleManager;

    /**
     * Countries constructor.
     * @param ResourceConnection $resourceConnection
     * @param ScopeConfigInterface $scopeConfig
     * @param Mongo $mongo
     * @param StoreManagerInterface $storeManager
     * @param \Magento\Framework\Module\Manager $moduleManager
     * @param Configuration $coreConfiguration
     */
    public function __construct(
        ResourceConnection $resourceConnection,
        ScopeConfigInterface $scopeConfig,
        Mongo $mongo,
        StoreManagerInterface $storeManager,
        Manager $moduleManager,
        Configuration $coreConfiguration
    ) {
        parent::__construct($mongo, $coreConfiguration, $scopeConfig);
        $this->resourceConnection = $resourceConnection;
        $this->storeManager = $storeManager;
        $this->moduleManager = $moduleManager;
    }

    /**
     * @param OutputInterface|null $output
     */
    public function preExecute(OutputInterface $output = null)
    {
    }

    public function getCollections(): iterable
    {
        yield 'storelocator';
    }

    /**
     * @param OutputInterface|null $output
     * @throws LocalizedException
     */
    public function execute(OutputInterface $output = null)
    {
        $isMultiDomain = $this->getCoreConfiguration()->isMultiDomain();

        $projectIds = [];

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

        $connection = $this->resourceConnection->getConnection();
        $bulkData = [];
        // TODO: move in dedicated module
        if ($this->moduleManager->isEnabled('FiloBlu_Storelocator')) {
            $queryTags = "SELECT fsst.store_id, fst.*, CONCAT('/filoblu/storelocator/stores/image',fst.image) as image_url FROM filoblu_storelocator_store_tag as fsst
                          INNER JOIN filoblu_storelocator_tags as fst on fsst.tag_id = fst.tag_id";
            $queryImages = "SELECT fssi.store_id, fsi.*, CONCAT('/filoblu/storelocator/stores/image',fsi.image) as image_url FROM filoblu_storelocator_store_image as fssi
                            INNER JOIN filoblu_storelocator_images as fsi on fssi.image_id = fsi.image_id";
            $queryWorkingTimes = 'SELECT * FROM filoblu_storelocator_store_workingtimes;';
            $queryEvents = 'SELECT * FROM filoblu_storelocator_events;';

            $resultTags = $connection->fetchAll($queryTags, [], Zend_Db::FETCH_ASSOC);
            $resultImages = $connection->fetchAll($queryImages, [], Zend_Db::FETCH_ASSOC);
            $resultWorkingTimes = $connection->fetchAll($queryWorkingTimes, [], Zend_Db::FETCH_ASSOC);
            $resultEvents = $connection->fetchAll($queryEvents, [], Zend_Db::FETCH_ASSOC);

            // Prepare lookup tables

            $tagsLookup = [];
            $imagesLookup = [];
            $workingTimesLookup = [];
            $eventsLookup = [];

            foreach ($resultTags as $tag) {
                $storeId = $tag['store_id'];
                $tag['store_id'] = (int)$storeId;
                $tag['tag_id'] = (int)$tag['tag_id'];
                $tag['enabled'] = (int)$tag['enabled'];
                $tagsLookup[$storeId][] = $tag;
            }

            foreach ($resultImages as $image) {
                $storeId = $image['store_id'];
                $image['store_id'] = (int)$storeId;
                $image['image_id'] = (int)$image['image_id'];
                $image['enabled'] = (int)$image['enabled'];
                $imagesLookup[$storeId][] = $image;
            }

            foreach ($resultWorkingTimes as $workingTime) {
                $storeId = $workingTime['store_id'];
                $workingTime['store_id'] = (int)$storeId;
                $workingTime['workingtime_id'] = (int)$workingTime['workingtime_id'];
                $workingTime['closed'] = (int)$workingTime['closed'];
                $workingTime['day'] = (int)$workingTime['day'];
                $workingTime['period'] = (int)$workingTime['period'];
                $workingTimesLookup[$storeId][] = $workingTime;
            }

            foreach ($resultEvents as $event) {
                $storeId = $event['store_id'];
                $event['event_id'] = (int)$event['event_id'];
                $event['store_id'] = (int)$storeId;
                $eventsLookup[$storeId][] = $event;
            }

            foreach ($this->storeManager->getStores() as $storeView) {
                if (!$storeView->getIsActive()) {
                    continue;
                }

                $storeViewId = $storeView->getId();
                $where = "enabled = 1 AND (store_ids like '$storeViewId,%' OR store_ids like '%,$storeViewId' OR store_ids like '%,$storeViewId,%' OR store_ids = '0' OR store_ids = '$storeViewId')";

                $queryStores = "SELECT *,
                            CONCAT('/filoblu/storelocator/stores/image',fss.marker_image) as marker_image_url,
                            CONCAT('/filoblu/storelocator/stores/image',fss.image) as image_url FROM filoblu_storelocator_stores as fss
                            WHERE $where;";

                $resultStores = $connection->fetchAll($queryStores, [], Zend_Db::FETCH_ASSOC);

                foreach ($resultStores as $store) {
                    $storeId = $store['store_id'];
                    unset($store['store_id']);
                    $store['is_enabled_for_pickup_in_store'] = (bool)$store['is_enabled_for_pickup_in_store'];
                    $store['is_enabled_shop_details'] = (bool)$store['is_enabled_shop_details'];
                    $store['enabled'] = (int)$store['enabled'];
                    $store['latitude'] = (float)$store['latitude'];
                    $store['longitude'] = (float)$store['longitude'];
                    $store['_id'] = "{$storeId}_$storeViewId";
                    $store['entity_id'] = "{$storeId}";
                    $store['code'] = $store['store_code'];
                    $store['store_code'] = $storeView->getCode();
                    $store['tags'] = $tagsLookup[$storeId] ?? [];
                    $store['images'] = $imagesLookup[$storeId] ?? [];
                    $store['working_times'] = $workingTimesLookup[$storeId] ?? [];
                    foreach ($eventsLookup[$storeId] ?? [] as $key => $currentStore) {
                        $eventsLookup[$storeId][$key]['store_id'] = $currentStore['store_id'] . "_$storeViewId";
                    }
                    $store['events'] = $eventsLookup[$storeId] ?? [];
                    $bulkData[] = $store;
                }
            }
        }

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