package com.xxfc.platform.order.biz;

import cn.hutool.json.JSONUtil;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.xxfc.platform.order.contant.enumerate.AccountTypeEnum;
import com.xxfc.platform.order.contant.enumerate.DeductionTypeEnum;
import com.xxfc.platform.order.contant.enumerate.OrderTypeEnum;
import com.xxfc.platform.order.entity.DailyOrderStatistics;
import com.xxfc.platform.order.entity.DailyVehicleOrderStatistics;
import com.xxfc.platform.order.entity.OrderAccount;
import com.xxfc.platform.order.entity.OrderStatistics;
import com.xxfc.platform.order.mapper.DailyVehicleOrderStatisticsMapper;
import com.xxfc.platform.order.pojo.account.OrderAccountDTO;
import com.xxfc.platform.order.pojo.account.OrderAccountDeduction;
import com.xxfc.platform.order.pojo.account.OrderAccountDetail;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import tk.mybatis.mapper.common.example.UpdateByExampleSelectiveMapper;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

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

/**
 * 每日租车订单统计
 *
 * @author Administrator
 */
@Service
@Slf4j
public class DailyVehicleOrderStatisticsBiz extends BaseBiz<DailyVehicleOrderStatisticsMapper, DailyVehicleOrderStatistics> {
    /**
     * 延期
     */
    private final Integer TYPE_DEFERRED = 1;
    /**
     * 损坏
     */
    private final Integer TYPE_DAMAGE = 2;
    /**
     * 其他
     */
    private final Integer TYPE_OTHER = 3;

    /**
     * 统计几天前的数据
     */
    @Value("${order.day}")
    private Integer day;


    @Autowired
    private OrderAccountBiz accountBiz;


//    @Transactional(rollbackFor = Exception.class)
//    public boolean StatisticsOfCarRentalOrders() {
//
//        try {
//
//            ArrayList<DailyVehicleOrderStatistics> result = new ArrayList<>();
//
////        获取每日租车订单成交金和押金总额
//            List<DailyVehicleOrderStatistics> gmvAndMarginTotal = mapper.getGmvAndMarginTotal(day);
//            result.addAll(gmvAndMarginTotal);
//
////        获取取消订单扣款总额
//            List<DailyVehicleOrderStatistics> penalSum = mapper.getPenalSum(day);
//            result.addAll(penalSum);
//
////        获取订单退还押金总额
//            List<DailyVehicleOrderStatistics> refundSecurityDeposit = mapper.getRefundSecurityDeposit(day);
//            result.addAll(refundSecurityDeposit);
//
////        获取违章查询总和
//            List<DailyVehicleOrderStatistics> violationMoney = mapper.getViolationMoney(day);
//            result.addAll(violationMoney);
//
////        获取赔偿和延期JSON字符串
//            List<Map> compensationAndPostpone = mapper.getCompensationAndPostpone(day);
////        获取赔偿和延期JSON字符串转换为map
//            List<DailyVehicleOrderStatistics> compensationAndPostpones = getCompensationAndPostpones(compensationAndPostpone);
//            result.addAll(compensationAndPostpones);
//
//            InsertByList(result);
//            return true;
//        } catch (Exception e) {
//            e.printStackTrace();
//            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
//            return false;
//        }
//
//    }
//
//    private void InsertByList(ArrayList<DailyVehicleOrderStatistics> result) throws Exception {
//        if (CollectionUtils.isNotEmpty(result)) {
//
//            Map<Integer, DailyVehicleOrderStatistics> map = new HashMap<>();
//
//            for (DailyVehicleOrderStatistics value : result) {
//                Integer branchCompanyId = value.getBranchCompanyId();
//                DailyVehicleOrderStatistics statistics = map.get(branchCompanyId);
//
//                if (statistics == null) {
//                    statistics = new DailyVehicleOrderStatistics();
//                    map.put(branchCompanyId, statistics);
//                }
//                BeanUtil.copyProperties(
//                        value,
//                        statistics,
//                        CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
//            }
//
//            String oneDay = map.entrySet().parallelStream().map(Map.Entry::getValue).collect(Collectors.toList()).get(0).getOneDay();
//            if (StringUtils.isBlank(oneDay)) {
//                throw new BaseException();
//            }
//            Example exa = new Example(DailyVehicleOrderStatistics.class);
//            exa.createCriteria().andEqualTo("oneDay", oneDay);
//            List<DailyVehicleOrderStatistics> statistics = selectByExample(exa);
//
//            if (CollectionUtils.isEmpty(statistics)) {
//                for (Map.Entry<Integer, DailyVehicleOrderStatistics> entry : map.entrySet()) {
//                    insertSelectiveRe(entry.getValue());
//                }
//            } else {
//                log.error("今日已统计车辆订单,请不要重复统计!");
//            }
//        }
//
//    }
//
//
//    /**
//     * 获取赔偿总额和延期总额
//     */
//    private List<DailyVehicleOrderStatistics> getCompensationAndPostpones(List<Map> list) {
//
//        if (CollectionUtils.isNotEmpty(list)) {
//            //获取分公全部赔偿和延期DedDetailDTO
//            HashMap<Integer, List<DedDetailDTO>> map = new HashMap<>();
//
//            for (Map value : list) {
//                if (value != null) {
//
//                    //获取分公司id
//                    Integer branchCompanyId = (Integer) value.get("branchCompanyId");
//                    List<DedDetailDTO> strings = map.get(branchCompanyId);
//                    if (strings == null) {
//                        strings = new ArrayList<DedDetailDTO>();
//                        map.put(branchCompanyId, strings);
//                    }
//
//                    String str = (String) value.get("dedDetail");
//
//                    if (StringUtils.isNotBlank(str)) {
//                        List<DedDetailDTO> dedDetailDTOS = JSON.parseArray(str, DedDetailDTO.class);
//                        if (CollectionUtils.isNotEmpty(dedDetailDTOS)) {
//                            strings.addAll(dedDetailDTOS);
//                        }
//                    }
//                }
//
//            }
//
//
//            List<DailyVehicleOrderStatistics> result = new ArrayList<>();
//
//            if (!map.isEmpty()) {
//
//                //获取分工对象集合
//                for (Map.Entry<Integer, List<DedDetailDTO>> entry : map.entrySet()) {
//                    DailyVehicleOrderStatistics statistics = new DailyVehicleOrderStatistics();
//                    //公司id添加到对象当中
//                    statistics.setBranchCompanyId(entry.getKey());
//
//                    //获取公司的JSON字符串
//                    List<DedDetailDTO> sumDedDetailDTOs = entry.getValue();
//
////            获取赔偿金额总和
//                    BigDecimal compensation = get(sumDedDetailDTOs, TYPE_DAMAGE);
//                    statistics.setCompensation(compensation);
////            获取延期金额总和
//                    BigDecimal postpone = get(sumDedDetailDTOs, TYPE_DEFERRED);
//                    statistics.setPostpone(postpone);
//////            其他款项总金额
////                    BigDecimal other = get(sumDedDetailDTOs, TYPE_OTHER);
//
//                    result.add(statistics);
//                }
//
//            }
//
//
//            return result;
//        }
//        return new ArrayList<>();
//    }
    /****************************************************************************************************************************/


    /**
     * 根据type获取对应的金额总和
     *
     * @param list
     * @param types 金额类型
     * @return
     */
    private BigDecimal get(List<OrderAccountDeduction> list, List<Integer> types) {
        return list.parallelStream()
                .filter(el -> types.contains(el.getType()))
                .map(OrderAccountDeduction::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

    }

    /***
     * 添加每日记录
     * @param entity
     * @return
     */
    @Override
    public int insertSelectiveRe(DailyVehicleOrderStatistics entity) {
        entity.setCrtTime(new Date());
        return mapper.insertSelective(entity);
    }


    public OrderStatistics findAll(Integer companyId) {
        return mapper.monthOrderTotal(companyId);
    }

    /**
     * 统计订单并保存到数据库当中
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean saveDailyVehicleOrderRecord() {
        try {
            //获取每日订单统计
            List<DailyVehicleOrderStatistics> orderStatistics = getDailyVehicleOrderRecord();
            log.info("Vehicle:统计完成");
            if (CollectionUtils.isNotEmpty(orderStatistics)) {
                for (DailyVehicleOrderStatistics orderStatistic : orderStatistics) {
                    //保存统计
                    if (JudgmentOfExistence(orderStatistic)) {

                        insertSelectiveRe(orderStatistic);
                    } else {
                        mapper.updateByExampleSelective(orderStatistic, Example.builder(DailyVehicleOrderStatistics.class)
                                .where(WeekendSqls.<DailyVehicleOrderStatistics>custom()
                                        .andEqualTo(DailyVehicleOrderStatistics::getOneDay, orderStatistic.getOneDay())
                                        .andEqualTo(DailyVehicleOrderStatistics::getBranchCompanyId, orderStatistic.getBranchCompanyId()))
                                .build());

                    }
                }
            }
            log.info("Vehicle:保存成功");
            return true;
        } catch (Exception e) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            log.error("Vehicle:" + e.getMessage());
            return false;
        }
    }

    private boolean JudgmentOfExistence(DailyVehicleOrderStatistics orderStatistic) {
        List<DailyVehicleOrderStatistics> statistics = selectByExample(Example.builder(DailyVehicleOrderStatistics.class)
                .where(WeekendSqls.<DailyVehicleOrderStatistics>custom()
                        .andEqualTo(DailyVehicleOrderStatistics::getOneDay, orderStatistic.getOneDay())
                        .andEqualTo(DailyVehicleOrderStatistics::getBranchCompanyId, orderStatistic.getBranchCompanyId()))
                .build());
        if (CollectionUtils.isNotEmpty(statistics)) {
            return false;
        }
        return true;
    }

    /**
     * 获取所有分公司每日统计记录
     *
     * @return
     */
    private List<DailyVehicleOrderStatistics> getDailyVehicleOrderRecord() {
        //获取当天所有订单账目
        List<OrderAccountDTO> accountList = accountBiz.getOrderAccountByOrderType(OrderTypeEnum.RENT_VEHICLE.getCode(), day);
        if (CollectionUtils.isEmpty(accountList)) {
            return null;
        }
        //获取每个分公司当天所有的订单帐目
        HashMap<Integer, List<OrderAccountDTO>> companyIdmap = new HashMap<>();
        for (OrderAccountDTO orderAccountDTO : accountList) {
            List<OrderAccountDTO> list = companyIdmap.get(orderAccountDTO.getCompanyId());
            if (list == null) {
                list = new ArrayList<>();
                companyIdmap.put(orderAccountDTO.getCompanyId(), list);
            }
            list.add(orderAccountDTO);
        }

        //获取每个公司当天订单的总数据
        ArrayList<DailyVehicleOrderStatistics> statistics = new ArrayList<>();
        for (Map.Entry<Integer, List<OrderAccountDTO>> integerListEntry : companyIdmap.entrySet()) {
            //获取不同类型的账单详情
            List<OrderAccountDTO> orderAccountDTOS = integerListEntry.getValue();
            if (CollectionUtils.isNotEmpty(orderAccountDTOS)) {
                Map<Integer, List<OrderAccountDTO>> typeMap = Maps.newHashMap();
                for (OrderAccountDTO orderAccountDTO : orderAccountDTOS) {

                    List<OrderAccountDTO> list = typeMap.get(orderAccountDTO.getAccountType());
                    if (list == null) {
                        list = new ArrayList<>();
                        typeMap.put(orderAccountDTO.getAccountType(), list);

                    }
                    list.add(orderAccountDTO);
                }

                if (MapUtils.isNotEmpty(typeMap)) {
                    //获取该公司当天的账单数据
                    if (CollectionUtils.isNotEmpty(orderAccountDTOS)) {
                        DailyVehicleOrderStatistics dvos = getStatisticsByOrderAccountDetail(typeMap);
                        if (dvos != null) {
                            statistics.add(dvos);
                            dvos.setBranchCompanyId(integerListEntry.getKey());
                            dvos.setOneDay(orderAccountDTOS.get(0).getOneDay());
                        }
                    }
                }
            }
        }

        return statistics;
    }


    /**
     * 获取该分公司的统计数据
     *
     * @param map
     * @return
     */
    private DailyVehicleOrderStatistics getStatisticsByOrderAccountDetail(Map<Integer, List<OrderAccountDTO>> map) {
        //获取收入金额
        DailyVehicleOrderStatistics orderStatistics = getGmvAndSecurityDeposit(map);
        //获取扣款和退还金额
        refundAndDeductions(map, orderStatistics);
        return orderStatistics;

    }

    /**
     * 获取扣款和退款金额
     *
     * @param map
     * @param orderStatistics
     */
    private void refundAndDeductions(Map<Integer, List<OrderAccountDTO>> map, DailyVehicleOrderStatistics orderStatistics) {
        ArrayList<OrderAccountDTO> arrayList = Lists.newArrayList();
        for (Integer key : map.keySet()) {
            if (!key.equals(AccountTypeEnum.IN_ORDER_PAY.getCode())) {
                arrayList.addAll(map.get(key));
            }
        }
        if (CollectionUtils.isNotEmpty(arrayList)) {
            ArrayList<OrderAccountDetail> orderAccountDetail = getOrderAccountDetail(arrayList);
            if (CollectionUtils.isNotEmpty(orderAccountDetail)) {
                //获取退还订总额
                BigDecimal returnGmv = getOrderAmountTotal(orderAccountDetail);
                orderStatistics.setReturnGmv(returnGmv);
                //获取退还押金总额
                BigDecimal refundSecurityDeposit = getDepositAmountTotal(orderAccountDetail);
                orderStatistics.setRefundSecurityDeposit(refundSecurityDeposit);
                List<OrderAccountDeduction> OrderAccountDeductions = gettDeductions(orderAccountDetail);
                //获取违章总额
                orderStatistics.setViolationMoney(get(OrderAccountDeductions, new ArrayList<Integer>() {{
                    add(DeductionTypeEnum.VIOLATE_TRAFFIC_DEDUCT.getCode());
                }}));
                //获取损坏赔偿总额
                orderStatistics.setCompensation(get(OrderAccountDeductions, new ArrayList<Integer>() {{
                    add(DeductionTypeEnum.DAMAGES.getCode());
                }}));
                //获取违约总额
                ArrayList<Integer> types = Lists.newArrayList();
                types.add(DeductionTypeEnum.VIOLATE_ADVANCE.getCode());
                types.add(DeductionTypeEnum.VIOLATE_CANCEL.getCode());
                types.add(DeductionTypeEnum.VIOLATE_DELAY.getCode());
                orderStatistics.setDefaultMoney(get(OrderAccountDeductions, types));

                //消费金额
                orderStatistics.setTotalExpenditure(get(OrderAccountDeductions, new ArrayList<Integer>() {{
                    add(DeductionTypeEnum.CONSUME.getCode());
                }}));
            }
        }
    }

    /**
     * 获取订单总额和预交押金总额
     *
     * @param map
     * @return
     */
    private DailyVehicleOrderStatistics getGmvAndSecurityDeposit(Map<Integer, List<OrderAccountDTO>> map) {
        DailyVehicleOrderStatistics orderStatistics = new DailyVehicleOrderStatistics();
        List<OrderAccountDTO> orderAccountDTOS = map.get(AccountTypeEnum.IN_ORDER_PAY.getCode());

        if (CollectionUtils.isNotEmpty(orderAccountDTOS)) {
            ArrayList<OrderAccountDetail> orderAccountDetails = getOrderAccountDetail(orderAccountDTOS);
            if (CollectionUtils.isNotEmpty(orderAccountDetails)) {
                //获取订单总额
                BigDecimal gmv = getOrderAmountTotal(orderAccountDetails);
                orderStatistics.setGmv(gmv);
                //获取押金总额
                BigDecimal securityDeposit = getDepositAmountTotal(orderAccountDetails);
                orderStatistics.setSecurityDeposit(securityDeposit);


            }
        }
        return orderStatistics;
    }

    /**
     * 获取订单和
     *
     * @param orderAccountDetails
     * @return
     */
    private BigDecimal getDepositAmountTotal(ArrayList<OrderAccountDetail> orderAccountDetails) {
        return orderAccountDetails.stream()
                .map(OrderAccountDetail::getDepositAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取押金和
     *
     * @param orderAccountDetails
     * @return
     */
    private BigDecimal getOrderAmountTotal(ArrayList<OrderAccountDetail> orderAccountDetails) {
        return orderAccountDetails.stream()
                .map(OrderAccountDetail::getOrderAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    /**
     * 获取赔款数据
     *
     * @param orderAccountDetails
     * @return
     */
    private List<OrderAccountDeduction> gettDeductions(ArrayList<OrderAccountDetail> orderAccountDetails) {
        ArrayList<OrderAccountDeduction> arrayList = Lists.newArrayList();
        orderAccountDetails.parallelStream().map(OrderAccountDetail::getDeductions).forEach(e -> arrayList.addAll(e));
        return arrayList;
    }

    /**
     * 获取金额详情
     *
     * @param orderAccountDTOS
     * @return
     */
    private ArrayList<OrderAccountDetail> getOrderAccountDetail(List<OrderAccountDTO> orderAccountDTOS) {
        ArrayList<OrderAccountDetail> arrayList = Lists.newArrayList();
        orderAccountDTOS.parallelStream()
                .map(OrderAccount::getAccountDetail)
                .forEach(detail -> {
                    if (StringUtils.isNotBlank(detail)) {
                        arrayList.add(JSONUtil.toBean(detail, OrderAccountDetail.class));
                    }
                });

        return arrayList;
    }


}
