package cn.superdesk.uniorder.service.order.base;


import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.superdesk.uniorder.common.enums.common.CommonDirectionEnum;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.numerical.AnCollectionUtils;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrder;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderCredit;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderCreditExample;
import cn.superdesk.uniorder.dao.mapper.base.*;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;


/**
 * @Description: 重构 处理 合并数据 不写 interface
 * @Author: linjinyu
 * @CreateDate: 9/15/20 5:03 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 9/15/20 5:03 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@Service
public class CommonMergeOrderCreditProcessService {

	@Autowired
	private UnifiedOrderMapper         unifiedOrderMapper;
	@Autowired
	private UnifiedOrderGoodsMapper    unifiedOrderGoodsMapper;
	@Autowired
	private UnifiedOrderGoodsMapperEx  unifiedOrderGoodsMapperEx;
	@Autowired
	private UnifiedOrderCreditMapper   unifiedOrderCreditMapper;
	@Autowired
	private UnifiedOrderCreditMapperEx unifiedOrderCreditMapperEx;


	/**
	 * 处理 kdfka 重推单 问题
	 * <p>
	 * 处理方法
	 * kafkaUnifiedOrderReceive
	 * kafkaScoreOrderReceive
	 *
	 * @param unifiedOrderEntity
	 * @param processUnifiedOrderCreditList
	 */
	public void processUnifiedOrderCreditBykafkaPushOrderReceive(
			UnifiedOrder unifiedOrderEntity,
			List<UnifiedOrderCredit> processUnifiedOrderCreditList,
			Integer direction
	) {

		// 积分订单
		// 之前是先删除再 插入
//		UnifiedOrderCreditExample scoreOrderCreditExample4Delete = new UnifiedOrderCreditExample();
//		scoreOrderCreditExample4Delete.createCriteria()
//				.andOrderSnEqualTo(unifiedOrderEntity.getOrderSn());
//		unifiedOrderCreditMapper.deleteByExample(scoreOrderCreditExample4Delete);
//		processUnifiedOrderCreditList.forEach(unifiedOrderCredit -> {
//			unifiedOrderCreditMapper.insert(unifiedOrderCredit);
//		});

		log.info("processUnifiedOrderCreditBykafkaPushOrderReceive UnifiedOrder\n{}", AnJsonUtils.toPrettyJson(unifiedOrderEntity));

		if (null == unifiedOrderEntity) {
			log.error("processUnifiedOrderCreditBykafkaPushOrderReceive UnifiedOrder 是 null ");
			return;
		}

		if (CollUtil.isEmpty(processUnifiedOrderCreditList)) {
			return;
		}

		UnifiedOrderCreditExample          orderCreditExample4SaveOrUpdate  = new UnifiedOrderCreditExample();
		UnifiedOrderCreditExample.Criteria orderCreditCriteria4SaveOrUpdate = orderCreditExample4SaveOrUpdate.createCriteria();
		orderCreditCriteria4SaveOrUpdate
				// 新逻辑 不在这里加条件 mark by linjinyu at 20210701
//				.andOrderSnEqualTo(unifiedOrderEntity.getOrderSn())
				// 20201017 12:39 add 之前可能是这样把退单的数据清了
				.andDirectionEqualTo(direction);
		// TODO 超级前台的统一订单 目前不存在流水 所以没问题
		// 因为退单 退的商品只有 1
		if (direction.equals(CommonDirectionEnum.负向.getKey())) {

			// 此逻辑是为了框定范围,因为会有多次退单
			List<Long> processGoodsIds = processUnifiedOrderCreditList.stream().filter(AnLamdaUtils.distinctByKey(o -> o.getGoodsId())).map(o -> o.getGoodsId()).collect(Collectors.toList());
			if (AnCollectionUtils.isNotEmpty(processGoodsIds)) {
				orderCreditCriteria4SaveOrUpdate.andGoodsIdIn(processGoodsIds);
			}

			// 因为如果这个数据不纠,再有退单的数据过来就会叠了,好好想想

			/****************************************** 早前的数据纠一下,好像只是改个单号不会影响对账单关系 start ******************************************/
			List<String> orderSns = new ArrayList<>();
			orderSns.add(unifiedOrderEntity.getOrderSn());
			orderSns.add(unifiedOrderEntity.getRefundOrderSn());

			orderCreditCriteria4SaveOrUpdate.andOrderSnIn(orderSns);
			/****************************************** 早前的数据纠一下,好像只是改个单号不会影响对账单关系 start ******************************************/

		} else {
			orderCreditCriteria4SaveOrUpdate.andOrderSnEqualTo(unifiedOrderEntity.getOrderSn());
		}

		List<UnifiedOrderCredit> existsDatabaseUnifiedOrderCreditList = unifiedOrderCreditMapper.selectByExample(orderCreditExample4SaveOrUpdate);

		log.info("\n\n\nOrderCredit: \n已存在数据 : \n{}\n过来的数据 : \n{}\n\n\n",
				AnJsonUtils.toJson(existsDatabaseUnifiedOrderCreditList),
				AnJsonUtils.toJson(processUnifiedOrderCreditList)
		);

		List<UnifiedOrderCredit> finalUnifiedOrderCreditList = new ArrayList<>();

		for (UnifiedOrderCredit processOrderCredit : processUnifiedOrderCreditList) {

			/****************************************** 情况1 ******************************************/


			// 新过来的数据在老的是不是存在
			List<UnifiedOrderCredit> findByOutSnapshotIdOrderCreditList = null;
			List<UnifiedOrderCredit> findByManyOrderCreditList          = null;


			boolean isRetry = false;

			// 先是判定过来的这个流水Id 是不是合法
			if (processOrderCredit.getOutSnapshotOrderCreditId() != null && !processOrderCredit.getOutSnapshotOrderCreditId().equals(0L)) {

				// 这里的前题条件 已经是同样的 orderSn 所以这个可以看作为 orderSn + OutSnapshotOrderCreditId
				List<Predicate<UnifiedOrderCredit>> predicatesByOne = new ArrayList<>();
				predicatesByOne.add(r -> null != r.getOutSnapshotOrderCreditId() && r.getOutSnapshotOrderCreditId().equals(processOrderCredit.getOutSnapshotOrderCreditId()));

				// 如果本来数据 是没这个流水Id 是找不出来的
				findByOutSnapshotIdOrderCreditList = AnLamdaUtils.filters(existsDatabaseUnifiedOrderCreditList, predicatesByOne);

				// 当 商城
				// 前题是 同样的orderSn
				// 流水有这个流水ID 这个流水ID在统一订单中找到
				if (AnCollectionUtils.isEmpty(findByOutSnapshotIdOrderCreditList)) {
					isRetry = true;
				}
			} else {

				isRetry = true;
			}

			if (isRetry) {

//				// 查询条件 如果 goods_id 为 0 条数大于 1 是会有问题 0 默认只有运费 , 如果 附件与赠品过来的情况 就会有问题,具体的问题再写吧
				List<Predicate<UnifiedOrderCredit>> predicatesByMany = new ArrayList<>();

				// 20201016 add start 从数据上看,是会有可能 同样的 orderId 不同的 orderSn
				predicatesByMany.add(
						r -> r.getOrderSn().equals(processOrderCredit.getOrderSn())
								&& r.getOrderId().equals(processOrderCredit.getOrderId())
								&& r.getGoodsId().equals(processOrderCredit.getGoodsId())
								&& r.getCreditType().equals(processOrderCredit.getCreditType())
//                                && r.getCreditName().equals(processOrderCredit.getCreditName())
								&& r.getBalance().compareTo(processOrderCredit.getBalance()) == 0
								&& r.getBatchs().equals(processOrderCredit.getBatchs())
				);
				// 20201016 add end

//				// 新过来的数据在老的是不是存在
				findByManyOrderCreditList = AnLamdaUtils.filters(existsDatabaseUnifiedOrderCreditList, predicatesByMany);

			}


			/****************************************** 情况1 ******************************************/

			// 如果第一次找到了
			if (AnCollectionUtils.isNotEmpty(findByOutSnapshotIdOrderCreditList)) {

				UnifiedOrderCredit findedOrderCredit = findByOutSnapshotIdOrderCreditList.get(0);

				overWriteCreditField(processOrderCredit, findedOrderCredit);

				findedOrderCredit.setUpdateUserId(2L);
				findedOrderCredit.setUpdateTime(DateUtil.date());

				finalUnifiedOrderCreditList.add(findedOrderCredit);

			}
			// 只有 isExistsOrderCredit == null 时 isRetry 才会为true
			else if (isRetry && AnCollectionUtils.isNotEmpty(findByManyOrderCreditList)) {

				UnifiedOrderCredit findedOrderCredit = findByManyOrderCreditList.get(0);

				overWriteCreditField(processOrderCredit, findedOrderCredit);

				findedOrderCredit.setUpdateUserId(3L);
				findedOrderCredit.setUpdateTime(DateUtil.date());

				finalUnifiedOrderCreditList.add(findedOrderCredit);

			}
			// 两种情况都不存 才会作为新数据插入
			else {
				finalUnifiedOrderCreditList.add(processOrderCredit);
			}
		}


		unifiedOrderCreditMapper.deleteByExample(orderCreditExample4SaveOrUpdate);

		log.info("\n\n\n\nOrderCredit Final:\n{}\n\n\n\n", AnJsonUtils.toJson(finalUnifiedOrderCreditList));

		finalUnifiedOrderCreditList.forEach(unifiedOrderCredit -> {
			unifiedOrderCreditMapperEx.insertSelective(unifiedOrderCredit);
		});

	}

	/**
	 * 覆写字段
	 *
	 * @param processOrderCredit
	 * @param findedOrderCredit
	 */
	private void overWriteCreditField(UnifiedOrderCredit processOrderCredit, UnifiedOrderCredit findedOrderCredit) {

		// TODO 新的业务逻辑 退单作为新主体时这个地方是要覆写一下 纠一下 mark by linjinyu at 20210701
		findedOrderCredit.setOrderSn(processOrderCredit.getOrderSn());

		findedOrderCredit.setCreditType(processOrderCredit.getCreditType());
		findedOrderCredit.setCreditName(processOrderCredit.getCreditName());
		findedOrderCredit.setOutSnapshotOrderCreditId(processOrderCredit.getOutSnapshotOrderCreditId());
		findedOrderCredit.setGoodsId(processOrderCredit.getGoodsId());
		findedOrderCredit.setDailyAccountType(processOrderCredit.getDailyAccountType());
		findedOrderCredit.setBatchs(processOrderCredit.getBatchs());
		findedOrderCredit.setBalance(processOrderCredit.getBalance());
		findedOrderCredit.setEnterpriseId(processOrderCredit.getEnterpriseId());
		findedOrderCredit.setMemberId(processOrderCredit.getMemberId());
		findedOrderCredit.setPayStatus(processOrderCredit.getPayStatus());
		findedOrderCredit.setPayType(processOrderCredit.getPayType());

	}

}
