package com.xxfc.platform.order.biz;

import cn.hutool.core.collection.CollectionUtil;
import com.github.wxiaoqi.security.admin.entity.BaseUserMemberLevel;
import com.github.wxiaoqi.security.common.biz.BaseBiz;
import com.github.wxiaoqi.security.common.exception.BaseException;
import com.github.wxiaoqi.security.common.msg.auth.PageResult;
import com.google.common.collect.Maps;
import com.xxfc.platform.order.Utils.OrderDateUtils;
import com.xxfc.platform.order.contant.enumerate.OrderInquiryType;
import com.xxfc.platform.order.contant.enumerate.OrderTypeEnum;
import com.xxfc.platform.order.entity.*;
import com.xxfc.platform.order.mapper.OrderStatisticsMapper;
import com.xxfc.platform.order.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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


/**
 * @author Administrator
 */
@Service
@Slf4j
public class OrderStatisticsBiz extends BaseBiz<OrderStatisticsMapper, OrderStatistics> {
    @Autowired
    private DailyVehicleOrderStatisticsBiz vehicleBiz;
    @Autowired
    private DailyTravelOrderStatisticsBiz TravelBiz;
    @Autowired
    private DailyMembersOrderStatisticsBiz membersBiz;

    @Autowired
    private DailyVehicleOrderStatisticsBiz vehicleStatisticsBiz;
    @Autowired
    private DailyTravelOrderStatisticsBiz travelStatisticsBiz;
    @Autowired
    private DailyMembersOrderStatisticsBiz membersStatisticsBiz;

    public HomePageOrderData getTotalOrder(List<Integer> companyIds, Integer dataAll) {
        HomePageOrderData result = new HomePageOrderData();
        ArrayList<HomePageOrderData> list = new ArrayList<>();
        list.add(getVehicleHomePageOrderData(companyIds));
        list.add(getTourHomePageOrderData(companyIds));
        if (1==dataAll) {
            list.add(getMemberHomePageOrderData(companyIds));
        }
        result.setTotalOrders(list.stream().map(HomePageOrderData::getTotalOrders).reduce(BigDecimal.ZERO, BigDecimal::add));
        result.setTotalOutstandingDeposit(list.stream().map(HomePageOrderData::getTotalOutstandingDeposit).reduce(BigDecimal.ZERO, BigDecimal::add));
        result.setAdditionalIndemnity(list.stream().map(HomePageOrderData::getAdditionalIndemnity).reduce(BigDecimal.ZERO, BigDecimal::add));
        return result;
    }

    /**
     * 会员数据
     *
     * @param companyIds
     * @return
     */
    public HomePageOrderData getMemberHomePageOrderData(List<Integer> companyIds) {
        //今天之前的数据
        OrderStatistics member = membersBiz.findAll(companyIds);
        log.error("member:"+member);
        //当天的数据
        OrderStatistics sameDayData = getMemberOrderDataOfTheDay(companyIds);
        log.error("member:sameDayData:"+sameDayData);

        if (member == null) {
            member = new OrderStatistics();
        }

        add(member, sameDayData);

        OrderStatistics finalMember = member;
        HomePageOrderData data = new HomePageOrderData() {{
            setTotalOrders(finalMember.getTotalGmv());
        }};
        return data;
    }

    /**
     * 获取会员订单当天数据
     *
     * @param companyIds
     * @return
     */
    public OrderStatistics getMemberOrderDataOfTheDay(List<Integer> companyIds) {
        OrderStatistics member = new OrderStatistics();
        DailyMembersOrderStatistics statistics = membersStatisticsBiz.statistics(new Term(OrderTypeEnum.MEMBER.getCode(), 0, 1, null, null, companyIds));
        if (statistics == null) {
            return new OrderStatistics();
        }

        //加入会员订单收入
        member.setTotalGmv(member.getTotalGmv().add(statistics.getGmv()));
        return member;
    }


    //加上当天数据
    private void add(OrderStatistics original, OrderStatistics add) {
        original.setTotalGmv(original.getTotalGmv().add(add.getTotalGmv()));
        original.setTotalReturnGmv(original.getTotalReturnGmv().add(add.getTotalReturnGmv()));
        original.setTotalSecurityDeposit(original.getTotalSecurityDeposit().add(add.getTotalSecurityDeposit()));
        original.setTotalRefundSecurityDeposit(original.getTotalRefundSecurityDeposit().add(add.getTotalRefundSecurityDeposit()));
        original.setTotalDefaultMoney(original.getTotalDefaultMoney().add(add.getTotalDefaultMoney()));
        original.setTotalOrderCompensation(original.getTotalOrderCompensation().add(add.getTotalOrderCompensation()));
        original.setTotalCompensation(original.getTotalCompensation().add(add.getTotalCompensation()));
        original.setTotalForfeit(original.getTotalForfeit().add(add.getTotalForfeit()));
    }


    /**
     * 旅游数据
     *
     * @param companyIds
     * @return
     */
    public HomePageOrderData getTourHomePageOrderData(List<Integer> companyIds) {
        //今天之前的数据
        OrderStatistics tour = TravelBiz.findAll(companyIds);
        log.error("tour:"+tour);
        if (tour == null) {
            tour = new OrderStatistics();
        }
        OrderStatistics sameDayData = getTourOrderDataOfTheDay(companyIds);
        log.error("tour:sameDayData:"+sameDayData);
        add(tour, sameDayData);
        OrderStatistics finalTour = tour;
        HomePageOrderData data = new HomePageOrderData() {{
            setTotalOrders(finalTour.getTotalGmv().subtract(finalTour.getTotalReturnGmv()));
            setAdditionalIndemnity(finalTour.getTotalDefaultMoney());
        }};
        return data;
    }

    /**
     * 获取租车订单当天数据
     *
     * @param companyIds
     * @return
     */
    public OrderStatistics getTourOrderDataOfTheDay(List<Integer> companyIds) {
        OrderStatistics tour = new OrderStatistics();

        //当天数据
        List<DailyTravelOrderStatistics> record = travelStatisticsBiz.getDailyTravelOrderStatistics(new Term(OrderTypeEnum.TOUR.getCode(), 0, 1, null, null, companyIds));
        if (CollectionUtils.isEmpty(record)) {
            return new OrderStatistics();
        }
        //加入当天旅游路线订单总和
        tour.setTotalGmv(tour.getTotalGmv().add(record.parallelStream().map(DailyTravelOrderStatistics::getGmv).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入当天退还订单总和
        tour.setTotalReturnGmv(tour.getTotalReturnGmv().add(record.parallelStream().map(DailyTravelOrderStatistics::getReturnGmv).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入当违约总和
        tour.setTotalDefaultMoney(tour.getTotalDefaultMoney().add(record.parallelStream().map(DailyTravelOrderStatistics::getDefaultMoney).reduce(BigDecimal.ZERO, BigDecimal::add)));
        return tour;
    }

    /**
     * 车辆数据
     *
     * @param companyIds
     * @return
     */
    public HomePageOrderData getVehicleHomePageOrderData(List<Integer> companyIds) {
        //今天之前的数据
        OrderStatistics vehicle = vehicleBiz.findAll(companyIds);
        log.error("vehicle:"+vehicle);
        if (vehicle == null) {
            vehicle = new OrderStatistics();
        }
        OrderStatistics sameDayData = getVehicleOrderDataOfTheDay(companyIds);
        log.error("vehicle:sameDayData:"+sameDayData);
        add(vehicle, sameDayData);

        OrderStatistics finalVehicle = vehicle;
        HomePageOrderData data = new HomePageOrderData() {{
            setTotalOrders(finalVehicle.getTotalGmv().subtract(finalVehicle.getTotalReturnGmv()));
            setAdditionalIndemnity(finalVehicle.getTotalCompensation()
                    .add(finalVehicle.getTotalForfeit())
                    .add(finalVehicle.getTotalDefaultMoney())
                    .add(finalVehicle.getTotalOrderCompensation()));
            setTotalOutstandingDeposit(finalVehicle.getTotalSecurityDeposit()
                    .subtract(finalVehicle.getTotalRefundSecurityDeposit())
                    .subtract(getAdditionalIndemnity()));
        }};
        return data;

    }

    /**
     * 获取车来个你当天数据
     *
     * @param companyIds
     * @return
     */
    public OrderStatistics getVehicleOrderDataOfTheDay(List<Integer> companyIds) {
        OrderStatistics vehicle = new OrderStatistics();
        //当天的数据
        List<DailyVehicleOrderStatistics> record = vehicleStatisticsBiz.getDailyVehicleOrderRecord(new Term(OrderTypeEnum.RENT_VEHICLE.getCode(), 0, 1, null, null, companyIds));

        if (CollectionUtils.isEmpty(record)) {
            return new OrderStatistics();
        }
        //加入当天租车订单总和
        vehicle.setTotalGmv(vehicle.getTotalGmv().add(record.parallelStream().map(DailyVehicleOrderStatistics::getGmv).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入当天退还订单总和
        vehicle.setTotalReturnGmv(vehicle.getTotalReturnGmv().add(record.parallelStream().map(DailyVehicleOrderStatistics::getReturnGmv).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入当违约总和
        vehicle.setTotalDefaultMoney(vehicle.getTotalDefaultMoney().add(record.parallelStream().map(DailyVehicleOrderStatistics::getDefaultMoney).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入当天押金总和
        vehicle.setTotalSecurityDeposit(vehicle.getTotalSecurityDeposit().add(record.parallelStream().map(DailyVehicleOrderStatistics::getSecurityDeposit).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入退还押金总和
        vehicle.setTotalRefundSecurityDeposit(vehicle.getTotalRefundSecurityDeposit().add(record.parallelStream().map(DailyVehicleOrderStatistics::getRefundSecurityDeposit).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入赔偿
        vehicle.setTotalCompensation(vehicle.getTotalCompensation().add(record.parallelStream().map(DailyVehicleOrderStatistics::getCompensation).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //加入违章
        vehicle.setTotalForfeit(vehicle.getTotalForfeit().add(record.parallelStream().map(DailyVehicleOrderStatistics::getForfeit).reduce(BigDecimal.ZERO, BigDecimal::add)));
        //损坏赔偿
        vehicle.setTotalOrderCompensation(vehicle.getTotalOrderCompensation().add(record.parallelStream().map(DailyVehicleOrderStatistics::getOrderCompensation).reduce(BigDecimal.ZERO, BigDecimal::add)));
        return vehicle;
    }


    /**
     * 会员统计列表
     *
     * @param memberLevels
     * @param query
     * @return
     * @throws ParseException
     */
    public PageResult getMemberOrderStatistics(List<BaseUserMemberLevel> memberLevels, OrderQuery query) throws ParseException {

        List<MembersOrder> membersOrderList = membersBiz.getMemberOrderStatistics(query);

        //按每天分类
        if (CollectionUtil.isEmpty(membersOrderList)) {
            return PageResult.nowPageResult(query.getPage(), query.getLimit(), Lists.newArrayList());
        }
        //按每天分类
        if (CollectionUtil.isEmpty(memberLevels)) {
            throw new BaseException("获取不到会员信息");
        }
        //获取会员等级对应的名称
        HashMap<Integer, String> map = Maps.newHashMap();
        for (BaseUserMemberLevel memberLevel : memberLevels) {
            map.put(memberLevel.getLevel(), memberLevel.getName());
        }
        //按查询条件获取统计信息
        ArrayList<MembersOrderDto> arrayList = Lists.newArrayList();
        if (OrderInquiryType.DAY.getCode().equals(query.getType())) {
            for (MembersOrder mb : membersOrderList) {
                MembersOrderDto mbdto = new MembersOrderDto();
                //设置时间段
                mbdto.setTimeSlot(mb.getPeriod());
                TotalPaymentAndMemberName(map, mb, mbdto);
                arrayList.add(mbdto);
            }
        } else {
            for (int i = 0; i < membersOrderList.size(); i++) {
                MembersOrder mb = membersOrderList.get(i);
                String period = mb.getPeriod();
                if (StringUtils.isBlank(period)) {
                    continue;
                }
                MembersOrderDto mbdto = new MembersOrderDto();
                String[] periods = mb.getPeriod().split("-");
                String startDay = null;
                String endDay = null;
                Integer time = null;
                if (OrderInquiryType.WEEK.getCode().equals(query.getType())) {
                    startDay = OrderDateUtils.getStartDayOfWeekNo(Integer.parseInt(periods[0]), Integer.parseInt(periods[1]));
                    endDay = OrderDateUtils.getEndDayOfWeekNo(Integer.parseInt(periods[0]), Integer.parseInt(periods[1]));
                    //获取今天是今年的第几周
                    time = OrderDateUtils.getTodayOfWeek();
                }
                Integer thisYear = OrderDateUtils.getThisYear();
                if (OrderInquiryType.MONTH.getCode().equals(query.getType())) {
                    startDay = OrderDateUtils.getFirstDayOfMonth(Integer.parseInt(periods[0]), Integer.parseInt(periods[1]));
                    endDay = OrderDateUtils.getLastDayOfMonth(Integer.parseInt(periods[0]), Integer.parseInt(periods[1]));
                    //获取今天是今年的第几个月
                    time = OrderDateUtils.getTodayOfMonth();
                }

                if (i == 0 && query.getStartTime() != null) {
                    startDay = OrderDateUtils.timeStampConversionToString(query.getStartTime());
                }
                //获取当前的年.周(年.月)小数
                double today = Double.parseDouble(thisYear + "." + time);

                if (i == (membersOrderList.size() - 1)) {
                    //查询到的最后一条数据年.周(年.月)小数
                    double date = Double.parseDouble(Integer.parseInt(periods[0]) + "." + Integer.parseInt(periods[1]));
                    if (date == today) {
                        endDay = OrderDateUtils.timeStampConversionToString(System.currentTimeMillis());
                    } else if (date < today) {
                        //获取最后一条数据,周末日期
                        Long end = OrderDateUtils.ConvertingStringsToTimestamps(endDay);
                        //查询的结束日期
                        Long endTime = query.getEndTime();
                        if (endTime != null && end > endTime) {
                            endDay = OrderDateUtils.timeStampConversionToString(query.getEndTime());
                        }
                    }
                }
                if (StringUtils.isNotBlank(startDay) && StringUtils.isNotBlank(endDay)) {
                    mbdto.setTimeSlot(startDay + "~" + endDay);
                } else {
                    mbdto.setTimeSlot("");
                }
                TotalPaymentAndMemberName(map, mb, mbdto);
                arrayList.add(mbdto);
            }
        }

        //进行分页处理

        return PageResult.nowPageResult(query.getPage(), query.getLimit(), arrayList);
    }


    private void TotalPaymentAndMemberName(HashMap<Integer, String> map, MembersOrder mb, MembersOrderDto mbdto) {
        BigDecimal totalPayment = BigDecimal.ZERO;
        List<Member> members = mb.getMembers();
        //设置时间段购买会员总金额和不同的会员名称
        if (CollectionUtil.isNotEmpty(members)) {
            mbdto.setMembers(members);
            for (Member member : members) {
                member.setMemberName(map.get(member.getLevel()));
                totalPayment = totalPayment.add(member.getAmount() == null ? BigDecimal.ZERO : member.getAmount());
            }
        }
        mbdto.setTotalPayment(totalPayment);
    }


    public List<HashMap<Object, Object>> getRows(List<MembersOrderDto> list, List<BaseUserMemberLevel> memberLevels) {
        ArrayList<HashMap<Object, Object>> rows = Lists.newArrayList();
        for (MembersOrderDto membersOrderDto : list) {
            if (CollectionUtils.isEmpty(membersOrderDto.getMembers())) {
                continue;
            }
            HashMap<Object, Object> map = Maps.newLinkedHashMap();
            map.put("时间", membersOrderDto.getTimeSlot());
            for (BaseUserMemberLevel memberLevel : memberLevels) {
                setMap(membersOrderDto, map, memberLevel);
            }
            map.put("总支付金额", membersOrderDto.getTotalPayment());
            rows.add(map);
        }


        return rows;
    }

    private void setMap(MembersOrderDto membersOrderDto, HashMap<Object, Object> map, BaseUserMemberLevel memberLevel) {

        List<Member> collect = membersOrderDto.getMembers().parallelStream().filter(el -> el.getLevel().equals(memberLevel.getLevel())).collect(Collectors.toList());
        int number = 0;
        BigDecimal amount = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(collect)) {
            number = collect.get(0).getNumber();
            amount = collect.get(0).getAmount();
        }
        map.put(memberLevel.getName() + "购买量", number);
        map.put("支付金额(" + memberLevel.getName() + ")", amount);
    }
}
