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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.superdesk.uniorder.common.enums.common.CommonDirectionEnum;
import cn.superdesk.uniorder.common.enums.common.CommonOrderGoodsUnitEnum;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrder;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoods;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoodsExample;
import cn.superdesk.uniorder.dao.mapper.base.*;
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 CommonMergeOrderGoodsProcessService {

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

    /**
     * 处理 kdfka 重推单 问题
     *
     * @param unifiedOrderEntity
     * @param processUnifiedOrderGoodsList
     */
    public void processUnifiedOrderGoodsBykafkaPushOrderReceive(
            UnifiedOrder unifiedOrderEntity,
            List<UnifiedOrderGoods> processUnifiedOrderGoodsList,
            Integer direction
    ) {

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

        if (null == unifiedOrderEntity) {
            log.error("processUnifiedOrderGoodsBykafkaPushOrderReceive UnifiedOrder 是 null ");

            return;
        }


        // 一般订单
        // 有订单时 先删除在保存商品
//		unifiedOrderGoodsMapperEx.deleteBySn(unifiedOrder.getOrderSn());
//		for (UnifiedOrderGoods unifiedOrderGoods : unifiedOrderGoodsList) {
//			unifiedOrderGoodsMapper.insertSelective(unifiedOrderGoods);
//		}

        // 积分订单
        // 之前是先删除再 插入
//		UnifiedOrderGoodsExample scoreOrderGoodsExample4Delete = new UnifiedOrderGoodsExample();
//		scoreOrderGoodsExample4Delete.createCriteria()
//				.andOrderSnEqualTo(unifiedOrderEntity.getOrderSn());
//		unifiedOrderGoodsMapper.deleteByExample(scoreOrderGoodsExample4Delete);
//				processUnifiedOrderGoodsList.forEach(unifiedOrderGoods -> {
//					unifiedOrderGoodsMapper.insert(unifiedOrderGoods);
//				});


        UnifiedOrderGoodsExample          orderGoodsExample4SaveOrUpdate  = new UnifiedOrderGoodsExample();
        UnifiedOrderGoodsExample.Criteria orderGoodsCriteria4SaveOrUpdate = orderGoodsExample4SaveOrUpdate.createCriteria();

        orderGoodsCriteria4SaveOrUpdate
                // 新逻辑 不在这里加条件
//				.andOrderSnEqualTo(unifiedOrderEntity.getOrderSn());
                // 20201017 12:39 add 之前可能是这样把退单的数据清了
                .andDirectionEqualTo(direction);

        // TODO 超级前台的统一订单好像是有可能没有goods_id的 有可能有问题
        // 因为退单 退的商品只有 1 TODO mark by linjinyu at 20211008 目前对接 楼闪送 后 退的商品有可能大于1
        if (direction.equals(CommonDirectionEnum.负向.getKey())) {


            /****************************************** 订单商品限制 start ******************************************/
            List<Long> processGoodsIds = processUnifiedOrderGoodsList.stream()
                    .filter(o -> null != o.getGoodsId())
                    .filter(AnLamdaUtils.distinctByKey(o -> o.getGoodsId()))
                    .map(o -> o.getGoodsId()).collect(Collectors.toList());

            if (CollUtil.isNotEmpty(processGoodsIds)) {
                orderGoodsCriteria4SaveOrUpdate.andGoodsIdIn(processGoodsIds);
            }
            /****************************************** 订单商品限制  end ******************************************/

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

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

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

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

        List<UnifiedOrderGoods> existsUnifiedOrderGoodsList = unifiedOrderGoodsMapper.selectByExample(orderGoodsExample4SaveOrUpdate);

        log.info("\n\n\nOrderGoods: \n已存在数据 : \n{}\n过来的数据 : \n{}\n\n\n",
                AnJsonUtils.toJson(existsUnifiedOrderGoodsList),
                AnJsonUtils.toJson(processUnifiedOrderGoodsList)
        );

        // 最终合并后的结果
        List<UnifiedOrderGoods> finalUnifiedOrderGoodsList = new ArrayList<>();

        // 拿着过来的数据 去 查 数据库的
        for (UnifiedOrderGoods processOrderGoods : processUnifiedOrderGoodsList) {

            /****************************************** 兼容 情况 ******************************************/

            // 新过来的数据在老的是不是存在 因为在 同一个 order_sn 下 goods_id 是唯一的 ,所以成立
            // TODO 问题点 如果有 附件 赠品 就会有问题 20201018 已经清除了 goodsid = 0 金额 = 0 的商品数据 大概之前的问题是没有的
            List<UnifiedOrderGoods> findByOutSnapshotIdOrderGoodsList = null;
            List<UnifiedOrderGoods> findByOutGoodsIdOrderGoodsList    = null;
            List<UnifiedOrderGoods> findByGoodsNameOrderGoodsList     = null;

            boolean isRetry = false;

            // 逻辑是 统一订单 这边补的运费 必定是不成立
            if (processOrderGoods.getOutSnapshotOrderGoodsId() != null && !processOrderGoods.getOutSnapshotOrderGoodsId().equals(0L)) {

                List<Predicate<UnifiedOrderGoods>> predicatesByOutSnapshotId = new ArrayList<>();
                predicatesByOutSnapshotId.add(r -> null != r.getOutSnapshotOrderGoodsId()
                        && r.getOutSnapshotOrderGoodsId().equals(processOrderGoods.getOutSnapshotOrderGoodsId()));

                findByOutSnapshotIdOrderGoodsList = AnLamdaUtils.filters(existsUnifiedOrderGoodsList, predicatesByOutSnapshotId);

                if (CollUtil.isEmpty(findByOutSnapshotIdOrderGoodsList)) {
                    isRetry = true;
                }

            } else {
                // 运费的补刀
                isRetry = true;
            }

            if (isRetry) {

                if (null != processOrderGoods.getGoodsId()) {

                    List<Predicate<UnifiedOrderGoods>> predicatesByOutGoodsId = new ArrayList<>();
                    predicatesByOutGoodsId.add(r -> null != r.getGoodsId() && r.getGoodsId().equals(processOrderGoods.getGoodsId()));

                    findByOutGoodsIdOrderGoodsList = AnLamdaUtils.filters(existsUnifiedOrderGoodsList, predicatesByOutGoodsId);

                }

                // 再补 202009151941 by linjinyu 发现 生产环境上 unified_order_goods.goods_id 是 NULL  数据
                if (CollUtil.isEmpty(findByOutGoodsIdOrderGoodsList)) {

                    List<Predicate<UnifiedOrderGoods>> predicatesByGoodsName = new ArrayList<>();
                    predicatesByGoodsName.add(r -> null != r.getGoodsName() && r.getGoodsName().equals(processOrderGoods.getGoodsName()));

                    findByGoodsNameOrderGoodsList = AnLamdaUtils.filters(existsUnifiedOrderGoodsList, predicatesByGoodsName);
                }
            }

            /****************************************** 兼容 情况 ******************************************/

            // 第一次 找到?
            if (CollUtil.isNotEmpty(findByOutSnapshotIdOrderGoodsList)) {
                UnifiedOrderGoods findedBySnapshotIdOrderGoods = findByOutSnapshotIdOrderGoodsList.get(0);

                overWriteGoodsField(processOrderGoods, findedBySnapshotIdOrderGoods);
                finalUnifiedOrderGoodsList.add(findedBySnapshotIdOrderGoods);
            }
            // 第二次找到的
            else if (isRetry && CollUtil.isNotEmpty(findByOutGoodsIdOrderGoodsList)) {
                UnifiedOrderGoods findedByOutGoodsIdOrderGoods = findByOutGoodsIdOrderGoodsList.get(0);

                overWriteGoodsField(processOrderGoods, findedByOutGoodsIdOrderGoods);
                finalUnifiedOrderGoodsList.add(findedByOutGoodsIdOrderGoods);
            }
            // 第三次找到的
            else if (isRetry && CollUtil.isNotEmpty(findByGoodsNameOrderGoodsList)) {
                UnifiedOrderGoods findedByGoodsNameOrderGoods = findByGoodsNameOrderGoodsList.get(0);

                overWriteGoodsField(processOrderGoods, findedByGoodsNameOrderGoods);
                finalUnifiedOrderGoodsList.add(findedByGoodsNameOrderGoods);
            } else {
                finalUnifiedOrderGoodsList.add(processOrderGoods);
            }
        }

        // 先推正的再推负的再推正的,会把负的会被干了
        unifiedOrderGoodsMapper.deleteByExample(orderGoodsExample4SaveOrUpdate);

        // 20201109 坑位
//		finalUnifiedOrderGoodsList.forEach(unifiedOrderGoods -> {
//			unifiedOrderGoodsMapperEx.insertSelective(unifiedOrderGoods);
//		});
        // 20210203 重构
        unifiedOrderGoodsMapperEx.insertBatch(finalUnifiedOrderGoodsList);

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

    /**
     * 覆写字段
     *
     * @param processOrderGoods
     * @param findedOrderGoods
     */
    private void overWriteGoodsField(UnifiedOrderGoods processOrderGoods, UnifiedOrderGoods findedOrderGoods) {

        // 20201018 还有此 价格呀之类的没有覆写 先不覆写 目前这个覆写 只为了一些扩展数据的修正 不过按商城目前的稳定性,大概是要的 算了,还是加吧

//		findedOrderGoods.setId();

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

        findedOrderGoods.setGoodsName(processOrderGoods.getGoodsName());
        findedOrderGoods.setGoodsAlias(processOrderGoods.getGoodsAlias());

        findedOrderGoods.setGoodsId(processOrderGoods.getGoodsId());
        findedOrderGoods.setOutSnapshotOrderGoodsId(processOrderGoods.getOutSnapshotOrderGoodsId());

        findedOrderGoods.setQuantity(processOrderGoods.getQuantity());
        findedOrderGoods.setUnit(StrUtil.isBlank(processOrderGoods.getUnit()) ? CommonOrderGoodsUnitEnum.项.getDesc() : processOrderGoods.getUnit());
        findedOrderGoods.setPrice(processOrderGoods.getPrice());
        findedOrderGoods.setCostPrice(processOrderGoods.getCostPrice());

        findedOrderGoods.setGoodsParams(processOrderGoods.getGoodsParams());

        findedOrderGoods.setFiscalCode(processOrderGoods.getFiscalCode());
        findedOrderGoods.setTaxCode(processOrderGoods.getTaxCode());
        findedOrderGoods.setTaxRate(processOrderGoods.getTaxRate());

        // 商户税率
        findedOrderGoods.setMerchTaxId(processOrderGoods.getMerchTaxId());
        findedOrderGoods.setMerchTaxCode(processOrderGoods.getMerchTaxCode());
        findedOrderGoods.setMerchTaxRate(processOrderGoods.getMerchTaxRate());

        // 平台税率
        findedOrderGoods.setOperationTaxId(processOrderGoods.getOperationTaxId());
        findedOrderGoods.setOperationTaxCode(processOrderGoods.getOperationTaxCode());
        findedOrderGoods.setOperationTaxRate(processOrderGoods.getOperationTaxRate());

        findedOrderGoods.setCateIdLv1(processOrderGoods.getCateIdLv1());
        findedOrderGoods.setCateIdLv1(processOrderGoods.getCateIdLv2());
        findedOrderGoods.setCateIdLv3(processOrderGoods.getCateIdLv3());

        findedOrderGoods.setCateNameLv1(processOrderGoods.getCateNameLv1());
        findedOrderGoods.setCateNameLv2(processOrderGoods.getCateNameLv2());
        findedOrderGoods.setCateNameLv3(processOrderGoods.getCateNameLv3());

        findedOrderGoods.setSelfOption(processOrderGoods.getSelfOption() == null ? "" : processOrderGoods.getSelfOption());

        findedOrderGoods.setGoodsType(processOrderGoods.getGoodsType());

//		findedOrderGoods.setDirection();
//		findedOrderGoods.setAccountingStateCustomer();
//		findedOrderGoods.setAccountingStateSupplier();
//		findedOrderGoods.setRefundOrderSn();
//		findedOrderGoods.setCreateTime();
//		findedOrderGoods.setCreateUserId();
//		findedOrderGoods.setUpdateTime();
//		findedOrderGoods.setUpdateUserId();


    }

}
