<?php
declare(strict_types=1);

namespace Autogedal\Manufacturers\Block\Manufacturer;

use Autogedal\Manufacturers\Model\Config;
use Autogedal\Manufacturers\Model\ManufacturerPage;
use Autogedal\Manufacturers\Model\ManufacturerUrl;
use Autogedal\Manufacturers\Model\ResourceModel\ManufacturerPage as ManufacturerPageResource;
use Autogedal\Manufacturers\Model\ResourceModel\ManufacturerPage\Collection as ManufacturerPageCollection;
use Autogedal\Manufacturers\Model\ResourceModel\ManufacturerPage\CollectionFactory as ManufacturerPageCollectionFactory;
use Magento\Cms\Model\Page as CmsPage;
use Magento\Cms\Model\ResourceModel\Page\CollectionFactory as CmsPageCollectionFactory;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection as OptionCollection;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory as OptionCollectionFactory;
use Magento\Framework\DataObject;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class ManufacturerList extends Template implements IdentityInterface
{
    private ?ManufacturerPageCollection $manufacturerPageCollection = null;

    public function __construct(
        Context $context,
        private readonly OptionCollectionFactory $optionCollectionFactory,
        private readonly ManufacturerPageCollectionFactory $manufacturerPageCollectionFactory,
        private readonly CmsPageCollectionFactory $cmsPageCollectionFactory,
        private readonly Config $config,
        private readonly ManufacturerUrl $manufacturerUrl,
        private readonly ManufacturerPageResource $manufacturerPageResource,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    public function getManufacturers(): OptionCollection
    {
        $slugs = [];
        foreach ($this->getManufacturerPageCollection() as $page) {
            $slugs[$page->getOptionId()] = $page->getSlug();
        }

        $collection = $this->optionCollectionFactory->create()
            ->setAttributeFilter($this->config->getProductAttributeId())
            ->setStoreFilter($this->_storeManager->getStore()->getId())
            ->addFieldToFilter('main_table.option_id', ['in' => $slugs ? array_keys($slugs) : [0]]);

        foreach ($collection as $item) {
            $optionId = $item->getOptionId();
            if (isset($slugs[$optionId])) {
                $item->setData('slug', $slugs[$optionId]);
            }
        }

        return $collection;
    }

    public function getManufacturerUrl(DataObject $manufacturer): string
    {
        $slug = $manufacturer->getData('slug')
            ?: strtolower(str_replace(' ', '-', $manufacturer->getValue()));

        return $this->manufacturerUrl->getUrl((string)$slug);
    }

    public function getIdentities(): array
    {
        $identities = [[ManufacturerPage::CACHE_TAG]];
        foreach ($this->getManufacturerPageCollection() as $page) {
            $identities[] = $page->getIdentities();
        }
        foreach ($this->manufacturerPageResource->getCmsPageIds() as $cmsPageId) {
            $identities[] = [CmsPage::CACHE_TAG . '_' . $cmsPageId];
        }

        return array_values(array_unique(array_merge(...$identities)));
    }

    private function getManufacturerPageCollection(): ManufacturerPageCollection
    {
        if ($this->manufacturerPageCollection !== null) {
            return $this->manufacturerPageCollection;
        }

        $identifiers = $this->cmsPageCollectionFactory->create()
            ->addStoreFilter((int)$this->_storeManager->getStore()->getId())
            ->addFieldToFilter('is_active', 1)
            ->getColumnValues('identifier');

        $collection = $this->manufacturerPageCollectionFactory->create()
            ->addFieldToFilter('cms_page', ['in' => $identifiers ?: ['']]);

        $inactiveIds = $this->config->getInactiveManufacturerIds();
        if ($inactiveIds) {
            $collection->addFieldToFilter('option_id', ['nin' => $inactiveIds]);
        }

        $this->manufacturerPageCollection = $collection;

        return $collection;
    }
}
