<?php

declare(strict_types=1);

namespace Numinix\SeekmodoWordPress\LocalIndex;

/**
 * Stopword list for local index (DB + built-in English defaults).
 */
final class Stopwords
{
    /** @var array<string,true>|null */
    private static ?array $cache = null;

    /** @var list<string> */
    private const DEFAULT_EN = [
        'a', 'an', 'and', 'are', 'as', 'at', 'be', 'but', 'by', 'for',
        'from', 'has', 'he', 'in', 'is', 'it', 'its', 'of', 'on', 'or',
        'that', 'the', 'to', 'was', 'were', 'will', 'with',
    ];

    public static function isStopword(string $word): bool
    {
        $word = mb_strtolower(trim($word));
        if ($word === '') {
            return true;
        }
        $set = self::load();

        return isset($set[$word]);
    }

    /**
     * @return array<string,true>
     */
    public static function load(): array
    {
        if (self::$cache !== null) {
            return self::$cache;
        }
        $set = [];
        foreach (self::DEFAULT_EN as $w) {
            $set[$w] = true;
        }
        global $wpdb;
        $tables = Schema::tableNames();
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
        $rows = $wpdb->get_col("SELECT stopword FROM {$tables['stopwords']}");
        if (is_array($rows)) {
            foreach ($rows as $row) {
                $w = mb_strtolower((string) $row);
                if ($w !== '') {
                    $set[$w] = true;
                }
            }
        }
        self::$cache = $set;

        return $set;
    }

    public static function flushCache(): void
    {
        self::$cache = null;
    }

    public static function add(string $word): void
    {
        global $wpdb;
        $tables = Schema::tableNames();
        $word = mb_strtolower(trim($word));
        if ($word === '') {
            return;
        }
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $wpdb->replace($tables['stopwords'], ['stopword' => $word], ['%s']);
        self::flushCache();
    }

    public static function remove(string $word): void
    {
        global $wpdb;
        $tables = Schema::tableNames();
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
        $wpdb->delete($tables['stopwords'], ['stopword' => mb_strtolower(trim($word))], ['%s']);
        self::flushCache();
    }

    /**
     * @return list<string>
     */
    public static function all(): array
    {
        return array_keys(self::load());
    }
}
