<?php

declare(strict_types=1);

namespace Numinix\SeekmodoSdk\Search;

/**
 * Expands query terms using cached synonym rules from fallback_bundle.
 */
final class SynonymExpander
{
    private FallbackBundle $bundle;

    public function __construct(FallbackBundle $bundle)
    {
        $this->bundle = $bundle;
    }

    /**
     * @return list<string> expanded query tokens (unique, lowercased)
     */
    public function expandTerms(string $q): array
    {
        $normalized = mb_strtolower(trim($q));
        if ($normalized === '') {
            return [];
        }

        $terms = preg_split('/\s+/u', $normalized) ?: [];
        $terms = array_values(array_filter($terms, static fn (string $t): bool => $t !== ''));
        if ($terms === []) {
            return [];
        }

        $synonyms = $this->bundle->get()['synonyms'];
        $expanded = $terms;
        foreach ($synonyms as $row) {
            if (!is_array($row)) {
                continue;
            }
            $term = mb_strtolower(trim((string) ($row['term'] ?? '')));
            $expansions = is_array($row['expansions'] ?? null) ? $row['expansions'] : [];
            foreach ($terms as $token) {
                if ($token === $term) {
                    foreach ($expansions as $exp) {
                        $e = mb_strtolower(trim((string) $exp));
                        if ($e !== '') {
                            $expanded[] = $e;
                        }
                    }
                }
                foreach ($expansions as $exp) {
                    if ($token === mb_strtolower(trim((string) $exp))) {
                        if ($term !== '') {
                            $expanded[] = $term;
                        }
                    }
                }
            }
        }

        return array_values(array_unique($expanded));
    }

    /**
     * Build OR-style search string from original query + synonym expansions.
     */
    public function expandQuery(string $q): string
    {
        $terms = $this->expandTerms($q);
        if ($terms === []) {
            return trim($q);
        }

        return implode(' ', $terms);
    }
}
