<?php
/**
 * Mirasvit
 *
 * This source file is subject to the Mirasvit Software License, which is available at https://mirasvit.com/license/.
 * Do not edit or add to this file if you wish to upgrade the to newer versions in the future.
 * If you wish to customize this module for your needs.
 * Please refer to http://www.magentocommerce.com for more information.
 *
 * @category  Mirasvit
 * @package   mirasvit/module-cache-warmer
 * @version   1.11.13
 * @copyright Copyright (C) 2026 Mirasvit (https://mirasvit.com/)
 */


declare(strict_types=1);

namespace Mirasvit\CacheWarmer\Model;

use Magento\Framework\Data\Collection\AbstractDb;
use Magento\Framework\Model\AbstractModel;
use Magento\Framework\Model\Context;
use Magento\Framework\Model\ResourceModel\AbstractResource;
use Magento\Framework\Registry;
use Mirasvit\CacheWarmer\Api\Data\PageInterface;
use Magento\Framework\Serialize\SerializerInterface;
use Psr\Log\LoggerInterface;
use Mirasvit\Core\Service\SerializeService;

class Page extends AbstractModel implements PageInterface
{
    private $serializer;

    private $logger;

    public function __construct(
        Context $context,
        Registry $registry,
        SerializerInterface $serializer,
        LoggerInterface $logger,
        ?AbstractResource $resource = null,
        ?AbstractDb $resourceCollection = null,
        array $data = []
    ) {
        $this->serializer = $serializer;
        $this->logger     = $logger;
        parent::__construct($context, $registry, $resource, $resourceCollection, $data);
    }

    /**
     * {@inheritdoc}
     */
    protected function _construct()
    {
        $this->_init(ResourceModel\Page::class);
    }

    /**
     * {@inheritdoc}
     */
    public function getId()
    {
        return $this->getData(PageInterface::ID);
    }

    public function getUri(): string
    {
        return $this->getData(PageInterface::URI);
    }

    public function setUri(string $value): PageInterface
    {
        return $this->setData(PageInterface::URI, $value);
    }

    public function getUriHash(): ?string
    {
        return $this->getData(PageInterface::URI_HASH) ?: null;
    }

    public function setUriHash(string $value): PageInterface
    {
        return $this->setData(PageInterface::URI_HASH, $value);
    }

    public function getCacheId(): ?string
    {
        return $this->getData(PageInterface::CACHE_ID) ?: null;
    }

    public function setCacheId(string $value): PageInterface
    {
        return $this->setData(PageInterface::CACHE_ID, $value);
    }

    public function getPageType(): string
    {
        return $this->getData(PageInterface::PAGE_TYPE);
    }

    public function setPageType(string $value): PageInterface
    {
        return $this->setData(PageInterface::PAGE_TYPE, $value);
    }

    public function getProductId(): ?int
    {
        $productId = $this->getData(PageInterface::PRODUCT_ID);

        return $productId ? (int)$productId : null;
    }

    public function setProductId(int $value): PageInterface
    {
        return $this->setData(PageInterface::PRODUCT_ID, $value);
    }

    public function getCategoryId(): ?int
    {
        $categoryId = $this->getData(PageInterface::CATEGORY_ID);

        return $categoryId ? (int)$categoryId : null;
    }

    public function setCategoryId(int $value): PageInterface
    {
        return $this->setData(PageInterface::CATEGORY_ID, $value);
    }

    public function getStoreId(): int
    {
        return (int)$this->getData(PageInterface::STORE_ID);
    }

    public function setStoreId(int $value): PageInterface
    {
        return $this->setData(PageInterface::STORE_ID, $value);
    }

    /**
     * {@inheritdoc}
     */
    public function setVaryData($value): PageInterface
    {
        if (is_array($value)) {
            ksort($value);
            $value = $this->serializer->serialize($value);
        }

        return $this->setData(PageInterface::VARY_DATA, $value);
    }

    public function getVaryString(): ?string
    {
        if ($this->getVaryDataHash()) {
            return $this->getVaryDataHash();
        }
        //below is for backward compatibility
        $data = $this->getVaryData();
        if (!empty($data)) {
            ksort($data);
            return sha1($this->serializer->serialize($data));
        }
        return null;
    }

    public function getVaryData(): array
    {
        $varyData = $this->getData(PageInterface::VARY_DATA);
        if ($varyData === null || $varyData === false || $varyData === '' || $varyData === '[]') {
            $value = [];
        } else {
            try {
                $value = $this->serializer->unserialize((string)$varyData);
            } catch (\InvalidArgumentException $e) {
                $this->logger->warning('CacheWarmer: failed to unserialize vary_data for page', [
                    'page_id' => $this->getId(),
                    'error'   => $e->getMessage(),
                ]);
                $value = [];
            }
        }

        $value = is_array($value) ? $value : [];
        ksort($value);

        return $value;
    }

    public function getVaryDataHash(): string
    {
        return (string)$this->getData(PageInterface::VARY_DATA_HASH);
    }

    public function setVaryDataHash(string $value): PageInterface
    {
        return $this->setData(PageInterface::VARY_DATA_HASH, $value);
    }

    public function getCookie(): string
    {
        return (string)$this->getData(PageInterface::COOKIE);
    }

    public function setCookie(string $value): PageInterface
    {
        return $this->setData(PageInterface::COOKIE, $value);
    }

    public function getUserAgent(): string
    {
        $agent = $this->getData(PageInterface::USER_AGENT);
        if (!$agent) {
            return 'CacheWarmer';
        }
        return $agent;
    }

    public function setUserAgent(string $value): PageInterface
    {
        return $this->setData(PageInterface::USER_AGENT, $value);
    }

    public function getAttempts(): int
    {
        return (int)$this->getData(PageInterface::ATTEMPTS);
    }

    public function setAttempts(int $value): PageInterface
    {
        return $this->setData(PageInterface::ATTEMPTS, $value);
    }

    public function getPopularity(): int
    {
        return (int)$this->getData(PageInterface::POPULARITY);
    }

    public function setPopularity(int $value): PageInterface
    {
        return $this->setData(PageInterface::POPULARITY, $value);
    }

    public function getStatus(): string
    {
        return $this->getData(PageInterface::STATUS);
    }

    public function setStatus(string $value): PageInterface
    {
        return $this->setData(PageInterface::STATUS, $value);
    }

    public function getCreatedAt(): string
    {
        return $this->getData(PageInterface::CREATED_AT);
    }

    public function setCreatedAt(string $value): PageInterface
    {
        return $this->setData(PageInterface::CREATED_AT, $value);
    }

    public function getUpdatedAt(): string
    {
        return $this->getData(PageInterface::UPDATED_AT);
    }

    public function setUpdatedAt(string $value): PageInterface
    {
        return $this->setData(PageInterface::UPDATED_AT, $value);
    }

    public function getCachedAt(): ?string
    {
        return $this->getData(PageInterface::CACHED_AT) ?: null;
    }

    public function setCachedAt(?string $value): PageInterface
    {
        return $this->setData(PageInterface::CACHED_AT, $value);
    }

    public function getFlushedAt(): ?string
    {
        return $this->getData(PageInterface::FLUSHED_AT) ?: null;
    }

    public function setFlushedAt(?string $value): PageInterface
    {
        return $this->setData(PageInterface::FLUSHED_AT, $value);
    }

    public function getWarmRuleVersion(): ?string
    {
        return $this->getData(PageInterface::WARM_RULE_VERSION) ?: null;
    }

    public function setWarmRuleVersion(?string $value): PageInterface
    {
        return $this->setData(PageInterface::WARM_RULE_VERSION, $value);
    }

    public function getWarmRuleIds(): array
    {
        return array_filter(explode(',', (string)$this->getData(PageInterface::WARM_RULE_IDS)));
    }

    public function setWarmRuleIds(array $value): PageInterface
    {
        return $this->setData(PageInterface::WARM_RULE_IDS, implode(',', $value));
    }

    public function setMainRuleId(int $value): PageInterface
    {
        return $this->setData(PageInterface::MAIN_RULE_ID, $value);
    }

    public function getMainRuleId(): ?int
    {
        $ruleId = $this->getData(PageInterface::MAIN_RULE_ID);

        return $ruleId ? (int)$ruleId : null;
    }

    public function getHeaders(): array
    {
        try {
            $value = SerializeService::decode($this->getData(PageInterface::HEADERS));
            if (!$value) {
                return [];
            }
        } catch (\Exception $e) {
            $value = [];
        }

        if (is_array($value)) {
            ksort($value);
        }

        return $value;
    }

    public function setHeaders(array $value): PageInterface
    {
        if (is_array($value)) {
            ksort($value);
            $value = SerializeService::encode($value);
        }

        return $this->setData(PageInterface::HEADERS, $value);
    }

    public function getSourceId(): ?int
    {
        $sourceId = $this->getData(PageInterface::SOURCE_ID);

        return $sourceId ? (int)$sourceId : null;
    }

    public function setSourceId(int $value): PageInterface
    {
        return $this->setData(PageInterface::SOURCE_ID, $value);
    }

    public function getCustomerGroupId(): int
    {
        return (int)$this->getData(PageInterface::CUSTOMER_GROUP_ID);
    }

    public function setCustomerGroupId(int $value): PageInterface
    {
        return $this->setData(PageInterface::CUSTOMER_GROUP_ID, $value);
    }
}
