<?php

declare(strict_types=1);

namespace App\Knowledge\Retrieval;

use App\Knowledge\StopWords;

final readonly class QueryCleaner
{
    public function __construct(
        private StopWords $stopWords
    ) {
    }

    /**
     * Cleans a query strictly for retrieval purposes.
     *
     * Important:
     * - Unicode-safe
     * - Numbers are preserved
     * - Negations are preserved
     * - No aggressive token-length filtering
     * - Stop words are removed
     */
    public function clean(string $query): string
    {
        if ($query === '') {
            return '';
        }

        // 1. Convert to lowercase in a Unicode-safe way
        $query = mb_strtolower($query, 'UTF-8');

        // 2. Treat hyphens and slashes as word separators
        $query = str_replace(['-', '/'], ' ', $query);

        // 3. Remove special characters, but keep:
        //    - letters
        //    - numbers
        //    - other Unicode letters
        $query = preg_replace('/[^\p{L}\p{N}\s]/u', ' ', $query);

        if ($query === null) {
            return '';
        }

        // 4. Normalize multiple whitespace characters
        $query = preg_replace('/\s+/u', ' ', $query);
        $query = trim($query);

        if ($query === '') {
            return '';
        }

        // 5. Tokenize the query
        $tokens = preg_split('/\s+/u', $query);

        if ($tokens === false) {
            return '';
        }

        $cleanTokens = [];

        foreach ($tokens as $token) {

            $token = trim($token);

            if ($token === '') {
                continue;
            }

            // Remove stop words
            if ($this->stopWords->isStopWord($token)) {
                continue;
            }

            $cleanTokens[] = $token;
        }

        if ($cleanTokens === []) {
            return '';
        }

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