package com.red.circle.other.app.scheduler;

import com.google.common.collect.Lists;
import com.red.circle.component.redis.annotation.TaskCacheLock;
import com.red.circle.mq.rocket.business.producer.TeamSalaryMqMessage;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamPolicyManager;
import com.red.circle.other.infra.database.mongo.entity.team.team.TeamProfile;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamPolicyManagerService;
import com.red.circle.other.infra.database.mongo.service.team.team.TeamProfileService;
import com.red.circle.other.inner.model.dto.agency.agency.TeamStatus;
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.sql.Timestamp;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * 团队政策待生效切换任务.
 */
@Slf4j
@Component
@AllArgsConstructor
public class TeamPolicyActivationTask {

  private final TeamPolicyManagerService teamPolicyManagerService;
  private final TeamProfileService teamProfileService;
  private final TeamSalaryMqMessage teamSalaryMqMessage;

  /**
   * 每5分钟补偿激活已到生效时间的政策，避免服务短暂不可用导致漏切换.
   */
  @Scheduled(cron = "15 0/5 * * * ?", zone = "Asia/Riyadh")
  @TaskCacheLock(key = "TEAM_POLICY_ACTIVATION_TASK", expireSecond = 300)
  public void activateScheduledPolicies() {
    long startTime = System.currentTimeMillis();
    Timestamp now = TimestampUtils.now();
    List<TeamPolicyManager> policies = teamPolicyManagerService.listDueScheduledPolicies(now);
    if (CollectionUtils.isEmpty(policies)) {
      return;
    }

    Set<String> refreshedRegions = new HashSet<>();
    int activatedCount = 0;
    for (TeamPolicyManager policy : policies) {
      TeamPolicyManager activatedPolicy = teamPolicyManagerService.activateScheduledPolicy(policy.getId(), now);
      if (Objects.isNull(activatedPolicy)) {
        continue;
      }
      activatedCount++;
      String refreshKey = buildRefreshKey(activatedPolicy);
      if (refreshedRegions.add(refreshKey)) {
        refreshUnpaidBills(activatedPolicy);
      }
    }

    log.info("exec team_policy_activation_task activated={}, cost={}",
        activatedCount, System.currentTimeMillis() - startTime);
  }

  private void refreshUnpaidBills(TeamPolicyManager policy) {
    if (Objects.isNull(policy)
        || StringUtils.isBlank(policy.getSysOrigin())
        || StringUtils.isBlank(policy.getRegion())) {
      return;
    }

    List<TeamProfile> teamProfiles = Optional.ofNullable(teamProfileService.listRegionAll(policy.getRegion()))
        .orElse(Lists.newArrayList())
        .stream()
        .filter(teamProfile -> Objects.equals(TeamStatus.AVAILABLE, teamProfile.getStatus()))
        .filter(teamProfile -> Objects.equals(policy.getSysOrigin(), teamProfile.getSysOrigin()))
        .collect(Collectors.toList());

    if (CollectionUtils.isEmpty(teamProfiles)) {
      return;
    }

    Lists.partition(teamProfiles, 200).forEach(teamList -> teamSalaryMqMessage.sendSalaryCount(
        teamList.stream().map(TeamProfile::getId).collect(Collectors.toSet())));
  }

  private String buildRefreshKey(TeamPolicyManager policy) {
    return policy.getSysOrigin() + ":" + policy.getRegion();
  }
}
