<?php
declare(strict_types=1);

namespace Leadlion\Autogedal\Setup\Patch\Data;

use Magento\Framework\DB\Adapter\AdapterInterface;
use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

class ReplaceFeaturedWithLatestProducts implements DataPatchInterface
{
    private const HOME_PAGE_IDENTIFIER = 'porto_home_12';
    private const FEATURED_COMMENT = '<!-- Featured Products - Homepage -->';
    private const LATEST_COMMENT = '<!-- Latest Products - Homepage -->';
    private const EXTRA_INFO_COMMENT = '<!-- AutoGedal - HomePage Extra Single Images -->';

    /**
     * @var ModuleDataSetupInterface
     */
    private $moduleDataSetup;

    public function __construct(ModuleDataSetupInterface $moduleDataSetup)
    {
        $this->moduleDataSetup = $moduleDataSetup;
    }

    /**
     * @inheritDoc
     */
    public function apply(): ReplaceFeaturedWithLatestProducts
    {
        $connection = $this->moduleDataSetup->getConnection();
        $this->replaceFeaturedWithLatest($connection);
        $this->moveExtraSingleImagesAboveLatest($connection);

        return $this;
    }

    private function replaceFeaturedWithLatest(AdapterInterface $connection): void
    {
        $pageTable = $this->moduleDataSetup->getTable('cms_page');

        $row = $connection->fetchRow(
            $connection->select()
                ->from($pageTable, ['page_id', 'content'])
                ->where('identifier = ?', self::HOME_PAGE_IDENTIFIER)
        );

        if (!$row) {
            return;
        }

        $content = $row['content'];

        $latestPattern = '~' . preg_quote(self::LATEST_COMMENT, '~') . '\R\{\{widget[^}]*\}\}~';

        if (!preg_match($latestPattern, $content, $latestMatch)) {
            return;
        }

        $latestSection = $latestMatch[0];

        $removePattern = '~[ \t]*' . preg_quote(self::LATEST_COMMENT, '~')
            . '\R\{\{widget[^}]*\}\}[ \t]*\R?(?:[ \t]*\R)?~';
        $content = preg_replace($removePattern, '', $content, 1);

        $featuredPattern = '~' . preg_quote(self::FEATURED_COMMENT, '~') . '\R\{\{widget[^}]*\}\}~';

        if (!preg_match($featuredPattern, $content, $featuredMatch)) {
            return;
        }

        $newContent = $this->replaceFirst($featuredMatch[0], $latestSection, $content);

        if ($newContent !== $row['content']) {
            $connection->update(
                $pageTable,
                ['content' => $newContent],
                ['page_id = ?' => $row['page_id']]
            );
        }
    }

    private function moveExtraSingleImagesAboveLatest(AdapterInterface $connection): void
    {
        $pageTable = $this->moduleDataSetup->getTable('cms_page');

        $row = $connection->fetchRow(
            $connection->select()
                ->from($pageTable, ['page_id', 'content'])
                ->where('identifier = ?', self::HOME_PAGE_IDENTIFIER)
        );

        if (!$row) {
            return;
        }

        $pattern = '~('
            . preg_quote(self::LATEST_COMMENT, '~') . '\R\{\{widget[^}]*\}\})(\R+)('
            . preg_quote(self::EXTRA_INFO_COMMENT, '~') . '\R\{\{widget[^}]*\}\})~';

        $newContent = preg_replace($pattern, '$3$2$1', $row['content'], 1);

        if ($newContent !== null && $newContent !== $row['content']) {
            $connection->update(
                $pageTable,
                ['content' => $newContent],
                ['page_id = ?' => $row['page_id']]
            );
        }
    }

    private function replaceFirst(string $search, string $replace, string $subject): string
    {
        $pos = strpos($subject, $search);

        if ($pos === false) {
            return $subject;
        }

        return substr_replace($subject, $replace, $pos, strlen($search));
    }

    /**
     * @inheritDoc
     */
    public function getAliases(): array
    {
        return [];
    }

    /**
     * @inheritDoc
     */
    public static function getDependencies(): array
    {
        if (class_exists(MoveHomepagePresentationBelowBlog::class)) {
            return [MoveHomepagePresentationBelowBlog::class];
        }

        return [];
    }
}
