<?php

/*
 * Copyright (c) 2025-2026 Netresearch DTT GmbH
 * SPDX-License-Identifier: AGPL-3.0-or-later
 */

declare(strict_types=1);

namespace Netresearch\RteCKEditorImage\DataHandling\SoftReference;

use TYPO3\CMS\Core\DataHandling\SoftReference\AbstractSoftReferenceParser;
use TYPO3\CMS\Core\DataHandling\SoftReference\SoftReferenceParserResult;
use TYPO3\CMS\Core\Html\HtmlParser;

/**
 * Class for processing of the FAL soft references on img tags inserted in RTE content.
 *
 * @author  Stefan Galinski <stefan@sgalinski.de>
 * @license https://www.gnu.org/licenses/agpl-3.0.de.html
 *
 * @see    https://www.netresearch.de
 */
class RteImageSoftReferenceParser extends AbstractSoftReferenceParser
{
    /**
     * TYPO3 HTML parser.
     *
     * @var HtmlParser
     */
    private readonly HtmlParser $htmlParser;

    /**
     * @var string[]
     */
    private array $splitContentTags = [];

    /**
     * Constructor.
     *
     * @param HtmlParser $htmlParser
     */
    public function __construct(HtmlParser $htmlParser)
    {
        $this->htmlParser = $htmlParser;
    }

    /**
     * Main function through which all processing happens.
     *
     * @param string $table         Database table name
     * @param string $field         Field name for which processing occurs
     * @param int    $uid           UID of the record
     * @param string $content       The content/value of the field
     * @param string $structurePath if running from inside a FlexForm structure, this is the path of the tag
     *
     * @return SoftReferenceParserResult
     */
    public function parse(
        string $table,
        string $field,
        int $uid,
        string $content,
        string $structurePath = '',
    ): SoftReferenceParserResult {
        $this->setTokenIdBasePrefix($table, (string) $uid, $field, $structurePath);

        $retVal = $this->parserKey === 'rtehtmlarea_images' ? $this->findImageTags($content) : [];

        return SoftReferenceParserResult::create($content, $retVal);
    }

    /**
     * Finds image tags with "data-htmlarea-file-uid" attribute in the content. All images that have
     * a "data-htmlarea-file-uid" attribute will be returned with an info text.
     *
     * @param string $content The input content to analyse
     *
     * @return array<int|string, array<string, mixed>>
     */
    private function findImageTags(string $content): array
    {
        // Content split into images and other elements
        /** @var string[] $splitResult */
        $splitResult            = $this->htmlParser->splitTags('img', $content);
        $this->splitContentTags = $splitResult;

        return $this->findImagesWithDataUid();
    }

    /**
     * Checks for image tags.
     *
     * @param string $element
     *
     * @return bool
     */
    private function isImageTag(string $element): bool
    {
        return (bool) preg_match('/^<img/', $element);
    }

    /**
     * Finding image tags with "data-htmlarea-file-uid" attribute in the content. All images that have
     * a "data-htmlarea-file-uid" attribute will be returned with an info text.
     *
     * @return array<array<string, mixed>>
     */
    private function findImagesWithDataUid(): array
    {
        $images = [];

        // Traverse split parts
        foreach ($this->splitContentTags as $key => $htmlTag) {
            if (!$this->isImageTag($htmlTag)) {
                continue;
            }

            // Get FAL uid reference
            $attribs       = $this->htmlParser->get_tag_attributes($htmlTag);
            $tagAttributes = is_array($attribs[0] ?? null) ? $attribs[0] : [];
            $fileUid       = $tagAttributes['data-htmlarea-file-uid'] ?? false;
            // If there is a file uid, continue. Otherwise, ignore this img tag.
            if ($fileUid === false) {
                continue;
            }

            if (!is_string($fileUid)) {
                continue;
            }

            // Initialize the element entry with info text here
            $tokenID = $this->makeTokenID((string) $key);

            $images[$key]                = [];
            $images[$key]['matchString'] = $htmlTag;

            // Token and substitute value
            $this->splitContentTags[$key] = str_replace(
                'data-htmlarea-file-uid="' . $fileUid . '"',
                'data-htmlarea-file-uid="{softref:' . $tokenID . '}"',
                $htmlTag,
            );

            $images[$key]['subst'] = [
                'type'       => 'db',
                'recordRef'  => 'sys_file:' . $fileUid,
                'tokenID'    => $tokenID,
                'tokenValue' => $fileUid,
            ];
        }

        return $images;
    }
}
