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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.superdesk.uniorder.common.enums.common.CommonDirectionEnum;
import cn.superdesk.uniorder.common.enums.common.CommonOrderSubjectSituationEnum;
import cn.superdesk.uniorder.common.json.AnJsonUtils;
import cn.superdesk.uniorder.common.lamda.AnLamdaUtils;
import cn.superdesk.uniorder.common.rest.response.R;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrder;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderGoods;
import cn.superdesk.uniorder.dao.entity.base.UnifiedOrderReturn;
import cn.superdesk.uniorder.dao.mapper.base.*;
import cn.superdesk.uniorder.dto.vo.unified.UnifiedOrderCommonHeadSum;
import cn.superdesk.uniorder.dto.vo.unified.UnifiedOrderReturnVo;
import cn.superdesk.uniorder.dto.vo.unified.ViewUnifiedOrderReturn;
import cn.superdesk.uniorder.service.order.base.CommonOrderProcessService;
import cn.superdesk.uniorder.service.order.base.UnifiedOrderReturnService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;


/**
 * @Description: 统一订单 退单
 * @Author: linjinyu 修改 补充
 * @CreateDate: 5/12/20 3:47 PM
 * @UpdateUser: linjinyu
 * @UpdateDate: 5/12/20 3:47 PM
 * @UpdateRemark: 修改内容
 * @Version: 1.0
 */
@Slf4j
@Service
public class UnifiedOrderReturnServiceImpl implements UnifiedOrderReturnService {

    @Autowired
    private UnifiedOrderReturnMapper   unifiedOrderReturnMapper;
    @Autowired
    private UnifiedOrderReturnMapperEx unifiedOrderReturnMapperEx;

    @Autowired
    private UnifiedOrderReturnGoodsMapper   unifiedOrderReturnGoodsMapper;
    @Autowired
    private UnifiedOrderReturnGoodsMapperEx unifiedOrderReturnGoodsMapperEx;


    @Autowired
    private UnifiedOrderMapper   unifiedOrderMapper;
    @Autowired
    private UnifiedOrderMapperEx unifiedOrderMapperEx;

    @Autowired
    private UnifiedOrderGoodsMapper   unifiedOrderGoodsMapper;
    @Autowired
    private UnifiedOrderGoodsMapperEx unifiedOrderGoodsMapperEx;

    @Autowired
    private CommonOrderProcessService commonOrderProcessService;


    @Override
    public int insertSelective(UnifiedOrderReturn t) {

        return unifiedOrderReturnMapper.insertSelective(t);
    }

    @Override
    public int updateByPrimaryKeySelective(UnifiedOrderReturn t) {

        return unifiedOrderReturnMapper.updateByPrimaryKeySelective(t);
    }

    @Override
    public void deleteObj(Long id) {

        unifiedOrderReturnMapper.deleteByPrimaryKey(id);
    }

    @Override
    public UnifiedOrderReturn findById(Long id) {

        return unifiedOrderReturnMapper.selectByPrimaryKey(id);
    }


    @Override
    public List<UnifiedOrderReturn> findAll(Map<String, Object> queryMap) {

        return unifiedOrderReturnMapperEx.findAll(queryMap);
    }

    @Override
    public PageInfo<UnifiedOrderReturn> findByPaging(Map<String, Object> params, Integer pageNo, Integer pageSize) {

        return null;
    }


    @Override
    public UnifiedOrderCommonHeadSum getPageHeadSum(Map<String, Object> queryParams) {

        return unifiedOrderReturnMapperEx.getPageH(queryParams);
    }

    @Override
    public List<ViewUnifiedOrderReturn> findView(Map<String, Object> queryParams) {

        return unifiedOrderReturnGoodsMapperEx.findView(queryParams);
    }

    @Override
    public R<List<UnifiedOrderReturnVo>> findViewReturnVo(Map<String, Object> queryParams, int pageNo, int pageSize) {

        PageHelper.startPage(pageNo, pageSize);

        List<UnifiedOrderReturnVo> resultList = unifiedOrderReturnMapperEx.findPage(queryParams);

        PageInfo<UnifiedOrderReturnVo> page = new PageInfo<UnifiedOrderReturnVo>(resultList);
        PageHelper.clearPage();

        return new R<List<UnifiedOrderReturnVo>>(page.getPageNum(), page.getPageSize(), (int) page.getTotal(), resultList);

    }


    /****************************************** 工具方法 start ******************************************/

    /**
     * 退单单号找退单
     *
     * @param refundOrderSn
     * @return
     */
    public List<UnifiedOrderReturn> findByRefundOrderSn(String refundOrderSn) {
        return unifiedOrderReturnMapperEx.findByRefundOrderSn(refundOrderSn);
    }

    public UnifiedOrderReturn getByRefundOrderSn(String refundOrderSn) {

        List<UnifiedOrderReturn> resultList = unifiedOrderReturnMapperEx.findByRefundOrderSn(refundOrderSn);

        if (CollUtil.isNotEmpty(resultList)) {
            return resultList.get(0);
        }

        return null;
    }

    /**
     * 正单单号找退单
     *
     * @param orderSn
     * @return
     */
    public List<UnifiedOrderReturn> findByOrderSn(String orderSn) {
        return unifiedOrderReturnMapperEx.findByOrderSn(orderSn);
    }

    public UnifiedOrderReturn getByOrderSn(String orderSn) {

        List<UnifiedOrderReturn> resultList = unifiedOrderReturnMapperEx.findByOrderSn(orderSn);

        if (CollUtil.isNotEmpty(resultList)) {
            return resultList.get(0);
        }

        return null;
    }


    /**
     * 此方法的前题是 相信京东 京东已经告诉你 有售后 , 没有这个前题的情况下,是否适用,要考量
     * <p>
     * 还有一个前题 只适用 供应商结算场景 与 侨城汇 企业结算(积分) 无关 服务于 京东对账
     * 还有一个作用 就是 隐藏关注 退单的问题 修饰为 只用正单实体就能解决问题
     *
     * @param orderSn
     * @param situationEnum
     * @return
     */
    public UnifiedOrder getByOrderSnAndCheckUpAndFixField(String orderSn, CommonOrderSubjectSituationEnum situationEnum) {

        UnifiedOrder resultOrder = null;

        /****************************************** fail fast 此记录如果没有 很大程度上已经证明没有退单过来 start ******************************************/
        UnifiedOrderReturn unifiedOrderReturn = getByOrderSn(orderSn);

        if (ObjectUtil.isNull(unifiedOrderReturn)) {
            return null;
        }
        /****************************************** fail fast 此记录如果没有 很大程度上已经证明没有退单过来 start ******************************************/


        /****************************************** check up start ******************************************/

        UnifiedOrder orderEntityPlus        = unifiedOrderMapperEx.findByOrderSn(unifiedOrderReturn.getOrderSn());
        UnifiedOrder refundOrderEntityMinus = unifiedOrderMapperEx.findByOrderSn(unifiedOrderReturn.getReturnSn());

        // 如果没有退单主体 断定为 单主体
        if (ObjectUtil.isNull(refundOrderEntityMinus)) {
            situationEnum = CommonOrderSubjectSituationEnum.单主体;
        }

        switch (situationEnum) {
            case 单主体:
                resultOrder = situationForSubjectSingle(orderEntityPlus);
                break;
            case 双主体:
                resultOrder = situationForSubjectDouble(orderEntityPlus, refundOrderEntityMinus);
                break;
            case UNKNOW:
                break;
            default:
                break;

        }

        /****************************************** fix field start ******************************************/

        return resultOrder;

    }

    /**
     * 单主体情况 String orderSn, String refundOrderSn
     */
    public UnifiedOrder situationForSubjectSingle(UnifiedOrder subjectSingleOrder) {

        log.info("situationForSubjectSingle :: UnifiedOrder \n{}", AnJsonUtils.toJson(subjectSingleOrder));

        if (ObjectUtil.isNull(subjectSingleOrder)) {
            log.error("记录错误 situationForSubjectSingle params");
            return null;
        }

        List<UnifiedOrderGoods> checkOrderGoodsList = unifiedOrderGoodsMapperEx.findByOrderSn(subjectSingleOrder.getOrderSn());

        if (CollUtil.isEmpty(checkOrderGoodsList)) {
            log.error("记录错误 situationForSubjectSingle params 订单号 {} 订单商品为 NULL", subjectSingleOrder.getOrderSn());
            return null;
        }

//		BigDecimal checkOrderAmount     = BigDecimal.ZERO;
//		BigDecimal checkOrderCostAmount = BigDecimal.ZERO;
        BigDecimal checkGoodsAmount     = BigDecimal.ZERO;
        BigDecimal checkGoodsCostAmount = BigDecimal.ZERO;

//		BigDecimal checkRefundOrderAmount     = BigDecimal.ZERO;
//		BigDecimal checkRefundOrderCostAmount = BigDecimal.ZERO;
        BigDecimal checkRefundGoodsAmount     = BigDecimal.ZERO;
        BigDecimal checkRefundGoodsCostAmount = BigDecimal.ZERO;


        /****************************************** 正商品 排除 运费 start ******************************************/

        List<Predicate<UnifiedOrderGoods>> predicatesByPlusGoods = new ArrayList<>();
        predicatesByPlusGoods.add(r -> r.getGoodsName() != null && null != r.getDirection() && !r.getGoodsName().equals("运费") && r.getDirection().equals(CommonDirectionEnum.正向.getKey()));

        /****************************************** 正商品   end ******************************************/

        /****************************************** 负商品 排除 退运费 start ******************************************/

        List<Predicate<UnifiedOrderGoods>> predicatesByMinusGoods = new ArrayList<>();
        predicatesByMinusGoods.add(r -> r.getGoodsName() != null && null != r.getDirection() && !r.getGoodsName().equals("退单退运费") && r.getDirection().equals(CommonDirectionEnum.负向.getKey()));

        /****************************************** 负商品   end ******************************************/

        /****************************************** 运费 start ******************************************/
//		List<Predicate<UnifiedOrderGoods>> predicatesByTransportGoods = new ArrayList<>();
//		// 方法1
////        predicatesByTransportGoods.add(r -> r.getGoodsId() != null && r.getGoodsId() == 0 && r.getDirection() == 1);
//		// 方法2
//		predicatesByPlusGoods.add(r -> r.getGoodsName() != null && r.getGoodsName().equals("运费") && r.getDirection() == 1);
        /****************************************** 运费   end ******************************************/

        // 分 正负 向 plus-minus
        List<UnifiedOrderGoods> checkOrderGoodsListGroupPlus  = AnLamdaUtils.filters(checkOrderGoodsList, predicatesByPlusGoods);
        List<UnifiedOrderGoods> checkOrderGoodsListGroupMinus = AnLamdaUtils.filters(checkOrderGoodsList, predicatesByMinusGoods);


        checkGoodsAmount = checkOrderGoodsListGroupPlus
                .stream()
                .map(item -> item.getPrice() == null ? BigDecimal.ZERO : item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        checkGoodsCostAmount = checkOrderGoodsListGroupPlus
                .stream()
                .map(item -> item.getCostPrice() == null ? BigDecimal.ZERO : item.getCostPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        checkRefundGoodsAmount = checkOrderGoodsListGroupMinus
                .stream()
                .map(item -> item.getPrice() == null ? BigDecimal.ZERO : item.getPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        checkRefundGoodsCostAmount = checkOrderGoodsListGroupMinus
                .stream()
                .map(item -> item.getCostPrice() == null ? BigDecimal.ZERO : item.getCostPrice().multiply(new BigDecimal(item.getQuantity())))
                .reduce(BigDecimal.ZERO, BigDecimal::add);

//		subjectSingleOrder.setAmount(checkOrderAmount);
//		subjectSingleOrder.setCostAmount(checkOrderCostAmount);
        subjectSingleOrder.setGoodsAmount(checkGoodsAmount);
        subjectSingleOrder.setGoodsCostAmount(checkGoodsCostAmount);

//		subjectSingleOrder.setRefundOrderAmount(checkRefundOrderAmount);
//		subjectSingleOrder.setRefundOrderCostAmount(checkRefundOrderCostAmount);
        subjectSingleOrder.setRefundGoodsAmount(checkRefundGoodsAmount);
        subjectSingleOrder.setRefundGoodsCostAmount(checkRefundGoodsCostAmount);

        commonOrderProcessService.attachUpdate(subjectSingleOrder);

        return subjectSingleOrder;

    }

    /**
     * 双主体情况
     */
    public UnifiedOrder situationForSubjectDouble(UnifiedOrder subjectDoubleOrderPlus, UnifiedOrder subjectDoubleOrderMinus) {

        return subjectDoubleOrderPlus;

    }

    /****************************************** 工具方法   end ******************************************/

}
