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

import com.google.common.collect.Maps;
import com.red.circle.other.infra.database.mongo.dto.team.TeamPolicy;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService;
import com.red.circle.other.inner.enums.team.TeamPolicyTypeEnum;
import com.red.circle.tool.core.collection.CollectionUtils;
import com.red.circle.tool.core.text.StringUtils;
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;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 团队策略.
 *
 * @author pengshigang on 2022/12/12
 */
@Service
@RequiredArgsConstructor
public class TeamPolicyManagerServiceImpl implements TeamPolicyManagerService {

  private final MongoTemplate mongoTemplate;

  @Override
  public List<TeamPolicyManager> listSysOriginRegion(String sysOrigin, String region) {
    return mongoTemplate
        .find(Query.query(Criteria.where("region").is(region)
                .and("sysOrigin").is(sysOrigin)).with(Sort.by(Sort.Order.desc("createTime"))),
            TeamPolicyManager.class);
  }

  @Override
  public List<TeamPolicyManager> listTeamPolicy(String sysOrigin, String region) {
    return mongoTemplate
        .find(Query.query(Criteria.where("region").is(region)
                    .and("sysOrigin").is(sysOrigin))
                .with(Sort.by(Sort.Order.desc("createTime"))),
            TeamPolicyManager.class);
  }

  @Override
  public List<TeamPolicyManager> listTeamPolicyAndTypePolicy(String sysOrigin, String region,
                                                             String policyType, String countryCode) {
    Criteria criteria = new Criteria();
    criteria.and("region").is(region);
    criteria.and("sysOrigin").is(sysOrigin);
    if (StringUtils.isNotBlank(policyType) && Objects.equals(policyType, TeamPolicyTypeEnum.SALARY_DIAMOND.name())) {
      criteria.and("policyType").is(policyType);
    }else {
      criteria.and("policyType").ne(TeamPolicyTypeEnum.SALARY_DIAMOND.name());
    }
    if (StringUtils.isNotBlank(countryCode)) {
      criteria.and("countryCode").is(countryCode);
    }

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

  @Override
  public List<TeamPolicyManager> listReleaseTeamPolicy(String sysOrigin, String region) {
    return mongoTemplate
        .find(Query.query(Criteria.where("region").is(region)
                    .and("release").is(Boolean.TRUE)
                    .and("sysOrigin").is(sysOrigin))
                .with(Sort.by(Sort.Order.desc("createTime"))),
            TeamPolicyManager.class);
  }


  @Override
  public TeamPolicyManager getReleaseByRegionAndType(String sysOrigin, String region) {
    return mongoTemplate.findOne(Query.query(
        Criteria.where("region").is(region)
            .and("release").is(Boolean.TRUE)
            .and("sysOrigin").is(sysOrigin)
    ), TeamPolicyManager.class);
  }

  @Override
  public TeamPolicyManager getReleaseByRegionAndType(String sysOrigin, String region, String policyType,  String countryCode) {

    Criteria criteria = new Criteria();
    criteria.and("region").is(region);
    criteria.and("release").is(Boolean.TRUE);
    criteria.and("sysOrigin").is(sysOrigin);
    if (StringUtils.isNotBlank(policyType) && Objects.equals(policyType, TeamPolicyTypeEnum.SALARY_DIAMOND.name())) {
      criteria.and("policyType").is(policyType);
    }else {
      criteria.and("policyType").ne(TeamPolicyTypeEnum.SALARY_DIAMOND.name());
    }
    if (StringUtils.isNotBlank(countryCode)) {
      criteria.and("countryCode").is(countryCode);
    }

    return mongoTemplate.findOne(Query.query(criteria), TeamPolicyManager.class);
  }

  @Override
  public Map<String, TeamPolicyManager> mapRegionRelease(Set<String> regions) {

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

    List<TeamPolicyManager> teamPolicyManagers = mongoTemplate.find(
        Query.query(Criteria.where("region").in(regions).and("release").is(Boolean.TRUE)),
        TeamPolicyManager.class);

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

    return teamPolicyManagers.stream()
        .collect(Collectors.toMap(TeamPolicyManager::getRegion, v -> v));
  }

  @Override
  public Map<String, TeamPolicyManager> mapRegionReleaseWithCountry(Set<String> regions) {

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

    // 查询所有 region 的已发布政策（所有 countryCode）
    List<TeamPolicyManager> policies = mongoTemplate.find(
        Query.query(Criteria.where("region").in(regions)
            .and("release").is(Boolean.TRUE)),
        TeamPolicyManager.class);

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

    // 构建Map，key = region + "_" + countryCode
    return policies.stream()
        .collect(Collectors.toMap(
            policy -> buildPolicyMapKey(policy.getRegion(), policy.getCountryCode()),
            policy -> policy,
            (existing, replacement) -> existing
        ));
  }

  /**
   * 构建policy map的key.
   */
  private String buildPolicyMapKey(String region, String countryCode) {
    String delimiter = "_";
    String defaultCountry = "DEFAULT";
    return region + delimiter +
        (StringUtils.isNotBlank(countryCode) ? countryCode : defaultCountry);
  }

  @Override
  public TeamPolicyManager getById(Long id) {
    return mongoTemplate.findOne(Query.query(Criteria.where("id").is(id)), TeamPolicyManager.class);
  }

  @Override
  public void add(TeamPolicyManager policyManager) {
    policyManager.setHistoryRelease(Boolean.FALSE);

    if (Boolean.TRUE.equals(policyManager.getRelease()) && StringUtils
        .isNotBlank(policyManager.getRegion())
        && StringUtils.isNotBlank(policyManager.getSysOrigin())) {

      policyManager.setHistoryRelease(Boolean.TRUE);
    }

    policyManager.setPolicy(policyManager.getPolicy().stream()
        .sorted(Comparator.comparing(TeamPolicy::getLevel))
        .collect(Collectors.toList()));
    mongoTemplate.save(policyManager);
  }

  @Override
  public void deleteById(Long id) {

    mongoTemplate.remove(Query.query(Criteria.where("id").is(id)), TeamPolicyManager.class);
  }

}
