package com.xxfc.platform.order.biz;

import cn.hutool.core.util.ObjectUtil;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.enumconstant.LevelEnum;
import com.google.common.collect.Lists;
import com.xxfc.platform.order.bo.FeeTypeBo;
import com.xxfc.platform.order.contant.enumerate.StatisticsStatusEnum;
import com.xxfc.platform.order.entity.OrderMemberReceivedStatistics;
import com.xxfc.platform.order.mapper.OrderMemberReceivedStatisticsMapper;
import com.xxfc.platform.order.pojo.account.OrderAccountBo;
import com.xxfc.platform.order.pojo.dto.OrderDTO;
import com.xxfc.platform.order.pojo.dto.OrderReceivedStatisticsFindDTO;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 会员订单统计
 *
 * @author libin
 * @email 18178966185@163.com
 * @date 2019-11-08 18:03:42
 */
@Service
@Transactional(rollbackFor = Exception.class)
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class OrderMemberReceivedStatisticsBiz extends BaseBiz<OrderMemberReceivedStatisticsMapper, OrderMemberReceivedStatistics> {
    private final BaseOrderBiz baseOrderBiz;
    private final OrderAccountBiz orderAccountBiz;

    /**
     * 会员统计查询
     *
     * @param orderReceivedStatisticsFindDTO
     * @return
     */
    public List<OrderMemberReceivedStatistics> selectOrderReceivedStatisticsGroupByDate(OrderReceivedStatisticsFindDTO orderReceivedStatisticsFindDTO) {
        return mapper.selectOrderMemberReceivedStatisticsGroupByDate(orderReceivedStatisticsFindDTO);
    }

    public List<OrderMemberReceivedStatistics> selectOrderReceivedStatisticsGroupByMonth(OrderReceivedStatisticsFindDTO orderReceivedStatisticsFindDTO) {
        return mapper.selectOrderMemberReceivedStatisticsGroupByMonth(orderReceivedStatisticsFindDTO);
    }

    public List<OrderMemberReceivedStatistics> selectOrderReceivedStatisticsGroupByWeekOfYear(OrderReceivedStatisticsFindDTO orderReceivedStatisticsFindDTO) {
        return mapper.selectOrderMemberReceivedStatisticsGroupByWeekOfYear(orderReceivedStatisticsFindDTO);
    }

    /**
     * 会员统计处理
     *
     * @param startDate  开始时间
     * @param endDate    结束时间
     * @param companyMap 公司
     */
    public List<OrderMemberReceivedStatistics> orderMemberReceivedStatistics(Date startDate, Date endDate, Map<Integer, String> companyMap) {
        List<OrderMemberReceivedStatistics> orderMemberReceivedStatisticsList = new ArrayList<>(18);
        List<String> stisticsActiveState = new ArrayList<>();

        //根据时间范围查询出会员单
        List<OrderDTO> orders = baseOrderBiz.selectOrdersByTypeAndTime(Arrays.asList(StatisticsStatusEnum.ORDER_MEMBER_TYPE),null, startDate, endDate);
        //数据处理 状态组合 按支付状态分组 而后按组合状态
        Map<Boolean, Map<String, List<OrderDTO>>> stateGroupMap = StatisticsStatusEnum.processOrdersWithState(stisticsActiveState, orders);

        //订单账目信息
        List<OrderAccountBo> orderAccountBoList = orderAccountBiz.selectByTypeAndDate(StatisticsStatusEnum.ORDER_MEMBER_TYPE, startDate, endDate);
        //账目数据处理 状态组合
        Map<String, List<OrderAccountBo>> orderAccountMap = StatisticsStatusEnum.processOrderAccountsWithState(stisticsActiveState, orderAccountBoList);

        //已经支付单
        Set<Map.Entry<String, List<OrderAccountBo>>> ordersSet = orderAccountMap.entrySet();
        for (Map.Entry<String, List<OrderAccountBo>> orderEntry : ordersSet) {
            MemberLevelStatistics memberLevelStatistics = new MemberLevelStatistics();
            //状态key
            String orderKey = orderEntry.getKey();
            //创建默认的会员统计对象
            OrderMemberReceivedStatistics orderMemberReceivedStatistics = createDefaultOrderMemberReceivedStatistics();
            //设置相关默认值
            StatisticsStatusEnum.wrapStatisticsObject(startDate, orderKey, companyMap, orderMemberReceivedStatistics);

            //按会员等级分组
            Map<LevelEnum, List<OrderAccountBo>> orderMemberLevelMap = orderEntry.getValue().stream().collect(Collectors.groupingBy(OrderDTO::getLevelEnum, Collectors.toList()));
            Set<Map.Entry<LevelEnum, List<OrderAccountBo>>> ordermemberLevelentries = orderMemberLevelMap.entrySet();
            //遍历
            for (Map.Entry<LevelEnum, List<OrderAccountBo>> orderMemberLevelEntry : ordermemberLevelentries) {
                //对应状态的订单量
                Integer totalQuantity = stateGroupMap == null ?
                        0 : stateGroupMap.get(Boolean.TRUE).get(orderKey) == null ?
                        0 : stateGroupMap.get(Boolean.TRUE).get(orderKey).size();
                //处理支付金额(支付、退款、违约金)
                wrapMemberLevelStatistics(orderMemberLevelEntry.getKey(), orderMemberLevelEntry.getValue(), totalQuantity, memberLevelStatistics);
            }
            //对应的金额或订单量的复制
            BeanUtils.copyProperties(memberLevelStatistics, orderMemberReceivedStatistics);
            orderMemberReceivedStatisticsList.add(orderMemberReceivedStatistics);
        }

        //未支付单
        Map<String, List<OrderDTO>> noPayOrdersMap = stateGroupMap == null ?
                Collections.EMPTY_MAP : stateGroupMap.get(Boolean.FALSE) == null ?
                Collections.EMPTY_MAP : stateGroupMap.get(Boolean.FALSE);
        List<OrderMemberReceivedStatistics> noPayOrderMemberReceivedStatisticsList = createNoPayOrderMemberReceivedStatisticsList(startDate, noPayOrdersMap, companyMap);
        orderMemberReceivedStatisticsList.addAll(noPayOrderMemberReceivedStatisticsList);

        //创建剩余状态数据
        List<OrderMemberReceivedStatistics> otherStatisticsStateGroupList = createOtherStatisticsStateGroupList(startDate, stisticsActiveState, companyMap);
        orderMemberReceivedStatisticsList.addAll(otherStatisticsStateGroupList);
        //保存
        StatisticsStatusEnum.insertReceivedStatisticsBatch(orderMemberReceivedStatisticsList, mapper);
        return orderMemberReceivedStatisticsList;
    }

    /**
     * memberLevelStatistics 对象包装
     *
     * @param levelEnum             会员等级
     * @param orderAccountBos       账目对象
     * @param totalQuantity         对应等级的单量
     * @param memberLevelStatistics
     * @return
     */
    private MemberLevelStatistics wrapMemberLevelStatistics(LevelEnum levelEnum, List<OrderAccountBo> orderAccountBos, Integer totalQuantity, MemberLevelStatistics memberLevelStatistics) {
        //获取账目各种费用
        FeeTypeBo feeTypeBo = StatisticsStatusEnum.getFeeTyBoByOrderAccounts(orderAccountBos);
        BeanUtils.copyProperties(feeTypeBo, memberLevelStatistics);
        return wrapMemberLevelStatistics(levelEnum, feeTypeBo.getTotalAmount(), totalQuantity, memberLevelStatistics);
    }

    /**
     * @param startDate      时间
     * @param noPayOrdersMap 未支付单map
     * @param companyMap     公司map
     * @return
     */
    private List<OrderMemberReceivedStatistics> createNoPayOrderMemberReceivedStatisticsList(Date startDate, Map<String, List<OrderDTO>> noPayOrdersMap, Map<Integer, String> companyMap) {
        List<OrderMemberReceivedStatistics> orderMemberReceivedStatisticsList = new ArrayList<>();
        if (noPayOrdersMap == null || noPayOrdersMap.isEmpty()) {
            return orderMemberReceivedStatisticsList;
        }
        Set<Map.Entry<String, List<OrderDTO>>> noPayOrderSet = noPayOrdersMap.entrySet();
        for (Map.Entry<String, List<OrderDTO>> noPayOrderEntry : noPayOrderSet) {
            MemberLevelStatistics memberLevelStatistics = new MemberLevelStatistics();
            //获取状态
            String noPayOrderStateGroup = noPayOrderEntry.getKey();
            //创建默认的会员订单统计对象
            OrderMemberReceivedStatistics orderMemberReceivedStatistics = createDefaultOrderMemberReceivedStatistics();
            //设置默认属性值
            StatisticsStatusEnum.wrapStatisticsObject(startDate, noPayOrderStateGroup, companyMap, orderMemberReceivedStatistics);

            //会员订单按等级分组
            Map<LevelEnum, List<OrderDTO>> noPayOrderEntryMap = noPayOrderEntry.getValue().stream().collect(Collectors.groupingBy(OrderDTO::getLevelEnum, Collectors.toList()));
            Set<Map.Entry<LevelEnum, List<OrderDTO>>> noPayOrderEntries = noPayOrderEntryMap.entrySet();
            //遍历等级分组map
            for (Map.Entry<LevelEnum, List<OrderDTO>> orderEntry : noPayOrderEntries) {
                //处理金额(支付金额,订单量)
                wrapOrderMemberReceivedStatistics(orderEntry.getValue(), orderEntry.getKey(), memberLevelStatistics);
            }
            //复制对象属性值(对应的等级金额和订单量)
            BeanUtils.copyProperties(memberLevelStatistics, orderMemberReceivedStatistics);
            orderMemberReceivedStatisticsList.add(orderMemberReceivedStatistics);
        }
        return orderMemberReceivedStatisticsList;
    }

    /**
     * @param orders                某种状态下的会员单
     * @param levelEnum             会员等级
     * @param memberLevelStatistics 会员统计对象
     * @return
     */
    private MemberLevelStatistics wrapOrderMemberReceivedStatistics(List<OrderDTO> orders, LevelEnum levelEnum, MemberLevelStatistics memberLevelStatistics) {
        //会员单对应等级的总量
        orders = CollectionUtils.isEmpty(orders) ? Collections.EMPTY_LIST : orders;
        //会员单对应等级的总金额
        BigDecimal totalAmount = orders.stream().map(OrderDTO::getRealAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        return wrapMemberLevelStatistics(levelEnum, totalAmount, orders.size(), memberLevelStatistics);
    }

    /**
     * memberLevelStatistics 对象包装
     *
     * @param levelEnum             会员等级
     * @param amount                订单总额
     * @param quantity              订单量
     * @param memberLevelStatistics
     * @return
     */
    private MemberLevelStatistics wrapMemberLevelStatistics(LevelEnum levelEnum, BigDecimal amount, Integer quantity, MemberLevelStatistics memberLevelStatistics) {
        switch (levelEnum) {
            //普通会员
            case GENERAL:
                memberLevelStatistics.setToalCommonAmmount(amount);
                memberLevelStatistics.setTotalCommonQuantity(quantity);
                break;
            //黄金会员
            case GOLD:
                memberLevelStatistics.setTotalGoldAmount(amount);
                memberLevelStatistics.setTotalGoldQuantity(quantity);
                break;
            //钻石会员
            case DIAMOND:
                memberLevelStatistics.setTotalDiamondAmmount(amount);
                memberLevelStatistics.setTotalDiamondQuantity(quantity);
                break;
            default:
                break;
        }
        return memberLevelStatistics;
    }

    /**
     * 创建剩余状态数据
     *
     * @param startDate             时间
     * @param statisticsStateGroups 状态组合 集合
     * @param companyMap            公司
     * @return
     */
    private List<OrderMemberReceivedStatistics> createOtherStatisticsStateGroupList(Date startDate, List<String> statisticsStateGroups, Map<Integer, String> companyMap) {
        List<OrderMemberReceivedStatistics> orderMemberReceivedStatisticsList = new ArrayList<>();
        //获取剩余状态组合
        List<Integer> companyIds = Objects.isNull(companyMap) ? Collections.EMPTY_LIST : Lists.newArrayList(companyMap.keySet());
        List<String> otherStatisticsStateGroup = StatisticsStatusEnum.getOtherStatisticsStateGroup(companyIds, statisticsStateGroups);
        //创建会员克隆统计对象
        OrderMemberReceivedStatistics orderMemberReceivedStatistics = createDefaultOrderMemberReceivedStatistics();
        //统计对象的生成
        otherStatisticsStateGroup.stream().peek(stateGroup -> {
            OrderMemberReceivedStatistics orderMemberReceivedStatisticsClone = StatisticsStatusEnum.wrapStatisticsObject(startDate, stateGroup, companyMap,
                    ObjectUtil.clone(orderMemberReceivedStatistics));
            orderMemberReceivedStatisticsList.add(orderMemberReceivedStatisticsClone);
        }).count();
        return orderMemberReceivedStatisticsList;
    }

    /**
     * 创建默认的会员订单统计对象
     *
     * @return
     */
    private OrderMemberReceivedStatistics createDefaultOrderMemberReceivedStatistics() {
        OrderMemberReceivedStatistics orderMemberReceivedStatistics = new OrderMemberReceivedStatistics();
        orderMemberReceivedStatistics.setTotalCommonQuantity(0);
        orderMemberReceivedStatistics.setToalCommonAmmount(BigDecimal.ZERO);
        orderMemberReceivedStatistics.setTotalGoldQuantity(0);
        orderMemberReceivedStatistics.setTotalGoldAmount(BigDecimal.ZERO);
        orderMemberReceivedStatistics.setTotalDiamondQuantity(0);
        orderMemberReceivedStatistics.setTotalDiamondAmmount(BigDecimal.ZERO);
        return orderMemberReceivedStatistics;
    }

    @Data
    @NoArgsConstructor
    private class MemberLevelStatistics {
        private BigDecimal toalCommonAmmount = BigDecimal.ZERO;

        private Integer totalCommonQuantity = new Integer(0);

        private BigDecimal totalGoldAmount = BigDecimal.ZERO;

        private Integer totalGoldQuantity = new Integer(0);

        private BigDecimal totalDiamondAmmount = BigDecimal.ZERO;

        private Integer totalDiamondQuantity = new Integer(0);

        private BigDecimal totalAmount;

        private Integer totalQuantity;

        /**
         * 违约金
         */
        private BigDecimal lateFeeAmount = BigDecimal.ZERO;
        /**
         * 订单退款金额
         */
        private BigDecimal orderRefundAmount = BigDecimal.ZERO;

        public BigDecimal getTotalAmount() {
            return toalCommonAmmount.add(totalGoldAmount).add(totalDiamondAmmount);
        }

        public Integer getTotalQuantity() {
            return totalCommonQuantity + totalGoldQuantity + totalDiamondQuantity;
        }
    }
}