package com.red.circle.common.business.core.util;

import com.fasterxml.jackson.core.type.TypeReference;
import com.red.circle.tool.core.json.JacksonUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 国家码别名工具.
 */
public final class CountryCodeAliasUtils {

  private static final String SA = "SA";
  private static final String KSA = "KSA";
  private static final String PK = "PK";
  private static final String PAK = "PAK";
  private static final Map<String, Set<String>> COUNTRY_CODE_ALIAS_GROUPS;

  static {
    Map<String, Set<String>> aliasGroups = new LinkedHashMap<>();
    aliasGroups.put(SA, Set.of(SA, KSA));
    aliasGroups.put(PK, Set.of(PK, PAK, "P2", "P3"));
    COUNTRY_CODE_ALIAS_GROUPS = Collections.unmodifiableMap(aliasGroups);
  }

  private CountryCodeAliasUtils() {
  }

  /**
   * 归一化国家码.
   */
  public static String normalize(String code) {
    return StringUtils.isBlank(code) ? null : code.trim().toUpperCase();
  }

  /**
   * 沙特兼容归一化，保留非沙特国家原有写法.
   */
  public static String normalizeSaudiCode(String code) {
    String normalized = normalize(code);
    return isSaudiCode(normalized) ? SA : normalized;
  }

  /**
   * 支付国家码归一化，三方不识别的业务别名会转换为真实国家码.
   */
  public static String normalizePaymentCountryCode(String code) {
    String normalized = normalize(code);
    if (StringUtils.isBlank(normalized)) {
      return null;
    }

    return COUNTRY_CODE_ALIAS_GROUPS.entrySet().stream()
        .filter(entry -> entry.getValue().contains(normalized))
        .map(Map.Entry::getKey)
        .findFirst()
        .orElse(normalized);
  }

  /**
   * 是否是沙特国家码.
   */
  public static boolean isSaudiCode(String code) {
    String normalized = normalize(code);
    return SA.equals(normalized) || KSA.equals(normalized);
  }

  /**
   * 获取国家码别名集合.
   */
  public static Set<String> legacyAliases(String code) {
    return buildMatchCodes(code, null, Collections.emptyList());
  }

  /**
   * 解析存储中的别名数组.
   */
  public static List<String> parseAliasCodes(String aliasCodes) {
    if (StringUtils.isBlank(aliasCodes)) {
      return Collections.emptyList();
    }

    try {
      List<String> values = JacksonUtils.readValue(aliasCodes, new TypeReference<List<String>>() {});
      return normalizeCodes(values);
    } catch (Exception ignore) {
      return normalizeCodes(List.of(aliasCodes.split(",")));
    }
  }

  /**
   * 序列化别名数组到存储值.
   */
  public static String toAliasCodesJson(Collection<String> aliasCodes) {
    List<String> values = normalizeCodes(aliasCodes);
    if (values.isEmpty()) {
      return "";
    }
    return JacksonUtils.toJson(values);
  }

  /**
   * 构造完整匹配国家码集合.
   */
  public static Set<String> buildMatchCodes(String alphaTwo, String alphaThree,
      Collection<String> aliasCodes) {
    LinkedHashSet<String> result = new LinkedHashSet<>();
    appendCode(result, alphaTwo);
    appendCode(result, alphaThree);
    if (aliasCodes != null) {
      aliasCodes.forEach(code -> appendCode(result, code));
    }

    LinkedHashSet<String> originalCodes = new LinkedHashSet<>(result);
    for (String code : originalCodes) {
      result.addAll(aliasGroupCodes(code));
    }
    return result;
  }

  /**
   * 规范化国家码列表.
   */
  public static List<String> normalizeCodes(Collection<String> codes) {
    if (codes == null || codes.isEmpty()) {
      return Collections.emptyList();
    }
    LinkedHashSet<String> result = new LinkedHashSet<>();
    codes.stream().map(CountryCodeAliasUtils::normalize).filter(StringUtils::isNotBlank)
        .forEach(result::add);
    return new ArrayList<>(result);
  }

  private static void appendCode(Set<String> result, String code) {
    String normalized = normalize(code);
    if (StringUtils.isNotBlank(normalized)) {
      result.add(normalized);
    }
  }

  private static Set<String> aliasGroupCodes(String code) {
    String normalized = normalizePaymentCountryCode(code);
    if (StringUtils.isBlank(normalized)) {
      return Collections.emptySet();
    }
    return COUNTRY_CODE_ALIAS_GROUPS.getOrDefault(normalized, Set.of(normalized));
  }
}
