<?php
declare(strict_types=1);

namespace Ekesto\CacheInvalidator\Integrations\Forms;

/**
 * Helpers for matching target form IDs in scanned content.
 */
final class FormsReferenceMatcher
{
    /**
     * Normalize one scanned text payload before adapter extraction.
     *
     * Normalization is representation-focused only and must remain lightweight,
     * idempotent, and deterministic so adapters can stay storage-agnostic.
     *
     * @param string $text Raw scanned text.
     * @return string
     */
    public static function normalizeScannedText(string $text): string
    {
        return FormsScanTextNormalizer::normalize($text);
    }

    /**
     * Determine whether text contains the target form ID.
     *
     * @param FormAdapterInterface $adapter Adapter instance.
     * @param string               $text Text to inspect.
     * @param string               $targetFormId Target form ID.
     * @return bool
     */
    public static function containsTargetFormId(FormAdapterInterface $adapter, string $text, string $targetFormId): bool
    {
        return self::containsTargetFormIds($adapter, $text, [$targetFormId]);
    }

    /**
     * Determine whether text contains any target form ID.
     *
     * @param FormAdapterInterface $adapter Adapter instance.
     * @param string               $text Text to inspect.
     * @param string[]             $targetFormIds Target form IDs.
     * @return bool
     */
    public static function containsTargetFormIds(FormAdapterInterface $adapter, string $text, array $targetFormIds): bool
    {
        return self::findMatchingFormId($adapter, $text, $targetFormIds) !== null;
    }

    /**
     * Returns the matched form ID token from content, or null when no match.
     *
     * @param FormAdapterInterface $adapter Adapter instance.
     * @param string               $text Text to inspect.
     * @param string[]             $targetFormIds Target form IDs.
     * @return string|null
     */
    public static function findMatchingFormId(FormAdapterInterface $adapter, string $text, array $targetFormIds): ?string
    {
        if ($text === '') {
            return null;
        }

        $normalizedTargets = self::normalizeFormIds($targetFormIds);
        if (empty($normalizedTargets)) {
            return null;
        }

        $targetLookup = array_fill_keys($normalizedTargets, true);
        $ids = $adapter->extractFormIdsFromContent(self::normalizeScannedText($text));

        foreach ($ids as $id) {
            $normalized = self::normalizeFormId((string) $id);
            if ($normalized !== '' && isset($targetLookup[$normalized])) {
                return $normalized;
            }
        }

        return null;
    }

    /**
     * Normalize form ID for string-based comparison.
     *
     * @param string $id Raw form ID.
     * @return string
     */
    public static function normalizeFormId(string $id): string
    {
        return trim($id);
    }

    /**
     * Normalize list of form IDs for string-based comparison.
     *
     * @param string[] $ids Raw form IDs.
     * @return string[]
     */
    private static function normalizeFormIds(array $ids): array
    {
        return array_values(array_unique(array_filter(array_map(
            static fn($id): string => self::normalizeFormId((string) $id),
            $ids
        ))));
    }
}
