package com.qunzhixinxi.hnqz.daemon.quartz.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qunzhixinxi.hnqz.daemon.quartz.entity.SingleMemberSettleSameAmountInSeveralMonths;
import com.qunzhixinxi.hnqz.daemon.quartz.entity.WmScorePackageSettleNote;
import com.qunzhixinxi.hnqz.daemon.quartz.mapper.WmScorePackageSettleNoteMapper;
import com.qunzhixinxi.hnqz.daemon.quartz.service.WmScorePackageSettleNoteService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * {@code WmScorePackageSettleNoteServiceImpl} 类
 *
 * @author Hengchen.Sun
 * @version 1.0.0
 * @date 2021-06-08
 * @since ver.1.0.0
 */
@Service
@AllArgsConstructor
@Slf4j
public class WmScorePackageSettleNoteServiceImpl extends ServiceImpl<WmScorePackageSettleNoteMapper, WmScorePackageSettleNote> implements WmScorePackageSettleNoteService {

	private WmScorePackageSettleNoteMapper wmScorePackageSettleNoteMapper;

	/**
	 * 计算指定部门对应的结算数据之和
	 *
	 * @param deptId
	 * @param subType
	 * @param startTime
	 * @param endTime
	 * @return
	 */
	@Override
	public List<WmScorePackageSettleNote> listSettleAmountByDeptId(Integer deptId, String subType, LocalDateTime startTime, LocalDateTime endTime) {
		return wmScorePackageSettleNoteMapper.listSettleAmountByDeptId(deptId, subType, startTime, endTime);
	}

	/**
	 * 同一用户，连续多月结算金额相同
	 * <p>
	 * 在A企业下，张三5月份结算了1000（加入是两个积分包500和500），六月份也结算了1000（400和600），这是连续两个月结算金额相同，应该把500、500、400、600四个积分包列出来
	 * 同一个用户，同一个月结算相同金额不算
	 *
	 * @param startTime 开始时间
	 * @param endTime   结束时间
	 * @return
	 */
	@Override
	public List<SingleMemberSettleSameAmountInSeveralMonths> singleMemberSettleSameAmountInSeveralMonths(LocalDateTime startTime, LocalDateTime endTime) {

		List<SingleMemberSettleSameAmountInSeveralMonths> list = wmScorePackageSettleNoteMapper.singleMemberSettleSameAmountInSeveralMonths(startTime, endTime);

		// 按照用户分组，然后按照月度分组
		Map<String, Map<String, List<SingleMemberSettleSameAmountInSeveralMonths>>> collect = list.stream().collect(Collectors.groupingBy(SingleMemberSettleSameAmountInSeveralMonths::getIdNumber,
				Collectors.groupingBy(e -> DateTimeFormatter.ofPattern(DatePattern.NORM_MONTH_PATTERN).format(LocalDateTime.parse(e.getSettleNoteCreateTime(), DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN))))));

		List<SingleMemberSettleSameAmountInSeveralMonths> riskList = new ArrayList<>(list.size());

		// 遍历结果
		for (Map.Entry<String, Map<String, List<SingleMemberSettleSameAmountInSeveralMonths>>> entry : collect.entrySet()) {
			// 如果 只有一个月结算自动跳过
			if (entry.getValue().size() <= 1){
				continue;
			}
			// 遍历个人
			Map<BigDecimal, List<SingleMemberSettleSameAmountInSeveralMonths>> temp = new HashMap<>();
			for (Map.Entry<String, List<SingleMemberSettleSameAmountInSeveralMonths>> ent : entry.getValue().entrySet()) {
				// 计算每个月份的金额
				Optional<BigDecimal> reduce = ent.getValue().stream().map(SingleMemberSettleSameAmountInSeveralMonths::getSettleAmount).filter(Objects::nonNull)
						.reduce(BigDecimal::add);

				if (!reduce.isPresent()) {
					break;
				}

				// 判断是否有相同的金额
				if (temp.containsKey(reduce.get())) {
					riskList.addAll(temp.get(reduce.get()));
					riskList.addAll(ent.getValue());
				}
				// 记录月份结算值
				else {
					temp.put(reduce.get(),ent.getValue());
				}
			}
		}

		return riskList;
	}

	/**
	 * 同一用户，连续多月结算金额超过限额
	 *
	 * @param startTime 开始时间
	 * @param endTime   结束时间
	 * @param limit     限额
	 * @return 运行结果
	 */
	@Override
	public List<SingleMemberSettleSameAmountInSeveralMonths> singleMemberSettleAmountOverrunInSeveralMonths(LocalDateTime startTime, LocalDateTime endTime, BigDecimal limit) {
		List<SingleMemberSettleSameAmountInSeveralMonths> list = wmScorePackageSettleNoteMapper.singleMemberSettleSameAmountInSeveralMonths(startTime, endTime);

		Map<String, List<SingleMemberSettleSameAmountInSeveralMonths>> collect = list.stream().collect(Collectors.groupingBy(SingleMemberSettleSameAmountInSeveralMonths::getIdNumber));

		List<SingleMemberSettleSameAmountInSeveralMonths> riskList = new ArrayList<>(list.size());

		for (Map.Entry<String, List<SingleMemberSettleSameAmountInSeveralMonths>> entry : collect.entrySet()) {

			List<SingleMemberSettleSameAmountInSeveralMonths> coll = entry.getValue().stream().filter(e -> e.getSettleAmount() != null).collect(Collectors.toList());

			BigDecimal tmp = BigDecimal.ZERO;
			for (SingleMemberSettleSameAmountInSeveralMonths e : coll) {
				tmp = tmp.add(e.getSettleAmount());
			}

			if (limit.subtract(tmp).doubleValue() < 0.01) {
				riskList.addAll(entry.getValue());
			}
		}

		return riskList;
	}

	/**
	 * 同一企业，当前月给多个用户支付相同金额
	 * <p>
	 * 统计逻辑通 singleMemberSettleSameAmountInSeveralMonths
	 *
	 * @param startTime   开始时间
	 * @param endTime     结束时间
	 * @param memberCount 统计个数
	 * @return 风控对象
	 */
	@Override
	public List<SingleMemberSettleSameAmountInSeveralMonths> singleEnterpriseSettleSameAmountForSeveralMembersInCurrentMonth(LocalDateTime startTime, LocalDateTime endTime, int memberCount) {
		List<SingleMemberSettleSameAmountInSeveralMonths> list = wmScorePackageSettleNoteMapper.singleMemberSettleSameAmountInSeveralMonths(startTime, endTime);

		// 按照企业分组，然后按照用户分组
		Map<String, Map<String, List<SingleMemberSettleSameAmountInSeveralMonths>>> collect = list.stream().collect(Collectors.groupingBy(SingleMemberSettleSameAmountInSeveralMonths::getDeptId,
				Collectors.groupingBy(SingleMemberSettleSameAmountInSeveralMonths::getIdNumber)));

		Set<SingleMemberSettleSameAmountInSeveralMonths> riskResult = new HashSet<>(list.size());

		// 遍历所有记录
		for (Map.Entry<String, Map<String, List<SingleMemberSettleSameAmountInSeveralMonths>>> entry : collect.entrySet()) {
			// 遍历所有人
			Map<BigDecimal, List<SingleMemberSettleSameAmountInSeveralMonths>> temp = new HashMap<>();
			for (Map.Entry<String, List<SingleMemberSettleSameAmountInSeveralMonths>> ent : entry.getValue().entrySet()) {
				// 计算每个人的结算金额
				Optional<BigDecimal> reduce = ent.getValue().stream().map(SingleMemberSettleSameAmountInSeveralMonths::getSettleAmount).filter(Objects::nonNull)
						.reduce(BigDecimal::add);

				if (!reduce.isPresent()) {
					continue;
				}

				if (temp.containsKey(reduce.get())) {
					riskResult.addAll(temp.get(reduce.get()));
					riskResult.addAll(ent.getValue());
				} else {
					temp.put(reduce.get(), ent.getValue());
				}

			}

		}
		return new ArrayList<>(riskResult);
	}
}
