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


import cn.hutool.core.date.DateUtil;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.numerical.AnCollectionUtils;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderReturn;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderReturnCredit;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderReturnCreditExample;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderReturnGoods;
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 CommonMergeRefundOrderCreditProcessService {

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

	/****************************************** 退单部分 ******************************************/
	@Autowired
	private UnifiedOrderReturnCreditMapper   unifiedOrderReturnCreditMapper;
	@Autowired
	private UnifiedOrderReturnCreditMapperEx unifiedOrderReturnCreditMapperEx;
	/****************************************** 退单部分 ******************************************/


	/**
	 * 处理 kdfka 重推单 问题
	 * <p>
	 * 处理方法
	 * kafkaUnifiedOrderReceive
	 * kafkaScoreOrderReceive
	 *
	 * @param unifiedOrderRefundEntity
	 * @param processRefundUnifiedOrderCreditList
	 */
	public List<UnifiedOrderReturnCredit> processRefundUnifiedOrderCreditBykafkaPushOrderReceive(
			UnifiedOrderReturn unifiedOrderRefundEntity,
			UnifiedOrderReturnGoods unifiedOrderReturnGoodsEntity,
			List<UnifiedOrderReturnCredit> processRefundUnifiedOrderCreditList
	) {

		List<UnifiedOrderReturnCredit> finalRefundOrderCreditList = new ArrayList<>();

		if (AnCollectionUtils.isEmpty(processRefundUnifiedOrderCreditList)) {
			// TODO 要报异常

			return finalRefundOrderCreditList;
		}

		List<Long> refundOutSnapshotOrderCreditId = processRefundUnifiedOrderCreditList.stream()
				.filter(o -> o.getOutSnapshotOrderCreditId() != null)
				.filter(AnLamdaUtils.distinctByKey(o -> o.getOutSnapshotOrderCreditId()))
				.map(o -> o.getOutSnapshotOrderCreditId()).collect(Collectors.toList());


		UnifiedOrderReturnCreditExample scoreOrderCreditExample4SaveOrUpdate = new UnifiedOrderReturnCreditExample();
		scoreOrderCreditExample4SaveOrUpdate.createCriteria()
				.andOrderSnEqualTo(unifiedOrderRefundEntity.getOrderSn())
				/* 因为同一个单有可能多个商品退单 */
//				.andGoodsIdEqualTo(unifiedOrderReturnGoodsEntity.getGoodsId())
				/* TODO 因为退运费问题 改的 */
				.andOutSnapshotOrderCreditIdIn(refundOutSnapshotOrderCreditId)
		;
		List<UnifiedOrderReturnCredit> existsDatabaseRefundOrderCreditList = unifiedOrderReturnCreditMapper.selectByExample(scoreOrderCreditExample4SaveOrUpdate);

		log.info("\n\n\nOrderCredit: \n退单流水表 已存在数据 : \n{}\n退单流水表 过来的数据 : \n{}\n\n\n",
				AnJsonUtils.toJson(existsDatabaseRefundOrderCreditList),
				AnJsonUtils.toJson(processRefundUnifiedOrderCreditList)
		);



		for (UnifiedOrderReturnCredit processRefundOrderCredit : processRefundUnifiedOrderCreditList) {

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


			// 新过来的数据在老的是不是存在
			List<UnifiedOrderReturnCredit> findByOutSnapshotIdRefundOrderCreditList = null;
			List<UnifiedOrderReturnCredit> findByManyRefundOrderCreditList          = null;


			boolean isRetry = false;

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

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

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

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

				isRetry = true;
			}

			if (isRetry) {

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

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


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

			}


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

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

				UnifiedOrderReturnCredit findedRefundOrderCredit = findByOutSnapshotIdRefundOrderCreditList.get(0);

				// TODO 好像没什么好更新的
				overWriteRefundCreditField(processRefundOrderCredit, findedRefundOrderCredit);

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

				finalRefundOrderCreditList.add(findedRefundOrderCredit);

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


				UnifiedOrderReturnCredit findedRefundOrderCredit = findByManyRefundOrderCreditList.get(0);

				overWriteRefundCreditField(processRefundOrderCredit, findedRefundOrderCredit);

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

				finalRefundOrderCreditList.add(findedRefundOrderCredit);


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

		log.info("\n\n\n\nRefund OrderCredit Final:\n{}\n\n\n\n", AnJsonUtils.toJson(finalRefundOrderCreditList));

		unifiedOrderReturnCreditMapper.deleteByExample(scoreOrderCreditExample4SaveOrUpdate);
		finalRefundOrderCreditList.forEach(unifiedOrderCredit -> {
			unifiedOrderReturnCreditMapperEx.insertSelective(unifiedOrderCredit);
		});


		return finalRefundOrderCreditList;
	}

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

		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());

	}

}
