package cn.superdesk.uniorder.service.order.receive.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.superdesk.uniorder.common.enums.accounting.AccountingOrderTypeDimEnum;
import cn.superdesk.uniorder.common.enums.common.*;
import cn.superdesk.uniorder.common.enums.order.UnifiedOrderCreditBackAccountStatusEnum;
import cn.superdesk.uniorder.common.enums.order.UnifiedOrderCreditInvoiceApplyStatusEnum;
import cn.superdesk.uniorder.common.enums.order.UnifiedOrderCreditInvoiceMakeStatusEnum;
import cn.superdesk.uniorder.common.exception.utils.ExceptionUtils;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.dao.entity.base.*;
import cn.superdesk.uniorder.dao.mapper.base.*;
import cn.superdesk.uniorder.dto.param.operation.UnifiedOrderIssuesFlowingParam;
import cn.superdesk.uniorder.dto.param.setting.UnifiedServicePartGoodsTransportParam;
import cn.superdesk.uniorder.dto.receive.consumer.superdeskmall.score.refund.ScoreOrderRefundGoodsReceiveParam;
import cn.superdesk.uniorder.dto.receive.consumer.superdeskmall.score.refund.ScoreOrderRefundOrderIntegralCreditReceiveParam;
import cn.superdesk.uniorder.dto.receive.consumer.superdeskmall.score.refund.ScoreOrderRefundOrderReceiveParam;
import cn.superdesk.uniorder.dto.receive.consumer.superdeskmall.score.refund.ScoreOrderRefundReceiveParam;
import cn.superdesk.uniorder.service.order.receive.ReceiveFlscQchRefundOrderService;
import cn.superdesk.uniorder.service.order.base.*;
import cn.superdesk.uniorder.service.setting.UnifiedServiceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


@Slf4j
@Service
public class ReceiveFlscQchRefundOrderServiceImpl implements ReceiveFlscQchRefundOrderService {

    @Autowired
    private UnifiedOrderMapper                    unifiedOrderMapper;
    @Autowired
    private UnifiedOrderMapperEx                  unifiedOrderMapperEx;
    @Autowired
    private UnifiedOrderMapperExCustomerDimCredit unifiedOrderMapperExScore;
    @Autowired
    private UnifiedOrderGoodsMapper               unifiedOrderGoodsMapper;
    @Autowired
    private UnifiedOrderGoodsMapperEx             unifiedOrderGoodsMapperEx;
    @Autowired
    private UnifiedOrderCreditMapper              unifiedOrderCreditMapper;

    /****************************************** 退单部分 ******************************************/

    @Autowired
    private UnifiedOrderReturnMapper        unifiedOrderReturnMapper;
    @Autowired
    private UnifiedOrderReturnMapperEx      unifiedOrderReturnMapperEx;
    @Autowired
    private UnifiedOrderReturnGoodsMapper   unifiedOrderReturnGoodsMapper;
    @Autowired
    private UnifiedOrderReturnGoodsMapperEx unifiedOrderReturnGoodsMapperEx;
    @Autowired
    private UnifiedOrderReturnCreditMapper  unifiedOrderReturnCreditMapper;

    /****************************************** 退单部分 ******************************************/

    @Autowired
    private CommonOrderProcessService            commonOrderProcessService;
    @Autowired
    private CommonMergeOrderGoodsProcessService  commonMergeOrderGoodsProcessService;
    @Autowired
    private CommonMergeOrderCreditProcessService commonMergeOrderCreditProcessService;

    @Autowired
    private CommonMergeRefundOrderProcessService       commonMergeOrderProcessService;
    @Autowired
    private CommonMergeRefundOrderCreditProcessService commonMergeRefundOrderCreditProcessService;

    @Autowired
    private CommonOrderTransportProcessService commonOrderTransportProcessService;

    @Autowired
    private UnifiedServiceService unifiedServiceService;

    /**
     * 退单 维权订单
     * 积分订单处理
     * <p>
     * 企业福利-侨城汇 20200812 mark by linjinyu
     *
     * @param receiveParam
     * @return
     */
    @Override
    @Transactional
    public UnifiedOrderIssuesFlowingParam kafkaScoreOrderRefundReceive(ScoreOrderRefundReceiveParam receiveParam) {


        UnifiedOrderIssuesFlowingParam callback = new UnifiedOrderIssuesFlowingParam();
        callback.setUid(receiveParam.getUid());
        callback.setProcessResult(CommonProcessResultEnum.正常.getKey());
        callback.setProcessReport("");

        // 运费税率设置
        UnifiedServicePartGoodsTransportParam defaultGoodsTransport = unifiedServiceService.getUnifiedServicePartGoodsTransport("FLSC_QCH");

        StringBuffer processReport = new StringBuffer();

        try {

            // 如查不按 文档 的结构 让它报错吧
            log.info(JSONUtil.toJsonStr(receiveParam));

            // 判定
            if (ObjectUtil.isEmpty(receiveParam.getOrder().getCompletState())) {
                callback.setProcessResult(CommonProcessResultEnum.异常_程序检查.getKey());
                callback.setProcessReport("退单归类后的状态不能为空 订单完成状态 必须 业务方归类订单状态推送完成状态:1-已完成;2-未完成;3-已取消/已作废;");
                return callback;
            }

            CommonOrderCompletStateEnum commonOrderCompletStateEnum = CommonOrderCompletStateEnum.get(receiveParam.getOrder().getCompletState());
            CommonDataIntegrityEnum     commonDataIntegrityEnum     = CommonDataIntegrityEnum.完整;


            int countDataIntegrity = 0;

            // 判定 order 为空
            if (null == receiveParam.getOrder()) {
                callback.setProcessResult(CommonProcessResultEnum.异常_程序检查.getKey());
                processReport.append("退单订单信息为空;");
                countDataIntegrity++;
            }
            // 判定 goods 为空
            if (null == receiveParam.getGoods()) {
                callback.setProcessResult(CommonProcessResultEnum.异常_程序检查.getKey());
                processReport.append("退单商品为空;");
                countDataIntegrity++;
            }
            // 判定 order.integralCredit 为空
            if (CollUtil.isEmpty(receiveParam.getOrder().getIntegralCredit())) {
                callback.setProcessResult(CommonProcessResultEnum.异常_程序检查.getKey());
                processReport.append("退单流水为空;");
                countDataIntegrity++;
            }

            if (countDataIntegrity > 0) {
                commonDataIntegrityEnum = CommonDataIntegrityEnum.缺失;
            }


            // 1. 数据是否完整
            // 1.1 完整
            // 1.1 不完整
//						未完成 已完成 已作废
//			退货退款 - >  >   >
//			换货 - 没流水 有商品
//			维修 - 没流水 有商品
//
//			2(未完成) -> 3(已作废)
//			退货退款	-> 换货 没流水

            switch (commonDataIntegrityEnum) {
                case 完整:
                    processDataIntegrity(receiveParam, commonOrderCompletStateEnum, callback);
                    break;
                case 缺失:
                    processDatalack(receiveParam, commonOrderCompletStateEnum, callback);
                    break;
            }


            // 分润处理 TODO 目前的没验证 先屏蔽 分润处理也不能在这里处理
//			processProfit(unifiedOrderReturn);

        } catch (Exception e) {

            log.error("商城 同步 统一订单 (侨城汇-积分订单)-kafkaScoreOrderRefundReceive 失败:{}", ExceptionUtils.getMessage(e));
            e.printStackTrace();

            processReport.append(ExceptionUtils.getMessage(e));

            callback.setProcessResult(CommonProcessResultEnum.异常_抛错.getKey());
            callback.setProcessReport(processReport.toString());

        } finally {
            return callback;
        }


    }

    //	完整(0, "完整"), // integrity
    private void processDataIntegrity(ScoreOrderRefundReceiveParam receiveParam, CommonOrderCompletStateEnum commonOrderCompletStateEnum, UnifiedOrderIssuesFlowingParam callback) {

        String orderSn       = receiveParam.getOrder().getOrderSn();
        String refundOrderSn = receiveParam.getOrder().getRefundNo();
        Date   finishTime    = receiveParam.getOrder().getFinishTime();


        log.error("数据完整 processDataIntegrity | commonOrderCompletStateEnum => {} | orderSn => {} | refundOrderSn => {} | finishTime => {}", commonOrderCompletStateEnum.getDesc(), orderSn, refundOrderSn, finishTime);

        /****************************************** 处理 start ******************************************/

        // 处理 退单 主体 转换 持久化 | 执行完后,这个退单是已经持久化了 是只 退单号来判定唯一的
        UnifiedOrderReturn unifiedOrderReturn = convertAndStoreScoreOrderRefundOrderReceiveParam2Entity(receiveParam);
        // 处理 退单 商品 转换 持久化
        UnifiedOrderReturnGoods unifiedOrderReturnGoods = convertAndStoreScoreOrderRefundGoodsReceiveParam2Entity(receiveParam);
        // 处理 退单 流水 转换
        List<UnifiedOrderReturnCredit> unifiedOrderReturnCredits = convertScoreOrderRefundOrderIntegralCreditReceiveParam(receiveParam);
        // 处理 退单 流水 持久化
        List<UnifiedOrderReturnCredit> finalRefundOrderCreditList = commonMergeRefundOrderCreditProcessService.processRefundUnifiedOrderCreditBykafkaPushOrderReceive(
                unifiedOrderReturn,
                unifiedOrderReturnGoods,
                unifiedOrderReturnCredits
        );

        /****************************************** 处理   end ******************************************/

        /****************************************** TODO 20210120 处理 退单退运费 验证 start ******************************************/

        UnifiedOrderGoods refundOrderGoods = commonOrderTransportProcessService.processRefundTransport(unifiedOrderReturn, finalRefundOrderCreditList);

        /****************************************** TODO 20210120 处理退单退运费验证   end ******************************************/


        // 重新核算 退单 修正 传过来时  amount 为 0 的问题 TODO 好像与退运费没什么关系
        accountingUnifiedOrderReturnAmount(unifiedOrderReturn, unifiedOrderReturnGoods, unifiedOrderReturnCredits);

        // 反过来再处理 UnifiedOrderCredits 没有持久化 只是转换
        List<UnifiedOrderCredit> hedgeUnifiedOrderCreditList = processScoreOrderRefundUnifiedOrderCredits(unifiedOrderReturn, finalRefundOrderCreditList);

        // 反过来再处理 UnifiedOrderGoods 没有持久化 只是转换
        List<UnifiedOrderGoods> hedgeUnifiedOrderGoodsList = processScoreOrderRefundUnifiedOrderGoods(unifiedOrderReturn, unifiedOrderReturnGoods);

        // 处理退运费
        if (null != refundOrderGoods) {
            hedgeUnifiedOrderGoodsList.add(refundOrderGoods);
        }

        /****************************************** 分歧点 start ******************************************/
        // 反过来再处理 UnifiedOrder | 重新核算 订单 并 持久化
        // UnifiedOrder hedgeUnifiedOrder = processScoreOrderRefundUnifiedOrder(unifiedOrderReturn);
        // TODO 反过来再处理 UnifiedOrder 退单作为主体的新逻辑 | 不核算 订单 通过订单 产生 退单 主体
        UnifiedOrder hedgeUnifiedOrder = commonMergeOrderProcessService.processScoreOrderRefundUnifiedOrder(unifiedOrderReturn);
        /****************************************** 分歧点   end ******************************************/

        // 与现有数据合并 并 持久化 TODO 新主体逻辑 可能要改 先标记
        commonMergeOrderGoodsProcessService.processUnifiedOrderGoodsBykafkaPushOrderReceive(hedgeUnifiedOrder, hedgeUnifiedOrderGoodsList, -1);
        // 与现有数据合并 并 持久化 TODO 新主体逻辑 可能要改 先标记
        commonMergeOrderCreditProcessService.processUnifiedOrderCreditBykafkaPushOrderReceive(hedgeUnifiedOrder, hedgeUnifiedOrderCreditList, -1);


//		已完成(1, "已完成"),
//		未完成(2, "未完成"),
//		已作废(3, "已作废"),
        // TODO 添加锁单逻辑 只锁了供应商对账 mark by linjinyu at 20210701
        switch (commonOrderCompletStateEnum) {
            case 未完成:
                // 锁定正单
                // 锁定负单
//				commonMergeOrderProcessService.lockByOrderSn(hedgeUnifiedOrder.getOrderSn());
//				commonMergeOrderProcessService.lockByOrderSn(refundOrderSn);
                commonMergeOrderProcessService.lockByOrderSn(orderSn);
                commonMergeOrderProcessService.lockByOrderSn(refundOrderSn);
                break;
            case 已完成:
                // 解锁正单 更新结算时间
                // 解锁负单 更新结算时间
                commonMergeOrderProcessService.unlockByOrderSn(orderSn);
                commonMergeOrderProcessService.unlockByOrderSn(refundOrderSn);

                // TODO 结算时间逻辑 添加 mark by linjinyu at 20211112
                // |---- 1. kafka 正向通道,触发点 订单已完成 产生 结算时间(订单完成时间填充) right
                // |---- 2. kafka 负向通道,解发点 退单已完成 解锁正负单时 产生结算时间(退单完成时间填充) right
                // |---- 3. 供应商结算 未对账商品 list 逻辑 不变(没说明) 看样子是 加了个 结算时间 筛选逻辑
                commonMergeOrderProcessService.processBizOrderRecordAccountingTime(orderSn, refundOrderSn, finishTime, callback);

                break;
            case 已作废:
                // 解锁正单 更新结算时间
                // 解锁负单 更新结算时间
                commonMergeOrderProcessService.unlockByOrderSn(orderSn);
                commonMergeOrderProcessService.unlockByOrderSn(refundOrderSn);

                commonMergeOrderProcessService.processBizOrderRecordAccountingTime(orderSn, refundOrderSn, finishTime, callback);
                break;

        }
    }

    //	缺失(1, "缺失"), // lack missing
    private void processDatalack(ScoreOrderRefundReceiveParam receiveParam, CommonOrderCompletStateEnum commonOrderCompletStateEnum, UnifiedOrderIssuesFlowingParam callback) {

        String orderSn       = receiveParam.getOrder().getOrderSn();
        String refundOrderSn = receiveParam.getOrder().getRefundNo();
        Date   finishTime    = receiveParam.getOrder().getFinishTime();


        switch (commonOrderCompletStateEnum) {
            case 已完成:

                // 不产生退单主体
                // 解锁正单 更新结算时间
                // 作废负单(如果有)

                commonMergeOrderProcessService.unlockByOrderSn(orderSn);
                commonMergeOrderProcessService.processBizOrderRecordAccountingTime(orderSn, refundOrderSn, finishTime, callback);

                commonMergeOrderProcessService.processOrderBecomeInvalidIfExist(refundOrderSn);

                break;

            case 未完成:

                // 不产生退单主体
                // 锁定正单
                // 作废负单(如果有)

                commonMergeOrderProcessService.lockByOrderSn(orderSn);

                commonMergeOrderProcessService.processOrderBecomeInvalidIfExist(refundOrderSn);

                break;


            case 已作废:

                // 不产生退单主体
                // 解锁正单 更新结算时间
                // 作废负单(如果有)

                commonMergeOrderProcessService.unlockByOrderSn(orderSn);
                commonMergeOrderProcessService.processBizOrderRecordAccountingTime(orderSn, refundOrderSn, finishTime, callback);

                commonMergeOrderProcessService.processOrderBecomeInvalidIfExist(refundOrderSn);

                break;
        }
    }


//	{"order":{"ordersn":"ME20200918125350152766","project_id":"0","parentid":"0","integralCredit":[{"enterprise_id":"90","member_id":"22930","credit_type":"1","batchs":"JF20200917144939296","balance":"200.00","orderid":"66211","goodsid":"65406","createtime":"1603157398","pay_status":"1","pay_type":"1","credit_name":"\u798f\u5229\u79ef\u5206","daily_account_type":"3"}],"refundno":"SR20201015105140102149","amount":"","complet_state":1},"goods":{"refundno":"SR20201015105140102149","goods_name":"\u4e94\u8c37\u4e30\u767b \u7cae\u6cb9\u798f\u888b","goods_id":"65406","refund_total":"1","cost_price":"180.00","realprice":"200.00","total":"1","orderid":"66211","price":"200.00"}}

    /**
     * 重新 核算 退单 金额
     * TODO 坑位
     *
     * @param unifiedOrderReturn
     * @param unifiedOrderReturnGoods
     * @param unifiedOrderReturnCredits
     */
    private void accountingUnifiedOrderReturnAmount(
            UnifiedOrderReturn unifiedOrderReturn,
            UnifiedOrderReturnGoods unifiedOrderReturnGoods,
            List<UnifiedOrderReturnCredit> unifiedOrderReturnCredits
    ) {

        log.info("accountingUnifiedOrderReturnAmount unifiedOrderReturn \n{}", AnJsonUtils.toPrettyJson(unifiedOrderReturn));
        log.info("accountingUnifiedOrderReturnAmount unifiedOrderReturnGoods \n{}", AnJsonUtils.toPrettyJson(unifiedOrderReturnGoods));
        log.info("accountingUnifiedOrderReturnAmount unifiedOrderReturnCredits \n{}", AnJsonUtils.toPrettyJson(unifiedOrderReturnCredits));

        if (null == unifiedOrderReturn.getAmount()
                || unifiedOrderReturn.getAmount().compareTo(BigDecimal.ZERO) == 0) {

            log.info("TODO 退单 金额 为 0 先记录 数据错误 ");

            BigDecimal checkUnifiedOrderReturnCreditsAmount = unifiedOrderReturnCredits
                    .stream()
                    .map(item -> item.getBalance() == null ? BigDecimal.ZERO : item.getBalance())
                    .reduce(BigDecimal.ZERO, BigDecimal::add);


            BigDecimal checkUnifiedOrderReturnGoodsPriceQuantity = unifiedOrderReturnGoods.getPrice().multiply(new BigDecimal(unifiedOrderReturnGoods.getQuantity()));

            if (checkUnifiedOrderReturnGoodsPriceQuantity.compareTo(checkUnifiedOrderReturnCreditsAmount) != 0) {

                log.info("TODO 退单的 商品 与 流水 金额还不对等 ? 什么鬼");

            } else {

                log.info("TODO 退单的 商品 与 流水 金额对等 更新");

                unifiedOrderReturn.setAmount(checkUnifiedOrderReturnCreditsAmount);

                unifiedOrderReturnMapper.updateByPrimaryKeySelective(unifiedOrderReturn);
            }
        }
    }


    /**
     * 目前 不作总体的完整性问题,作 saveOrUpdate 操作
     *
     * @param scoreOrderRefundReceiveParam
     * @return
     */
    private UnifiedOrderReturn convertAndStoreScoreOrderRefundOrderReceiveParam2Entity(ScoreOrderRefundReceiveParam scoreOrderRefundReceiveParam) {


        // 初始化 退单 主体
        UnifiedOrderReturn refundOrderEntity = new UnifiedOrderReturn();

        ScoreOrderRefundOrderReceiveParam refundOrderReceiveParam = scoreOrderRefundReceiveParam.getOrder();

        // 找一下这个退单 在当前数据库 有没有 也就是说是不是第一次推过来
        List<UnifiedOrderReturn> existRefundOrderList = unifiedOrderReturnMapperEx.findByRefundOrderSn(refundOrderReceiveParam.getRefundNo());

        if (CollUtil.isNotEmpty(existRefundOrderList)) {
            refundOrderEntity = existRefundOrderList.get(0);
        }

        /****************************************** 商城也要修改 start ******************************************/

        refundOrderEntity.setServiceName(CommonServiceNoEnum.企业福利_侨城汇.getServiceName());
        refundOrderEntity.setServiceNo(CommonServiceNoEnum.企业福利_侨城汇.getServiceNo());

        /****************************************** 商城也要修改 start ******************************************/

        refundOrderEntity.setOrderDim(AccountingOrderTypeDimEnum.积分订单.getKey());

        refundOrderEntity.setOrderSn(refundOrderReceiveParam.getOrderSn());
        refundOrderEntity.setReturnSn(refundOrderReceiveParam.getRefundNo());

        refundOrderEntity.setProjectId(refundOrderReceiveParam.getOrganizationId());
        refundOrderEntity.setProjectName(refundOrderReceiveParam.getOrganizationName());

        /**************************************** mark by linjinyu at 2022-07-25 10:34:44 - start ****************************************/

        refundOrderEntity.setExpress(refundOrderReceiveParam.getExpress());
        refundOrderEntity.setExpressCompany(refundOrderReceiveParam.getExpressCompany());
        refundOrderEntity.setExpressSn(refundOrderReceiveParam.getExpressSn());

        /**************************************** mark by linjinyu at 2022-07-25 10:34:44 -   end ****************************************/

        /****************************************** 以下信息没传 start ******************************************/

//		refundOrderEntity.setProjectName(refundOrderReceiveParam.getProjectName());

//		refundOrderEntity.setPurchaseVirtId(refundOrderReceiveParam.getPurchaseVirtId());
//		refundOrderEntity.setPurchaseVirtName(refundOrderReceiveParam.getPurchaseVirtName());
//
        refundOrderEntity.setPurchaseDepartmentName(refundOrderReceiveParam.getPurchaseDepartmentName());
//
//		refundOrderEntity.setPurchaseUserId(refundOrderReceiveParam.getPurchaseUserId());
//		refundOrderEntity.setPurchaseUserName(refundOrderReceiveParam.getPurchaseUserName());
//		refundOrderEntity.setPurchasePhone(refundOrderReceiveParam.getPurchasePhone());

        /****************************************** 以下信息没传   end ******************************************/

        refundOrderEntity.setCreateTime(refundOrderReceiveParam.getCreateTime());
        refundOrderEntity.setPayTime(refundOrderReceiveParam.getPayTime());
        refundOrderEntity.setSendTime(refundOrderReceiveParam.getSendTime());
        refundOrderEntity.setFinishTime(refundOrderReceiveParam.getFinishTime());

        // order : {"amount":"","project_id":"615","return_sn":"SR20190802170324142482","sn":"ME20190802153337664456","complet_state":1}
        // amount 为 空串的情况是 退换货的情况
        // TODO 这个不是销售价 是退款时 手工填写的金额
        refundOrderEntity.setAmount(refundOrderReceiveParam.getAmount() == null ? BigDecimal.ZERO : refundOrderReceiveParam.getAmount());


        // change dz 1025 TODO 这个是为什么呀? 就是上边说的问题 优化点 直接 先去看这个退款金金额有没有 没有直接返回啦 做这么多事干什么
        if (refundOrderEntity.getAmount().doubleValue() <= 0) {
            // TODO 记录一下问题 都核对一下吧
        }

        // 退运费 mark by linjinyu at 20210120
        refundOrderEntity.setTransportAmount(refundOrderReceiveParam.getDispatchPrice());
        refundOrderEntity.setTransportAmountSource(-1);

        // 这个是要验证的 -- 未审核完成的退单是不会过来
        refundOrderEntity.setCompletState(refundOrderReceiveParam.getCompletState());

        refundOrderEntity.setOrderState(refundOrderReceiveParam.getOrderState());
        refundOrderEntity.setOrderStateName(refundOrderReceiveParam.getOrderStateName());

        refundOrderEntity.setAppraiseState(2);

        refundOrderEntity.setUserType("kafka");
        refundOrderEntity.setUserName("kafka系统同步");

        if (null != refundOrderEntity.getId()) {

            refundOrderEntity.setUpdateUserId(1L);
            refundOrderEntity.setUpdateTime(DateUtil.date());

            unifiedOrderReturnMapper.updateByPrimaryKeySelective(refundOrderEntity);

        } else {

            // TODO 写死 未对账
            refundOrderEntity.setAccountingStateCustomer(2);
            // TODO 写死
            refundOrderEntity.setPayState(2);


            /****************************************** 重构 mark by linjinyu at 20210628 start ******************************************/
//			// TODO 未确认 linjinyu 订单状态 start
//			unifiedOrderReturn.setOrderState(param.getCompletState());
//
//			String orderStateName = "";
//
//			// TODO 20201018 此处是商城过来的,是这样定义的吗？
//			if (param.getCompletState().equals(1)) {
//				orderStateName = "完成";
//			} else if (param.getCompletState().equals(2)) {
//				orderStateName = "未完成";
//			} else if (param.getCompletState().equals(3)) {
//				orderStateName = "已取消";
//			}
//
//			unifiedOrderReturn.setOrderStateName(orderStateName);
            /****************************************** 重构 mark by linjinyu at 20210628 start ******************************************/

//			unifiedOrderReturn.setOrderState(param.getOrderState());
//			unifiedOrderReturn.setOrderStateName(param.getOrderStateName());

            refundOrderEntity.setCreateUserId(1L);
            refundOrderEntity.setCreateTime(refundOrderReceiveParam.getCreateTime());

            refundOrderEntity.setUpdateUserId(1L);
            refundOrderEntity.setUpdateTime(DateUtil.date());

            unifiedOrderReturnMapper.insertSelective(refundOrderEntity);
        }

        return refundOrderEntity;

    }

    /**
     * 目前 不作总体的完整性问题,作 saveOrUpdate 操作
     *
     * @param scoreOrderRefundReceiveParam
     * @return
     */
    private UnifiedOrderReturnGoods convertAndStoreScoreOrderRefundGoodsReceiveParam2Entity(ScoreOrderRefundReceiveParam scoreOrderRefundReceiveParam) {

        // 初始化 退单 商品 如果一条都没有记录
        UnifiedOrderReturnGoods unifiedOrderReturnGoods = new UnifiedOrderReturnGoods();

        ScoreOrderRefundGoodsReceiveParam param = scoreOrderRefundReceiveParam.getGoods();

        // TODO 基于退维权 订单SN来去查 退货 货物 为什么这里是对的呢 是因为每个退单只有一个商品
        List<UnifiedOrderReturnGoods> listUnifiedOrderReturnGoods = unifiedOrderReturnGoodsMapperEx.findByRefundOrderSn(param.getRefundNo());

        // SELECT COUNT(return_sn) as total ,return_sn FROM `unified_order_return` GROUP by return_sn HAVING total >1
        // 这个sql 查过了,是没有的
        if (CollUtil.isNotEmpty(listUnifiedOrderReturnGoods)) {
            unifiedOrderReturnGoods = listUnifiedOrderReturnGoods.get(0);
        }
        // SELECT COUNT(order_sn) as total ,order_sn FROM `unified_order_return` GROUP by order_sn HAVING total >1
        // 这个sql 查过了,同一订单 多种 商品退单是有的 正在显示第 0-24 行 (共 26 行, 查询花费 0.0005 秒。)


        unifiedOrderReturnGoods.setReturnSn(param.getRefundNo());
        unifiedOrderReturnGoods.setGoodsName(param.getGoodsName());
        unifiedOrderReturnGoods.setGoodsId(param.getGoodsId());
        unifiedOrderReturnGoods.setOutSnapshotOrderGoodsId(param.getOutSnapshotOrderGoodsId());

        unifiedOrderReturnGoods.setQuantity(param.getRefundTotal());
        unifiedOrderReturnGoods.setCostPrice(param.getCostPrice());
        unifiedOrderReturnGoods.setPrice(param.getPrice());

        /****************************************** 退单退商品 添加 税率 mark by linjinyu at 20210323 start ******************************************/

        unifiedOrderReturnGoods.setFiscalCode(param.getFiscalCode());
        unifiedOrderReturnGoods.setTaxCode(param.getTaxCode());
        unifiedOrderReturnGoods.setTaxRate(param.getTaxRate());

        // 商户税率
        unifiedOrderReturnGoods.setMerchTaxId(param.getMerchTaxId());
        unifiedOrderReturnGoods.setMerchTaxCode(param.getMerchTaxCode());
        unifiedOrderReturnGoods.setMerchTaxRate(param.getMerchTaxRate());

        // 平台税率
        unifiedOrderReturnGoods.setOperationTaxId(param.getOperationTaxId());
        unifiedOrderReturnGoods.setOperationTaxCode(param.getOperationTaxCode());
        unifiedOrderReturnGoods.setOperationTaxRate(param.getOperationTaxRate());

        // 三级分类
        unifiedOrderReturnGoods.setCateIdLv1(param.getCateIdLv1());
        unifiedOrderReturnGoods.setCateIdLv2(param.getCateIdLv2());
        unifiedOrderReturnGoods.setCateIdLv3(param.getCateIdLv3());

        unifiedOrderReturnGoods.setCateNameLv1(param.getCateNameLv1());
        unifiedOrderReturnGoods.setCateNameLv2(param.getCateNameLv2());
        unifiedOrderReturnGoods.setCateNameLv3(param.getCateNameLv3());

        unifiedOrderReturnGoods.setUnit(param.getUnit());
        unifiedOrderReturnGoods.setSelfOption(param.getSelfOption());

        /****************************************** 退单退商品 添加 税率 mark by linjinyu at 20210323   end ******************************************/

        if (null != unifiedOrderReturnGoods.getId()) {
            unifiedOrderReturnGoods.setUpdateUserId(2L);
            unifiedOrderReturnGoods.setUpdateTime(DateUtil.date());
        } else {
            unifiedOrderReturnGoods.setCreateUserId(1L);
            unifiedOrderReturnGoods.setCreateTime(DateUtil.date());
        }

        // 保存数据 维权订单 货品
        if (null != unifiedOrderReturnGoods.getId()) {
            unifiedOrderReturnGoodsMapper.updateByPrimaryKeySelective(unifiedOrderReturnGoods);
        } else {
            unifiedOrderReturnGoodsMapper.insertSelective(unifiedOrderReturnGoods);
        }

        return unifiedOrderReturnGoods;


    }

    /**
     * 目前 不作总体的完整性问题,只作 insert 操作
     * 重构 只作转换
     *
     * @param scoreOrderRefundReceiveParam
     * @return
     */
    private List<UnifiedOrderReturnCredit> convertScoreOrderRefundOrderIntegralCreditReceiveParam(ScoreOrderRefundReceiveParam scoreOrderRefundReceiveParam) {

        // 初始化 退单 商品 流水 如果一条都没有记录
        List<UnifiedOrderReturnCredit> unifiedOrderReturnCredits = new ArrayList<>();

        // 过来的 流水数据
        List<ScoreOrderRefundOrderIntegralCreditReceiveParam> params = scoreOrderRefundReceiveParam.getOrder().getIntegralCredit();

        if (CollUtil.isEmpty(params)) {
            // TODO throw error
        }

        // 商城过来的数据 TODO 新添加逻辑 退单成为新主体 且 未完成时 是没有流水数据的
        if (CollUtil.isNotEmpty(params)) {
            for (ScoreOrderRefundOrderIntegralCreditReceiveParam param : params) {


                // C位
                if (param.getCreditType().equals(0) && param.getCreditName() == null) {
                    param.setCreditName("微信支付");
                }


                UnifiedOrderReturnCredit creditRefund = new UnifiedOrderReturnCredit();

                creditRefund.setOrderSn(scoreOrderRefundReceiveParam.getOrder().getOrderSn());
                creditRefund.setOrderId(param.getOrderId());

                // 添加退单流水快照 ID 20201013 加字段
                creditRefund.setOutSnapshotOrderCreditId(param.getOrderCreditId());

                // TODO 添加退运费的 特殊逻辑
//			1. 首先, 这个是处理退单的流水
//			2. 已经约定退单退运费的积分流水goods_id为0
//			3. 但是在统一订单的处理中0为正单的运费
                creditRefund.setGoodsId(param.getGoodsId().compareTo(CommonOrderGoodsIdEnum.运费.getKey()) == 0 ? CommonOrderGoodsIdEnum.退单退运费.getKey() : param.getGoodsId());
                creditRefund.setCreditType(param.getCreditType());
                creditRefund.setCreditName(param.getCreditName());

                creditRefund.setDailyAccountType(param.getDailyAccountType());
                creditRefund.setBatchs(param.getBatchs());
                creditRefund.setBalance(param.getBalance());
                creditRefund.setEnterpriseId(param.getEnterpriseId());
                creditRefund.setMemberId(param.getMemberId());

                creditRefund.setPayStatus(param.getPayStatus());
                creditRefund.setPayType(param.getPayType());

                creditRefund.setAccountingStateCustomer(CommonAccountingStateEnum.未对账.getKey());
                creditRefund.setAccountingStateSupplier(CommonAccountingStateEnum.未对账.getKey());

                creditRefund.setInvoiceApplyStatus(UnifiedOrderCreditInvoiceApplyStatusEnum.待申请.getKey());
                creditRefund.setInvoiceMakeStatus(UnifiedOrderCreditInvoiceMakeStatusEnum.待开票.getKey());
                creditRefund.setBackStatus(UnifiedOrderCreditBackAccountStatusEnum.未回款.getKey());

                creditRefund.setCreateTime(DateUtil.date());
                creditRefund.setCreateUserId(1L);

                creditRefund.setUpdateTime(DateUtil.date());
                creditRefund.setUpdateUserId(1L);

                unifiedOrderReturnCredits.add(creditRefund);

            }
        }


        return unifiedOrderReturnCredits;
    }


    /**
     * 处理 对冲 流水
     *
     * @param unifiedOrderReturn
     * @param unifiedOrderReturnCredits
     */
    private List<UnifiedOrderCredit> processScoreOrderRefundUnifiedOrderCredits(UnifiedOrderReturn unifiedOrderReturn, /*信息来源 转换过的*/List<UnifiedOrderReturnCredit> unifiedOrderReturnCredits) {

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

        log.info("processScoreOrderRefundUnifiedOrderCredits :: unifiedOrderReturn \n{}", JSONUtil.toJsonStr(unifiedOrderReturn));
        log.info("processScoreOrderRefundUnifiedOrderCredits :: unifiedOrderReturnCredits \n{}", JSONUtil.toJsonStr(unifiedOrderReturnCredits));

        if (CollUtil.isEmpty(unifiedOrderReturnCredits)) {
            // TODO 如果没有数据,是要报错的

            return hedgeUnifiedOrderCreditList;
        }

//		UnifiedOrderCreditExample          checkExistExample  = new UnifiedOrderCreditExample();
//		UnifiedOrderCreditExample.Criteria checkExistCriteria = checkExistExample.createCriteria();

        for (UnifiedOrderReturnCredit unifiedOrderReturnCredit : unifiedOrderReturnCredits) {

//			checkExistCriteria.andOrderIdEqualTo(unifiedOrderReturnCredit.getOrderId())
//					.andOrderSnEqualTo(unifiedOrderReturn.getOrderSn())// 对
//					.andGoodsIdEqualTo(unifiedOrderReturnCredit.getGoodsId())// 对
//					.andEnterpriseIdEqualTo(unifiedOrderReturnCredit.getEnterpriseId())// 对
//					.andMemberIdEqualTo(unifiedOrderReturnCredit.getMemberId())// 对
////					.andCreditNameEqualTo(unifiedOrderReturnCredit.getCreditName())// 错 原来 退单 流水 积分名称 为 "" 先屏蔽
//					.andCreditTypeEqualTo(unifiedOrderReturnCredit.getCreditType())// 对
//					.andBatchsEqualTo(unifiedOrderReturnCredit.getBatchs())// 对
//					.andDirectionEqualTo(-1)// 对
//					.andBalanceEqualTo(unifiedOrderReturnCredit.getBalance().multiply(new BigDecimal(-1)));
//			List<UnifiedOrderCredit> checkExistRecord = unifiedOrderCreditMapper.selectByExample(checkExistExample);

//			if (CollUtil.isEmpty(checkExistRecord)) {

            UnifiedOrderCredit unifiedOrderCredit = new UnifiedOrderCredit();

//			unifiedOrderCredit.setOrderSn(unifiedOrderReturn.getOrderSn());
            unifiedOrderCredit.setOrderSn(unifiedOrderReturn.getReturnSn());

            unifiedOrderCredit.setDirection(CommonDirectionEnum.负向.getKey());


            unifiedOrderCredit.setOrderId(unifiedOrderReturnCredit.getOrderId());
            unifiedOrderCredit.setGoodsId(unifiedOrderReturnCredit.getGoodsId());

            unifiedOrderCredit.setOutSnapshotOrderCreditId(unifiedOrderReturnCredit.getOutSnapshotOrderCreditId());

            unifiedOrderCredit.setCreditType(unifiedOrderReturnCredit.getCreditType());
            unifiedOrderCredit.setCreditName(unifiedOrderReturnCredit.getCreditName());
            unifiedOrderCredit.setDailyAccountType(unifiedOrderReturnCredit.getDailyAccountType());

            unifiedOrderCredit.setBatchs(unifiedOrderReturnCredit.getBatchs());
            unifiedOrderCredit.setBalance(unifiedOrderReturnCredit.getBalance().multiply(new BigDecimal(-1)));

            unifiedOrderCredit.setEnterpriseId(unifiedOrderReturnCredit.getEnterpriseId());
            unifiedOrderCredit.setMemberId(unifiedOrderReturnCredit.getMemberId());
            unifiedOrderCredit.setPayStatus(unifiedOrderReturnCredit.getPayStatus());
            unifiedOrderCredit.setPayType(unifiedOrderReturnCredit.getPayType());

            unifiedOrderCredit.setCreditLockingCustomer(CommonAccountingLockingEnum.正常.getKey());
            unifiedOrderCredit.setCreditLockingSupplier(CommonAccountingLockingEnum.正常.getKey());

            unifiedOrderCredit.setAccountingStateCustomer(CommonAccountingStateEnum.未对账.getKey());
            unifiedOrderCredit.setAccountingStateSupplier(CommonAccountingStateEnum.未对账.getKey());

            unifiedOrderCredit.setInvoiceApplyStatus(UnifiedOrderCreditInvoiceApplyStatusEnum.待申请.getKey());
            unifiedOrderCredit.setInvoiceMakeStatus(UnifiedOrderCreditInvoiceMakeStatusEnum.待开票.getKey());
            unifiedOrderCredit.setBackStatus(UnifiedOrderCreditBackAccountStatusEnum.未回款.getKey());

            unifiedOrderCredit.setCreateTime(DateUtil.date());
            unifiedOrderCredit.setCreateUserId(1L);

            unifiedOrderCredit.setUpdateTime(DateUtil.date());
            unifiedOrderCredit.setUpdateUserId(1L);

            hedgeUnifiedOrderCreditList.add(unifiedOrderCredit);

//				unifiedOrderCreditMapper.insert(unifiedOrderCredit);


//			}

        }

        return hedgeUnifiedOrderCreditList;

    }

    /**
     * 处理 对冲 商品
     *
     * @param unifiedOrderReturnGoods
     */
    private List<UnifiedOrderGoods> processScoreOrderRefundUnifiedOrderGoods(UnifiedOrderReturn unifiedOrderReturn, UnifiedOrderReturnGoods unifiedOrderReturnGoods) {

        List<UnifiedOrderGoods> hedgeUnifiedOrderGoodsList = new ArrayList<>();

        log.info("processScoreOrderRefundUnifiedOrderGoods :: unifiedOrderReturn \n{}", JSONUtil.toJsonStr(unifiedOrderReturn));
        log.info("processScoreOrderRefundUnifiedOrderGoods :: unifiedOrderReturnGoods \n{}", JSONUtil.toJsonStr(unifiedOrderReturnGoods));

        // TODO 查一下这个对冲商品有没有 20201017 12:00 发现有个问题,如果同一个单 多个商品退单好像有问题 排查
//		UnifiedOrderGoodsExample example = new UnifiedOrderGoodsExample();
//		example.createCriteria()
//				.andOrderSnEqualTo(unifiedOrderReturn.getOrderSn())
//				.andGoodsIdEqualTo(unifiedOrderReturnGoods.getGoodsId())// 目前 数据库有可能是没记录的 // TODO 什么时候 修下这个问题, 再回头修改这里
////                .andPriceEqualTo(unifiedOrderReturnGoods.getPrice()) // TODO 按道理 这个金额是不会变的,存于商城快照
////                .andCostPriceEqualTo(unifiedOrderReturnGoods.getCostPrice()) // TODO 按道理 这个金额是不会变的,存于商城快照
////                .andGoodsNameEqualTo(unifiedOrderReturnGoods.getGoodsName()) // TODO 按道理 这个金额是不会变的,存于商城快照
//				.andQuantityLessThan(0)
//				.andDirectionEqualTo(-1);
//		List<UnifiedOrderGoods> existUnifiedOrderGoodsList = unifiedOrderGoodsMapper.selectByExample(example);

        // 算了 , 不做 更新的情况
//		if (CollUtil.isEmpty(existUnifiedOrderGoodsList)) {
        // 添加一条 负的 对充 商品

        UnifiedOrderGoods unifiedOrderGoods = new UnifiedOrderGoods();

        // TODO 分歧点
//		unifiedOrderGoods.setOrderSn(unifiedOrderReturn.getOrderSn());
        unifiedOrderGoods.setOrderSn(unifiedOrderReturn.getReturnSn());

        unifiedOrderGoods.setGoodsType(CommonOrderGoodsTypeEnum.商品.getKey());
        unifiedOrderGoods.setDirection(CommonDirectionEnum.负向.getKey());

        unifiedOrderGoods.setGoodsLockingCustomer(CommonAccountingLockingEnum.正常.getKey());
        unifiedOrderGoods.setGoodsLockingSupplier(CommonAccountingLockingEnum.正常.getKey());

        unifiedOrderGoods.setAccountingStateCustomer(CommonAccountingStateEnum.未对账.getKey());
        unifiedOrderGoods.setAccountingStateSupplier(CommonAccountingStateEnum.未对账.getKey());


        BigDecimal unitPrice = new BigDecimal(unifiedOrderReturnGoods.getPrice().doubleValue());


        unifiedOrderGoods.setGoodsName(unifiedOrderReturnGoods.getGoodsName());
        // 目前这个退单的商品没这个字段
        unifiedOrderGoods.setOutSnapshotOrderGoodsId(unifiedOrderReturnGoods.getOutSnapshotOrderGoodsId());
        unifiedOrderGoods.setGoodsId(unifiedOrderReturnGoods.getGoodsId());

        // 对充一下负数的数量
        unifiedOrderGoods.setQuantity(0 - unifiedOrderReturnGoods.getQuantity());

        unifiedOrderGoods.setCostPrice(unifiedOrderReturnGoods.getCostPrice());
        unifiedOrderGoods.setPrice(unifiedOrderReturnGoods.getPrice());

        /****************************************** 退单退商品 添加 税率 mark by linjinyu at 20210323 start ******************************************/

        unifiedOrderGoods.setFiscalCode(unifiedOrderReturnGoods.getFiscalCode());
        unifiedOrderGoods.setTaxCode(unifiedOrderReturnGoods.getTaxCode());
        unifiedOrderGoods.setTaxRate(unifiedOrderReturnGoods.getTaxRate());

        // 商户税率
        unifiedOrderGoods.setMerchTaxId(unifiedOrderReturnGoods.getMerchTaxId());
        unifiedOrderGoods.setMerchTaxCode(unifiedOrderReturnGoods.getMerchTaxCode());
        unifiedOrderGoods.setMerchTaxRate(unifiedOrderReturnGoods.getMerchTaxRate());

        // 平台税率
        unifiedOrderGoods.setOperationTaxId(unifiedOrderReturnGoods.getOperationTaxId());
        unifiedOrderGoods.setOperationTaxCode(unifiedOrderReturnGoods.getOperationTaxCode());
        unifiedOrderGoods.setOperationTaxRate(unifiedOrderReturnGoods.getOperationTaxRate());

        // 三级分类
        unifiedOrderGoods.setCateIdLv1(unifiedOrderReturnGoods.getCateIdLv1());
        unifiedOrderGoods.setCateIdLv2(unifiedOrderReturnGoods.getCateIdLv2());
        unifiedOrderGoods.setCateIdLv3(unifiedOrderReturnGoods.getCateIdLv3());

        unifiedOrderGoods.setCateNameLv1(unifiedOrderReturnGoods.getCateNameLv1());
        unifiedOrderGoods.setCateNameLv2(unifiedOrderReturnGoods.getCateNameLv2());
        unifiedOrderGoods.setCateNameLv3(unifiedOrderReturnGoods.getCateNameLv3());

        unifiedOrderGoods.setUnit(StrUtil.isBlank(unifiedOrderReturnGoods.getUnit()) ? CommonOrderGoodsUnitEnum.项.getDesc() : unifiedOrderReturnGoods.getUnit());
        unifiedOrderGoods.setSelfOption(unifiedOrderReturnGoods.getSelfOption());

        /****************************************** 退单退商品 添加 税率 mark by linjinyu at 20210323   end ******************************************/

//		unifiedOrderGoods.setGoodsParams();

        unifiedOrderGoods.setCreateTime(DateUtil.date());
        unifiedOrderGoods.setCreateUserId(1L);

        unifiedOrderGoods.setUpdateTime(DateUtil.date());
        unifiedOrderGoods.setUpdateUserId(1L);

//			unifiedOrderGoodsMapper.insert(unifiedOrderGoods);

        hedgeUnifiedOrderGoodsList.add(unifiedOrderGoods);

//		}
        return hedgeUnifiedOrderGoodsList;
    }

    /**
     * 单主体情况 - 此为订单与退单共用时的情况 mark by linjinyu at 20210628
     * <p>
     * 传入退单 -> 重新核算订单
     * 再重构吧 最终只要传入 orderSn 就好了
     *
     * @param unifiedOrderReturn
     */
    private UnifiedOrder processScoreOrderRefundUnifiedOrder(UnifiedOrderReturn unifiedOrderReturn) {

        log.info("processScoreOrderRefundUnifiedOrder :: unifiedOrderReturn \n{}", JSONUtil.toJsonStr(unifiedOrderReturn));

        UnifiedOrder checkGomputationUnifiedOrder = unifiedOrderMapperEx.findByOrderSn(unifiedOrderReturn.getOrderSn());
        if (null == checkGomputationUnifiedOrder) {
            // TODO 记录错误
            return null;
        }

        UnifiedOrderGoodsExample unifiedOrderGoodsExample = new UnifiedOrderGoodsExample();
        unifiedOrderGoodsExample.createCriteria()
                .andOrderSnEqualTo(unifiedOrderReturn.getOrderSn())
                // 排除退货
                .andDirectionEqualTo(1)
                // 排除运费
                .andGoodsIdNotEqualTo(0L);
//		unifiedOrderGoodsMapperEx.findByOrderSn(unifiedOrderReturn.getOrderSn());
        List<UnifiedOrderGoods> checkGomputationUnifiedOrderGoods = unifiedOrderGoodsMapper.selectByExample(unifiedOrderGoodsExample);
        if (CollUtil.isEmpty(checkGomputationUnifiedOrderGoods)) {
            // TODO 记录错误
            return null;
        }

        BigDecimal checkGomputationAmount     = BigDecimal.ZERO;
        BigDecimal checkGomputationCostAmount = BigDecimal.ZERO;

        checkGomputationAmount = checkGomputationUnifiedOrderGoods
                .stream()
                .map(item -> item.getPrice() == null ? BigDecimal.ZERO : item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        checkGomputationCostAmount = checkGomputationUnifiedOrderGoods
                .stream()
                .map(item -> item.getCostPrice() == null ? BigDecimal.ZERO : item.getCostPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        checkGomputationUnifiedOrder.setAmount(checkGomputationAmount);
        checkGomputationUnifiedOrder.setCostAmount(checkGomputationCostAmount);

        commonOrderProcessService.attachUpdate(checkGomputationUnifiedOrder);

        return checkGomputationUnifiedOrder;

    }
}
