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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.springframework.stereotype.Component;

import java.util.Iterator;
import java.util.Map;

/**
 * Сплющивает multi-locale JSON в плоское значение по выбранной локали.
 *
 * <p>Walk проходит {@code schemaJson.properties}, для каждого property с
 * {@code x-localized: true} в {@code data} заменяет object {@code {locale:text}}
 * на string выбранной локали. Если выбранной нет — fallback на default.
 *
 * <p>Если {@code chosenLocale == null} — возвращает data как есть (raw multi-locale).
 */
@Component
public class LocaleAwareJsonFlattener {

  private final ObjectMapper objectMapper;

  public LocaleAwareJsonFlattener(ObjectMapper objectMapper) {
    this.objectMapper = objectMapper;
  }

  /**
   * @param schema schema_json справочника
   * @param data текущая запись (полный multi-locale)
   * @param chosenLocale выбранная локаль, или null для raw
   * @param defaultLocale fallback если chosenLocale нет в data
   */
  public JsonNode flatten(JsonNode schema, JsonNode data, String chosenLocale, String defaultLocale) {
    if (chosenLocale == null) {
      return data;
    }
    if (data == null || !data.isObject()) {
      return data;
    }
    ObjectNode out = data.deepCopy();
    walkAndFlatten(schema, out, chosenLocale, defaultLocale);
    return out;
  }

  private void walkAndFlatten(JsonNode schema, ObjectNode data, String locale, String defaultLocale) {
    if (schema == null || !schema.isObject()) return;
    JsonNode properties = schema.get("properties");
    if (properties == null || !properties.isObject()) return;

    Iterator<Map.Entry<String, JsonNode>> it = properties.fields();
    while (it.hasNext()) {
      Map.Entry<String, JsonNode> entry = it.next();
      String fieldName = entry.getKey();
      JsonNode fieldSchema = entry.getValue();

      JsonNode xLocalized = fieldSchema.get("x-localized");
      if (xLocalized != null && xLocalized.isBoolean() && xLocalized.asBoolean()) {
        flattenLocalizedField(data, fieldName, locale, defaultLocale);
      } else if (fieldSchema.has("properties") && data.has(fieldName) && data.get(fieldName).isObject()) {
        walkAndFlatten(fieldSchema, (ObjectNode) data.get(fieldName), locale, defaultLocale);
      }
    }
  }

  private void flattenLocalizedField(ObjectNode data, String field, String locale, String defaultLocale) {
    JsonNode value = data.get(field);
    if (value == null || !value.isObject()) return;

    JsonNode picked = value.get(locale);
    if (picked == null || picked.isNull()) {
      picked = value.get(defaultLocale);
    }
    if (picked == null || picked.isNull()) {
      // ни запрошенной, ни default нет — оставляем null
      data.set(field, objectMapper.nullNode());
    } else {
      data.set(field, picked);
    }
  }
}
