package com.red.circle.other.infra.database.mongo.service.user.region.impl;

import com.google.common.collect.Maps;
import com.red.circle.other.infra.database.mongo.entity.user.region.SysRegionConfig;
import com.red.circle.other.infra.database.mongo.service.user.region.SysRegionConfigService;
import com.red.circle.other.inner.model.cmd.user.SysRegionConfigQryCmd;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.date.TimestampUtils;
import com.red.circle.tool.core.text.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

/**
 * 区域.
 *
 * @author pengshigang on 2022/12/5.
 */
@Service
@RequiredArgsConstructor
public class SysRegionConfigServiceImpl implements SysRegionConfigService {

  private final MongoTemplate mongoTemplate;

  @Override
  public void add(SysRegionConfig config) {
    if (StringUtils.isBlank(config.getId())) {
      return;
    }
    config.setDel(Boolean.FALSE);
    config.setLangeCodes(StringUtils.toLowerCase(config.getLangeCodes()));
    config.setCountryCodes(StringUtils.toUpperCase(config.getCountryCodes()));
    mongoTemplate.save(config);
  }

  @Override
  public void update(SysRegionConfig config) {
    if (StringUtils.isBlank(config.getId())) {
      return;
    }
    config.setLangeCodes(StringUtils.toLowerCase(config.getLangeCodes()));
    config.setCountryCodes(StringUtils.toUpperCase(config.getCountryCodes()));
    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(config.getId())),
        new Update()
            .set("regionCode", config.getRegionCode())
            .set("countryCodes", config.getCountryCodes())
            .set("langeCodes", config.getLangeCodes())
            .set("regionName", config.getRegionName())
            .set("remarks", config.getRemarks())
            .set("metadata", config.getMetadata())
            .set("withdrawalWays", config.getWithdrawalWays())
            .set("diamondMetadata", config.getDiamondMetadata())
            .set("updateTime", config.getUpdateTime())
            .set("updateUser", config.getUpdateUser()), SysRegionConfig.class);

  }

  @Override
  public void deleteById(String id, Long updateUser) {

    mongoTemplate.updateFirst(Query.query(Criteria.where("id").is(id)),
        new Update().set("del", Boolean.TRUE)
            .set("updateUser", updateUser)
            .set("updateTime", TimestampUtils.now()),
        SysRegionConfig.class);

  }

  @Override
  public List<SysRegionConfig> listByCondition(SysRegionConfigQryCmd query) {

    Criteria criteria = Criteria.where("sysOrigin").is(query.getSysOrigin())
        .and("del").is(Boolean.FALSE);

    return mongoTemplate.find(Query.query(criteria)
            .with(Sort.by(Sort.Order.desc("createTime"))),
        SysRegionConfig.class);

  }

  @Override
  public Map<String, String> mapRegionName(Set<String> regionIds) {

    if (CollectionUtils.isEmpty(regionIds)) {
      return Maps.newHashMap();
    }

    return Optional.of(mongoTemplate
            .find(Query.query(Criteria.where("id").in(regionIds).and("del").is(Boolean.FALSE)),
                SysRegionConfig.class))
        .map(region -> region.stream().collect(
            Collectors.toMap(SysRegionConfig::getId,
                v -> StringUtils.isBlankOrElse(v.getRegionName(), ""))))
        .orElseGet(Maps::newHashMap);
  }

  @Override
  public String getRegionName(String regionId) {
    if (StringUtils.isBlank(regionId)) {
      return "";
    }
    return Optional.ofNullable(mongoTemplate
            .findOne(Query.query(Criteria.where("id").is(regionId).and("del").is(Boolean.FALSE)),
                SysRegionConfig.class))
        .map(SysRegionConfig::getRegionName)
        .orElse("");
  }

  @Override
  public SysRegionConfig getById(String id) {
    return mongoTemplate
        .findOne(Query.query(Criteria.where("id").is(id).and("del").is(Boolean.FALSE)),
            SysRegionConfig.class);
  }

  @Override
  public Map<String, String> mapRegionName(String sysOrigin) {

    if (StringUtils.isBlank(sysOrigin)) {
      return Maps.newHashMap();
    }
    return Optional.of(mongoTemplate.find(Query.query(Criteria.where("sysOrigin").is(sysOrigin)
                .and("del").is(Boolean.FALSE)),
            SysRegionConfig.class))
        .map(region -> region.stream().collect(
            Collectors.toMap(SysRegionConfig::getId,
                v -> StringUtils.isBlankOrElse(v.getRegionName(), ""))))
        .orElseGet(Maps::newHashMap);

  }

  @Override
  public Boolean existRegionCode(String regionCode, String notId) {
    return mongoTemplate.exists(Query.query(Criteria.where("id").ne(notId)
            .and("regionCode").is(regionCode).and("del").is(Boolean.FALSE)),
        SysRegionConfig.class);
  }


  @Override
  public Boolean existRegionCode(String regionCode, String notId, String sysOrigin) {
    return mongoTemplate.exists(Query.query(Criteria.where("id").ne(notId)
            .and("sysOrigin").is(sysOrigin)
            .and("regionCode").is(regionCode)
            .and("del").is(Boolean.FALSE)),
        SysRegionConfig.class);
  }

  @Override
  public List<SysRegionConfig> listAvailable(String sysOrigin) {
    return mongoTemplate.find(Query.query(Criteria.where("sysOrigin").is(sysOrigin)
            .and("del").is(Boolean.FALSE)),
        SysRegionConfig.class);
  }

  @Override
  public List<SysRegionConfig> listAvailable(Set<String> ids) {
    return mongoTemplate.find(Query.query(Criteria.where("id").in(ids)
            .and("del").is(Boolean.FALSE)),
        SysRegionConfig.class);
  }

  @Override
  public Map<String, SysRegionConfig> mapAvailable(Set<String> ids) {
    List<SysRegionConfig> regionConfigs = listAvailable(ids);

    if (CollectionUtils.isEmpty(regionConfigs)) {
      return CollectionUtils.newHashMap();
    }

    return regionConfigs.stream().collect(Collectors.toMap(SysRegionConfig::getId, v -> v));
  }

  @Override
  public SysRegionConfig getByRegionCode(String regionCode, String sysOrigin) {

    return mongoTemplate.findOne(Query.query(Criteria.where("sysOrigin").is(sysOrigin)
            .and("regionCode").is(regionCode)
            .and("del").is(Boolean.FALSE)),
        SysRegionConfig.class);

  }

  @Override
  public List<SysRegionConfig> getRegionCodeByLangeCodes(String langeCodes){
    return mongoTemplate.find(Query.query(Criteria.where("langeCodes").is(langeCodes)),
            SysRegionConfig.class);}
}
