package com.red.circle.other.infra.common.sys;

import com.red.circle.common.business.core.util.CountryCodeAliasUtils;
import com.red.circle.other.infra.database.rds.entity.sys.SysCountryCode;
import com.red.circle.other.infra.database.rds.service.sys.SysCountryCodeService;
import com.red.circle.tool.core.text.StringUtils;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;

/**
 * 国家码别名支持.
 */
@Component
@RequiredArgsConstructor
public class CountryCodeAliasSupport {

  private final SysCountryCodeService sysCountryCodeService;

  /**
   * 获取某个国家码的全部可匹配代码.
   */
  public Set<String> getMatchCodes(String code) {
    String normalized = CountryCodeAliasUtils.normalize(code);
    if (StringUtils.isBlank(normalized)) {
      return Collections.emptySet();
    }

    SysCountryCode sysCountryCode = sysCountryCodeService.getByCode(normalized);
    if (sysCountryCode == null) {
      return CountryCodeAliasUtils.legacyAliases(normalized);
    }

    return CountryCodeAliasUtils.buildMatchCodes(sysCountryCode.getAlphaTwo(),
        sysCountryCode.getAlphaThree(),
        CountryCodeAliasUtils.parseAliasCodes(sysCountryCode.getAliasCodes()));
  }

  /**
   * 扩展多组国家码.
   */
  public Set<String> expandCodes(Collection<String> codes) {
    if (codes == null || codes.isEmpty()) {
      return Collections.emptySet();
    }

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

  /**
   * 两个国家码是否匹配.
   */
  public boolean matches(String leftCode, String rightCode) {
    Set<String> leftCodes = getMatchCodes(leftCode);
    Set<String> rightCodes = getMatchCodes(rightCode);
    if (leftCodes.isEmpty() || rightCodes.isEmpty()) {
      return false;
    }
    return leftCodes.stream().anyMatch(rightCodes::contains);
  }

  /**
   * 逗号分隔国家列表是否包含指定国家码.
   */
  public boolean containsCode(String csvCodes, String countryCode) {
    if (StringUtils.isBlank(csvCodes) || StringUtils.isBlank(countryCode)) {
      return false;
    }
    return Arrays.stream(csvCodes.split(","))
        .map(CountryCodeAliasUtils::normalize)
        .filter(StringUtils::isNotBlank)
        .anyMatch(code -> matches(code, countryCode));
  }
}
