<?php
declare(strict_types=1);

namespace Autogedal\Manufacturers\Block\Manufacturer;

use Autogedal\Manufacturers\Model\Config;
use Autogedal\Manufacturers\Model\ResourceModel\ManufacturerPage\CollectionFactory as ManufacturerPageCollectionFactory;
use Autogedal\Manufacturers\Service\SlugHandler;
use Magento\Cms\Api\Data\PageInterface;
use Magento\Cms\Api\GetPageByIdentifierInterface;
use Magento\Cms\Model\Template\FilterProvider;
use Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\CollectionFactory as OptionCollectionFactory;
use Magento\Framework\DataObject;
use Magento\Framework\DataObject\IdentityInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\Element\Template\Context;

class View extends Template implements IdentityInterface
{
    private ?DataObject $manufacturer = null;
    private ?DataObject $manufacturerPage = null;
    private ?PageInterface $cmsPage = null;
    private bool $cmsPageLoaded = false;

    public function __construct(
        Context $context,
        private readonly OptionCollectionFactory $optionCollectionFactory,
        private readonly ManufacturerPageCollectionFactory $manufacturerPageCollectionFactory,
        private readonly GetPageByIdentifierInterface $getPageByIdentifier,
        private readonly FilterProvider $filterProvider,
        private readonly SlugHandler $slugHandler,
        private readonly Config $config,
        array $data = []
    ) {
        parent::__construct($context, $data);
    }

    public function getManufacturer(): ?DataObject
    {
        if ($this->manufacturer !== null) {
            return $this->manufacturer;
        }

        $slug = $this->getRequest()->getParam('slug');
        if (!$slug || !$this->slugHandler->validateSlug($slug)) {
            return null;
        }

        $page = $this->manufacturerPageCollectionFactory->create()
            ->addFieldToFilter('slug', $slug)
            ->setPageSize(1)
            ->getFirstItem();
        if (!$page->getId()) {
            return null;
        }

        $this->manufacturerPage = $page;
        $this->manufacturer = $this->optionCollectionFactory->create()
            ->setAttributeFilter($this->config->getProductAttributeId())
            ->setStoreFilter($this->_storeManager->getStore()->getId())
            ->addFieldToFilter('main_table.option_id', $page->getOptionId())
            ->getFirstItem();

        if ($this->manufacturer->getId()) {
            $this->manufacturer->addData(['slug' => $page->getSlug(), 'cms_page' => $page->getCmsPage()]);
        }

        return $this->manufacturer;
    }

    public function getManufacturerName()
    {
        $manufacturer = $this->getManufacturer();

        return $manufacturer ? $manufacturer->getValue() : '';
    }

    public function getCmsPage(): ?PageInterface
    {
        if (!$this->cmsPageLoaded) {
            $this->cmsPageLoaded = true;
            $this->cmsPage = $this->loadCmsPage();
        }

        return $this->cmsPage;
    }

    public function getCmsPageContent()
    {
        $page = $this->getCmsPage();

        return $page ? $this->filterProvider->getPageFilter()->filter($page->getContent()) : '';
    }

    public function getIdentities(): array
    {
        $page = $this->getCmsPage();
        $identities = $page instanceof IdentityInterface ? $page->getIdentities() : [];

        if ($this->manufacturerPage instanceof IdentityInterface) {
            $identities = array_merge($identities, $this->manufacturerPage->getIdentities());
        }

        return array_values(array_unique($identities));
    }

    private function loadCmsPage(): ?PageInterface
    {
        $identifier = $this->getManufacturer()?->getData('cms_page');
        if (!$identifier) {
            return null;
        }

        try {
            $page = $this->getPageByIdentifier->execute(
                (string)$identifier,
                (int)$this->_storeManager->getStore()->getId()
            );
        } catch (NoSuchEntityException) {
            return null;
        }

        return $page->isActive() ? $page : null;
    }
}
