<?php

/**
 * Stemmers Loader
 *
 * Loads appropriate language stemmer based on locale
 *
 * @package ProRank\SEO\Modules\Content\InternalLinking\Parser\MultiLanguage
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Modules\Content\InternalLinking\Parser\MultiLanguage;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}


/**
 * StemmersLoader class
 */


class StemmersLoader {
    
    /**
     * Available stemmers
     *
     * @var array
     */
    private static array $stemmers = [];
    
    /**
     * Language mappings
     *
     * @var array
     */
    private const LANGUAGE_MAP = [
        'en' => 'English',
        'es' => 'Spanish',
        'fr' => 'French',
        'de' => 'German',
        'it' => 'Italian',
        'pt' => 'Portuguese',
        'nl' => 'Dutch',
        'ru' => 'Russian',
        'ar' => 'Arabic',
        'ja' => 'Japanese',
        'zh' => 'Chinese',
        'ko' => 'Korean',
        'hi' => 'Hindi',
        'pl' => 'Polish',
        'sv' => 'Swedish',
        'no' => 'Norwegian',
        'da' => 'Danish',
        'fi' => 'Finnish',
        'tr' => 'Turkish',
        'el' => 'Greek',
        'he' => 'Hebrew',
        'cs' => 'Czech',
    ];
    
    /**
     * Get stemmer for language
     *
     * @param string $language Language code (e.g., 'en', 'es')
     * @return Stemmer|null
     */
    public static function get_stemmer(string $language): ?Stemmer {
        $language = strtolower(substr($language, 0, 2));
        
        // Check cache
        if (isset(self::$stemmers[$language])) {
            return self::$stemmers[$language];
        }
        
        // Load stemmer
        $stemmer = self::load_stemmer($language);
        if ($stemmer !== null) {
            self::$stemmers[$language] = $stemmer;
        }
        
        return $stemmer;
    }
    
    /**
     * Get stemmer for current locale
     *
     * @return Stemmer|null
     */
    public static function get_current_stemmer(): ?Stemmer {
        $settings_language = '';

        if (class_exists('\\ProRank\\SEO\\Modules\\Content\\InternalLinking\\SettingsStore')) {
            $settings = \ProRank\SEO\Modules\Content\InternalLinking\SettingsStore::get();
            if (is_array($settings) && !empty($settings['language'])) {
                $settings_language = (string) $settings['language'];
            }
        }

        if ($settings_language !== '') {
            return self::get_stemmer($settings_language);
        }

        return self::get_stemmer((string) get_locale());
    }
    
    /**
     * Load stemmer class
     *
     * @param string $language Language code
     * @return Stemmer|null
     */
    private static function load_stemmer(string $language): ?Stemmer {
        if (!isset(self::LANGUAGE_MAP[$language])) {
            // Default to English
            $language = 'en';
        }
        
        $class_name = self::LANGUAGE_MAP[$language] . 'Stemmer';
        $namespace = __NAMESPACE__ . '\\Languages\\';
        $full_class = $namespace . $class_name;
        
        // Check if class file exists
        $file = dirname(__FILE__) . '/Languages/' . $class_name . '.php';
        
        if (file_exists($file)) {
            require_once $file;
            
            if (class_exists($full_class)) {
                return new $full_class();
            }
        }
        
        // Fall back to basic stemmer if specific language not available
        return self::create_basic_stemmer($language);
    }
    
    /**
     * Create basic stemmer for unsupported languages
     *
     * @param string $language Language code
     * @return Stemmer
     */
    private static function create_basic_stemmer(string $language): Stemmer {
        // Use anonymous class for basic stemming
        return new class($language) extends Stemmer {
            public function stem(string $word): string {
                $word = $this->normalize($word);
                
                // Basic suffix removal for most languages
                $suffixes = ['s', 'es', 'ed', 'ing', 'ly', 'er', 'est', 'tion', 'ment'];
                
                foreach ($suffixes as $suffix) {
                    if (strlen($word) > strlen($suffix) + 3 && substr($word, -strlen($suffix)) === $suffix) {
                        return substr($word, 0, -strlen($suffix));
                    }
                }
                
                return $word;
            }
        };
    }
    
    /**
     * Get available languages
     *
     * @return array
     */
    public static function get_available_languages(): array {
        return array_keys(self::LANGUAGE_MAP);
    }
    
    /**
     * Get language name
     *
     * @param string $code Language code
     * @return string Language name
     */
    public static function get_language_name(string $code): string {
        return self::LANGUAGE_MAP[$code] ?? 'Unknown';
    }
    
    /**
     * Detect language from text
     *
     * @param string $text Text to analyze
     * @return string Language code
     */
    public static function detect_language(string $text): string {
        // Simple language detection based on character patterns
        // This is a basic implementation - could be enhanced with ML
        
        // Check for non-Latin scripts
        if (preg_match('/[\x{0600}-\x{06FF}]/u', $text)) {
            return 'ar'; // Arabic
        }
        if (preg_match('/[\x{4E00}-\x{9FFF}]/u', $text)) {
            return 'zh'; // Chinese
        }
        if (preg_match('/[\x{3040}-\x{309F}\x{30A0}-\x{30FF}]/u', $text)) {
            return 'ja'; // Japanese
        }
        if (preg_match('/[\x{AC00}-\x{D7AF}]/u', $text)) {
            return 'ko'; // Korean
        }
        if (preg_match('/[\x{0400}-\x{04FF}]/u', $text)) {
            return 'ru'; // Russian/Cyrillic
        }
        if (preg_match('/[\x{0590}-\x{05FF}]/u', $text)) {
            return 'he'; // Hebrew
        }
        if (preg_match('/[\x{0900}-\x{097F}]/u', $text)) {
            return 'hi'; // Hindi/Devanagari
        }
        
        // For Latin-based languages, look for common patterns
        $text_lower = strtolower($text);
        
        // Spanish indicators
        if (preg_match('/\b(el|la|los|las|un|una|que|es|en|de|con)\b/', $text_lower)) {
            $spanish_score = substr_count($text_lower, 'ñ') + substr_count($text_lower, 'ción');
            if ($spanish_score > 0) return 'es';
        }
        
        // French indicators
        if (preg_match('/\b(le|la|les|un|une|de|du|des|que|est|et)\b/', $text_lower)) {
            $french_score = substr_count($text_lower, 'é') + substr_count($text_lower, 'è') + 
                           substr_count($text_lower, 'à') + substr_count($text_lower, 'ç');
            if ($french_score > 0) return 'fr';
        }
        
        // German indicators
        if (preg_match('/\b(der|die|das|ein|eine|und|ist|von|mit|zu)\b/', $text_lower)) {
            $german_score = substr_count($text_lower, 'ä') + substr_count($text_lower, 'ö') + 
                           substr_count($text_lower, 'ü') + substr_count($text_lower, 'ß');
            if ($german_score > 0) return 'de';
        }
        
        // Default to English
        return 'en';
    }
}
