<?php
/**
 * @package     com_htprotect
 * @copyright   (C) 2026 Pascal Lohmann / website-bereinigung.de
 * @license     GNU General Public License version 2 or later
 *
 * HtpMailLang: EINHEITLICHE Sprachwahl fuer ALLE HTProtect-Mails (Auto-Update,
 * Waechter-Alarme, Abmelde-/Feedback-Bestaetigung). Verhindert den Sprachen-MIX
 * ZWISCHEN Mails - jede Mail folgt DERSELBEN Regel:
 *   1) Backend-Sprache des Empfaengers (falls die Adresse ein Joomla-User mit eigener
 *      admin_language/language ist),
 *   2) sonst globale Standard-Admin-/Site-Sprache (com_languages-Params, "Erweiterungen
 *      -> Sprachen") = Backend-/Komponenten-Sprache,
 *   3) sonst konfigurierte Standard-Sprache (Global-Config / Default-Content-Sprache),
 *   4) sonst en-GB.
 *
 * load() spielt die Zielsprache mit reload=true FRISCH ueber en-GB - unabhaengig davon,
 * was htp_load_lang() (aktive Sprache) vorher geladen hat. Damit ist die Mail-Sprache
 * NICHT mehr von der Aufruf-Reihenfolge oder dem CLI-/Cron-Kontext (dort aktiv = en-GB)
 * abhaengig. Rein lesend, fail-open.
 */

defined('_JEXEC') or die;

class HtpMailLang
{
    /**
     * Erzwungener Sprachcode ('de'|'en'|'') fuer htp_lang() waehrend des Mail-Baus.
     * load() setzt ihn passend zur geladenen Mail-Sprache, damit auch die ueber
     * htp_lang() gewaehlten Texte (z. B. HtpDefs::localized() -> Advisory-Link) DERSELBEN
     * Sprache folgen wie der restliche Mailtext (kein Mix innerhalb einer Mail).
     */
    private static $forced = '';

    /** Von htp_lang() konsultiert: erzwungener Code ('de'|'en') oder '' (kein Zwang). */
    public static function langCode()
    {
        return self::$forced;
    }

    /**
     * Sprach-Tag auf eine der ZWEI ausgelieferten Sprachen normalisieren (rein):
     * jede deutsche Variante (de-DE, de-AT, de-CH, de-LI, de-LU, de-BE ...) -> de-DE;
     * alles andere -> en-GB (HTProtect liefert nur diese beiden .ini).
     *
     * @param   string  $tag  beliebiger Sprach-Tag (z. B. 'de-AT')
     *
     * @return  string  'de-DE' oder 'en-GB'
     */
    public static function normalizeTag($tag)
    {
        return (strncasecmp((string) $tag, 'de', 2) === 0) ? 'de-DE' : 'en-GB';
    }

    /**
     * Erste Empfaenger-Adresse aus der (Komma/Semikolon/Whitespace-getrennten) Liste.
     */
    private static function firstEmail($cfg)
    {
        $email = (is_array($cfg) && isset($cfg['notify_email'])) ? (string) $cfg['notify_email'] : '';

        return trim((string) preg_replace('~[,;\s].*$~s', '', $email));
    }

    /**
     * Sprach-Tag fuer eine Benachrichtigung bestimmen (rein lesend, fail-open).
     *
     * @param   array   $cfg    Konfiguration (fuer notify_email-Fallback)
     * @param   string  $email  Konkreter Empfaenger (leer = erste notify_email-Adresse)
     *
     * @return  string  z. B. 'de-DE'
     */
    public static function tag($cfg, $email = '')
    {
        $email = ($email !== '') ? trim($email) : self::firstEmail($cfg);
        $db    = function_exists('htp_db') ? htp_db() : null;

        // 1) Backend-Sprache des Empfaengers.
        if ($db && $email !== '' && strpos($email, '@') !== false) {
            try {
                $q = $db->getQuery(true)
                    ->select($db->quoteName('params'))
                    ->from($db->quoteName('#__users'))
                    ->where($db->quoteName('email') . ' = ' . $db->quote($email));
                $db->setQuery($q, 0, 1);
                $p = json_decode((string) $db->loadResult(), true);

                if (is_array($p)) {
                    foreach (array('admin_language', 'language') as $k) {
                        if (!empty($p[$k]) && preg_match('~^[a-z]{2,3}-[A-Z]{2}$~', (string) $p[$k])) {
                            return (string) $p[$k];
                        }
                    }
                }
            } catch (Exception $e) {
                // weiter mit Fallback
            } catch (Throwable $e) {
                // weiter
            }
        }

        // 2) Globale Backend-/Site-Default-Sprache (com_languages-Params). Bevorzugt
        //    administrator, dann site. = die "Backend-/Komponenten-Sprache".
        if ($db) {
            try {
                $q = $db->getQuery(true)
                    ->select($db->quoteName('params'))
                    ->from($db->quoteName('#__extensions'))
                    ->where($db->quoteName('element') . ' = ' . $db->quote('com_languages'));
                $db->setQuery($q, 0, 1);
                $lp = json_decode((string) $db->loadResult(), true);

                if (is_array($lp)) {
                    foreach (array('administrator', 'site') as $k) {
                        if (!empty($lp[$k]) && preg_match('~^[a-z]{2,3}-[A-Z]{2}$~', (string) $lp[$k])) {
                            return (string) $lp[$k];
                        }
                    }
                }
            } catch (Exception $e) {
                // weiter
            } catch (Throwable $e) {
                // weiter
            }
        }

        // 3) Konfigurierte Standard-Sprache (Global-Config) bzw. Default-Content-Sprache.
        try {
            if (class_exists('Joomla\\CMS\\Factory')) {
                $app = Joomla\CMS\Factory::getApplication();
                $tag = ($app && method_exists($app, 'get')) ? (string) $app->get('language', '') : '';

                if (preg_match('~^[a-z]{2,3}-[A-Z]{2}$~', $tag)) {
                    return $tag;
                }
            }

            if (class_exists('Joomla\\CMS\\Language\\LanguageHelper')) {
                $def = (string) Joomla\CMS\Language\LanguageHelper::getDefault();

                if (preg_match('~^[a-z]{2,3}-[A-Z]{2}$~', $def)) {
                    return $def;
                }
            }
        } catch (Exception $e) {
            // weiter
        } catch (Throwable $e) {
            // weiter
        }

        return 'en-GB';
    }

    /**
     * Die ermittelte Zielsprache FRISCH in die com_htprotect-Sprache laden (en-GB als
     * Basis, Zielsprache darueber). Danach liefern htp_t()-Aufrufe genau diese Sprache -
     * unabhaengig von der aktiven CLI-/Request-Sprache. Fail-open.
     *
     * @param   array   $cfg    Konfiguration
     * @param   string  $email  Konkreter Empfaenger (leer = erste notify_email-Adresse)
     *
     * @return  void
     */
    public static function load($cfg, $email = '')
    {
        // Zielsprache aus cfg/Empfaenger bestimmen, dann laden (siehe loadTag).
        self::loadTag(self::tag($cfg, $email));
    }

    /**
     * Eine BEREITS BEKANNTE Zielsprache (Tag) frisch in die com_htprotect-Sprache
     * laden. Fuer Kontexte, in denen die Sprache NICHT aus cfg/Empfaenger stammt,
     * sondern aus einem expliziten Hinweis - z. B. der htp_fbl-Parameter der
     * Feedback-/Report-Seite, damit sie in DERSELBEN Sprache wie die ausloesende
     * Mail erscheint (statt der aktiven Frontend-/Site-Sprache).
     *
     * Bildet jede deutsche Variante auf de-DE ab, alles andere auf en-GB (HTProtect
     * liefert nur diese beiden .ini). en-GB als Basis, Zielsprache DARUEBER; setzt
     * zudem $forced fuer htp_lang(). Rein lesend, fail-open.
     *
     * @param   string  $tag  beliebiger Sprach-Tag ('de'|'en'|'de-DE'|'en-GB' ...)
     *
     * @return void
     */
    public static function loadTag($tag)
    {
        // Auf eine der zwei ausgelieferten Sprachen abbilden.
        $tag = self::normalizeTag($tag);

        // htp_lang() auf DIESELBE Sprache zwingen, damit auch htp_lang()-gesteuerte
        // Texte (HtpDefs::localized -> Advisory) der Sprache folgen (kein Mix).
        self::$forced = ($tag === 'de-DE') ? 'de' : 'en';

        try {
            if (!class_exists('Joomla\\CMS\\Factory')) {
                if (function_exists('htp_load_lang')) {
                    htp_load_lang();
                }

                return;
            }

            $app  = Joomla\CMS\Factory::getApplication();
            $base = defined('JPATH_ADMINISTRATOR') ? JPATH_ADMINISTRATOR
                : (defined('JPATH_ROOT') ? JPATH_ROOT . '/administrator' : '');

            if (!$app || !method_exists($app, 'getLanguage') || $base === '') {
                if (function_exists('htp_load_lang')) {
                    htp_load_lang();
                }

                return;
            }

            $lang = $app->getLanguage();

            if (!$lang || !method_exists($lang, 'load')) {
                return;
            }

            // en-GB als Basis (fuellt etwaige Luecken), dann die Zielsprache DARUEBER
            // (reload=true erzwingt frisches Laden -> setzt eine evtl. vorher via
            // htp_load_lang() geladene aktive Sprache ausser Kraft). $default=false.
            $lang->load('com_htprotect', $base, 'en-GB', true, false);

            if ($tag !== 'en-GB') {
                $lang->load('com_htprotect', $base, $tag, true, false);
            }
        } catch (Exception $e) {
            // fail-open
        } catch (Throwable $e) {
            // fail-open
        }
    }
}
