<?php
/**
 * Biscotti Language Bridge
 *
 * Universal language detection across all major WordPress translation plugins.
 * Provides a single source of truth for the current language to all Biscotti
 * components (banner, shortcodes, API client, builder modules).
 *
 * Supported plugins:
 * - WPML
 * - Polylang
 * - TranslatePress
 * - Weglot
 * - MultilingualPress
 * - Loco Translate (uses WP locale)
 * - Standard WordPress locale
 *
 * @package Biscotti_CMP
 * @since 3.1.0
 */

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

class Biscotti_Language_Bridge
{
    /**
     * Cached language code for the current request
     * @var string|null
     */
    private static $cached_lang = null;

    /**
     * Get the current 2-letter language code.
     *
     * Checks all supported translation plugins in priority order,
     * then falls back to the WP locale. Result is cached per request.
     *
     * @return string 2-letter ISO 639-1 language code (e.g. 'de', 'en', 'fr')
     */
    public static function get_current_language()
    {
        if (self::$cached_lang !== null) {
            return self::$cached_lang;
        }

        $lang = self::detect_language();
        self::$cached_lang = $lang;
        return $lang;
    }

    /**
     * Reset the cached language (useful for testing or language switches)
     */
    public static function reset_cache()
    {
        self::$cached_lang = null;
    }

    /**
     * Detect language from translation plugins in priority order
     *
     * @return string 2-letter language code
     */
    private static function detect_language()
    {
        // 0. In admin context, the plugin's own language setting takes priority
        //    so that the admin panel language is independently configurable
        if (function_exists('is_admin') && is_admin()) {
            $options = get_option('biscotti_options', []);
            if (!empty($options['default_language'])) {
                return self::normalize($options['default_language']);
            }
        }

        // 1. WPML — most popular multilingual plugin
        if (defined('ICL_LANGUAGE_CODE') && ICL_LANGUAGE_CODE) {
            $code = ICL_LANGUAGE_CODE;
            // WPML 'all' means admin showing all languages
            if ($code !== 'all') {
                return self::normalize($code);
            }
        }

        // 2. Polylang — second most popular
        if (function_exists('pll_current_language')) {
            $code = pll_current_language('slug');
            if ($code) {
                return self::normalize($code);
            }
        }

        // 3. TranslatePress — URL/subdomain-based translation
        if (class_exists('TRP_Translate_Press')) {
            $trp = trp_get_languages();
            if (!empty($trp)) {
                // Get current language from TranslatePress settings
                $trp_settings = get_option('trp_settings', []);
                $current = isset($trp_settings['default-language'])
                    ? $trp_settings['default-language']
                    : '';
                // $TRP_LANGUAGE is a global defined by TranslatePress plugin — we only read it, not define it.
                global $TRP_LANGUAGE;
                if (!empty($TRP_LANGUAGE)) {
                    return self::normalize($TRP_LANGUAGE);
                }
                if ($current) {
                    return self::normalize($current);
                }
            }
        }

        // 4. Weglot — SaaS-based translation
        if (function_exists('weglot_get_current_language')) {
            $code = weglot_get_current_language();
            if ($code) {
                return self::normalize($code);
            }
        }

        // 5. MultilingualPress — multisite-based
        if (function_exists('mlp_get_current_blog_language')) {
            $locale = mlp_get_current_blog_language();
            if ($locale) {
                return self::normalize($locale);
            }
        }
        // MultilingualPress 3.x API
        if (function_exists('multilingualpress') && is_callable(['multilingualpress', 'resolve'])) {
            try {
                $api = multilingualpress()->resolve(
                    \Inpsyde\MultilingualPress\Framework\Api\SiteRelations::class
                );
                // Use WP locale as fallback for MLP 3.x
            } catch (\Exception $e) {
                // MLP not properly initialized
            }
        }

        // 6. Loco Translate — uses standard WordPress locale, no API
        // Falls through to WordPress locale below.

        // 7. Check plugin's own configured language
        $options = get_option('biscotti_options', []);
        if (!empty($options['default_language'])) {
            return self::normalize($options['default_language']);
        }

        // 8. WordPress locale (final fallback)
        $locale = determine_locale();
        return self::normalize($locale);
    }

    /**
     * Normalize a locale or language code to 2-letter ISO 639-1
     *
     * Handles formats like: 'de_DE', 'de-DE', 'de_DE_formal', 'de', 'deu'
     *
     * @param string $code Language code or locale
     * @return string 2-letter language code
     */
    private static function normalize($code)
    {
        if (empty($code)) {
            return 'en';
        }

        // Already 2-letter
        if (strlen($code) === 2) {
            return strtolower($code);
        }

        // Handle locale formats: de_DE, de-DE, de_DE_formal
        if (preg_match('/^([a-z]{2})[_\-]/i', $code, $m)) {
            return strtolower($m[1]);
        }

        // 3-letter ISO 639-2/3 fallback
        $iso3_map = [
            'deu' => 'de', 'eng' => 'en', 'fra' => 'fr', 'spa' => 'es',
            'ita' => 'it', 'nld' => 'nl', 'pol' => 'pl', 'por' => 'pt',
            'dan' => 'da', 'swe' => 'sv', 'fin' => 'fi', 'nor' => 'no',
            'ces' => 'cs', 'slk' => 'sk', 'hun' => 'hu', 'ron' => 'ro',
            'bul' => 'bg', 'hrv' => 'hr', 'slv' => 'sl', 'est' => 'et',
            'lav' => 'lv', 'lit' => 'lt', 'ell' => 'el', 'mlt' => 'mt',
            'gle' => 'ga', 'tur' => 'tr', 'rus' => 'ru', 'ukr' => 'uk',
            'jpn' => 'ja', 'zho' => 'zh', 'kor' => 'ko', 'ara' => 'ar',
            'hin' => 'hi', 'heb' => 'he', 'tha' => 'th', 'vie' => 'vi',
            'ind' => 'id', 'msa' => 'ms',
        ];
        $lower = strtolower($code);
        if (isset($iso3_map[$lower])) {
            return $iso3_map[$lower];
        }

        // Last resort: take first 2 chars
        return strtolower(substr($code, 0, 2));
    }

    /**
     * Get the name of the currently active translation plugin (for diagnostics)
     *
     * @return string Plugin name or 'none'
     */
    public static function get_active_plugin()
    {
        if (defined('ICL_LANGUAGE_CODE') && ICL_LANGUAGE_CODE !== 'all') {
            return 'WPML';
        }
        if (function_exists('pll_current_language')) {
            return 'Polylang';
        }
        if (class_exists('TRP_Translate_Press')) {
            return 'TranslatePress';
        }
        if (function_exists('weglot_get_current_language')) {
            return 'Weglot';
        }
        if (function_exists('mlp_get_current_blog_language') || function_exists('multilingualpress')) {
            return 'MultilingualPress';
        }
        if (class_exists('Loco_Locale')) {
            return 'Loco Translate';
        }
        return 'none';
    }
}
