package de.assecutor.votianlt.config;

import com.vaadin.flow.i18n.I18NProvider;
import de.assecutor.votianlt.model.Language;
import org.springframework.stereotype.Component;

import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.ResourceBundle.Control;

@Component
public class TranslationProvider implements I18NProvider {

    public static final String BUNDLE_PREFIX = "messages";
    private static final Locale DEFAULT_LOCALE = Locale.GERMAN;

    // Custom Control to map language codes to file names
    private static final Control BUNDLE_CONTROL = new Control() {
        @Override
        public List<Locale> getCandidateLocales(String baseName, Locale locale) {
            // Map Estonian "et" to "ee" file, Latvian "lv" to "lv", Lithuanian "lt" to "lt"
            String language = locale.getLanguage();

            // Create a locale that matches our file naming convention
            Locale mappedLocale = switch (language) {
            case "et" -> Locale.of("ee"); // Estonian -> messages_ee.properties
            case "lv" -> Locale.of("lv"); // Latvian -> messages_lv.properties
            case "lt" -> Locale.of("lt"); // Lithuanian -> messages_lt.properties
            case "ru" -> Locale.of("ru"); // Russian -> messages_ru.properties
            case "pl" -> Locale.of("pl"); // Polish -> messages_pl.properties
            case "tr" -> Locale.of("tr"); // Turkish -> messages_tr.properties
            case "es" -> Locale.of("es"); // Spanish -> messages_es.properties
            case "fr" -> Locale.of("fr"); // French -> messages_fr.properties
            case "en" -> Locale.of("en"); // English -> messages_en.properties
            case "de" -> Locale.of("de"); // German -> messages_de.properties
            default -> locale;
            };

            return super.getCandidateLocales(baseName, mappedLocale);
        }
    };

    @Override
    public List<Locale> getProvidedLocales() {
        return Collections.unmodifiableList(Arrays.asList(Locale.GERMAN, Locale.ENGLISH, Locale.FRENCH,
                Locale.of("es", "ES"), Locale.of("tr", "TR"), Locale.of("pl", "PL"), Locale.of("ru", "RU"),
                Locale.of("et", "EE"), Locale.of("lv", "LV"), Locale.of("lt", "LT")));
    }

    @Override
    public String getTranslation(String key, Locale locale, Object... params) {
        if (key == null) {
            return "";
        }

        try {
            String value = findTranslation(key, locale);
            if (value == null) {
                return key;
            }

            if (params.length > 0) {
                value = MessageFormat.format(value, params);
            }

            return value;
        } catch (MissingResourceException e) {
            return key;
        }
    }

    private String findTranslation(String key, Locale locale) {
        Locale effectiveLocale = locale != null ? locale : DEFAULT_LOCALE;
        ResourceBundle localizedBundle = ResourceBundle.getBundle(BUNDLE_PREFIX, effectiveLocale, BUNDLE_CONTROL);
        if (localizedBundle.containsKey(key)) {
            return localizedBundle.getString(key);
        }

        if (!DEFAULT_LOCALE.getLanguage().equals(effectiveLocale.getLanguage())) {
            ResourceBundle germanBundle = ResourceBundle.getBundle(BUNDLE_PREFIX, DEFAULT_LOCALE, BUNDLE_CONTROL);
            if (germanBundle.containsKey(key)) {
                return germanBundle.getString(key);
            }
        }

        return null;
    }

    public String getTranslation(String key, Language language) {
        Locale locale = switch (language) {
        case DE -> Locale.GERMAN;
        case EN -> Locale.ENGLISH;
        case FR -> Locale.FRENCH;
        case ES -> Locale.of("es", "ES");
        case TR -> Locale.of("tr", "TR");
        case PL -> Locale.of("pl", "PL");
        case RU -> Locale.of("ru", "RU");
        case EE -> Locale.of("et", "EE");
        case LV -> Locale.of("lv", "LV");
        case LT -> Locale.of("lt", "LT");
        };
        return getTranslation(key, locale);
    }
}
