<?php
declare(strict_types=1);

namespace Leadlion\Autogedal\Setup\Patch\Data;

use Magento\Framework\Setup\ModuleDataSetupInterface;
use Magento\Framework\Setup\Patch\DataPatchInterface;

class AddMoreLinksToOrderEmailCategoryList implements DataPatchInterface
{
    private const TEMPLATE_CODE = 'AutoGedal.Ro - Comandă nouă';

    private const CATEGORY_PATHS = [
        'Suporturi ski-uri' => 'suporturi-schiuri.html',
        'Bare transversale' => 'auto-bare-transversale.html',
        'Paravanturi auto' => 'paravanturi.html',
        'Genti, Rucsacuri, Huse' => 'genti-rucsacuri-huse.html',
        'Transport Copii' => 'transport-copii.html',
        'Corturi Auto' => 'corturi-auto.html',
    ];

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

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

    /**
     * @inheritDoc
     */
    public function apply(): AddMoreLinksToOrderEmailCategoryList
    {
        $connection = $this->moduleDataSetup->getConnection();
        $table = $this->moduleDataSetup->getTable('email_template');

        $row = $connection->fetchRow(
            $connection->select()
                ->from($table, ['template_id', 'template_text'])
                ->where('template_code = ?', self::TEMPLATE_CODE)
        );

        if (!$row) {
            return $this;
        }

        $newText = $this->appendCategoryLinks($row['template_text']);

        if ($newText !== $row['template_text']) {
            $connection->update(
                $table,
                ['template_text' => $newText],
                ['template_id = ?' => $row['template_id']]
            );
        }

        return $this;
    }

    /**
     * Appends the new category links to the end of the existing category list, right after the
     * last entry added by {@see AddLinksToOrderEmailCategoryList} ("Tavite Portbagaj").
     *
     * Unlike the first patch these categories are brand new, so there is nothing to linkify in
     * place - the entries have to be inserted. Idempotent: categories already present are skipped.
     */
    private function appendCategoryLinks(string $content): string
    {
        // The last category rendered by the first patch; used as the insertion anchor.
        $anchor = '>Tavite Portbagaj</a></span> <br/>';

        if (strpos($content, $anchor) === false) {
            return $content;
        }

        // Match the line ending and indentation already used by the existing entries.
        $eol = strpos($content, "\r\n") !== false ? "\r\n" : "\n";
        $indent = $this->detectIndent($content, $anchor);

        $additions = '';
        foreach (self::CATEGORY_PATHS as $name => $path) {
            if (strpos($content, 'direct_url="' . $path . '"') !== false) {
                continue; // already added
            }

            $additions .= $eol . $indent
                . '<span style="font-size:12px; line-height:16px;  margin:10px 0 0 0;">- '
                . '<a href="{{store direct_url="' . $path . '"}}" '
                . 'style="color:#3184ca; text-decoration:none;" target="_blank">' . $name . '</a></span> <br/>';
        }

        if ($additions === '') {
            return $content;
        }

        return str_replace($anchor, $anchor . $additions, $content);
    }

    /**
     * Returns the leading whitespace of the line that contains the anchor.
     */
    private function detectIndent(string $content, string $anchor): string
    {
        $anchorPos = strpos($content, $anchor);
        $lineStart = strrpos(substr($content, 0, $anchorPos), "\n");
        $rest = substr($content, $lineStart === false ? 0 : $lineStart + 1);

        preg_match('/^[ \t]*/', $rest, $matches);

        return $matches[0];
    }

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

    /**
     * @inheritDoc
     */
    public static function getDependencies(): array
    {
        return [
            AddLinksToOrderEmailCategoryList::class,
        ];
    }
}
