package cloud.nstart.terravault.ordinis.readapi.locale;

import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

/**
 * Locale negotiation per RFC 7231: парсит Accept-Language, lookup'ает по
 * supported_locales справочника, fallback на default_locale.
 *
 * <p>Особенный случай — {@code Accept-Language: *} → возвращаем null, что
 * означает «отдай как есть, не сплющивай».
 */
@Component
public class LocaleNegotiator {

  /**
   * @return chosen locale (BCP 47 tag like "ru-RU"), либо null если клиент
   *         попросил wildcard "*" (= raw multi-locale в ответе).
   */
  public String negotiate(String acceptLanguage, String[] supported, String defaultLocale) {
    if (supported == null || supported.length == 0) {
      return defaultLocale;
    }
    if (acceptLanguage == null || acceptLanguage.isBlank()) {
      return defaultLocale;
    }
    if ("*".equals(acceptLanguage.trim())) {
      return null; // raw mode
    }

    try {
      List<Locale.LanguageRange> ranges = Locale.LanguageRange.parse(acceptLanguage);
      List<Locale> supportedLocales = new ArrayList<>(supported.length);
      for (String s : supported) supportedLocales.add(Locale.forLanguageTag(s));

      Locale chosen = Locale.lookup(ranges, supportedLocales);
      if (chosen != null) {
        return chosen.toLanguageTag();
      }
    } catch (IllegalArgumentException ignore) {
      // malformed Accept-Language → fall through to default
    }
    return defaultLocale;
  }

  /**
   * Поддерживаемые локали справочника как list для удобства логирования.
   */
  public List<String> supportedAsList(String[] supported) {
    return supported == null ? List.of() : Arrays.asList(supported);
  }
}
