package com.slodon.b2b2c.controller.statistics.admin;

import com.slodon.b2b2c.core.constant.MemberConst;
import com.slodon.b2b2c.core.controller.BaseController;
import com.slodon.b2b2c.core.response.JsonResult;
import com.slodon.b2b2c.core.response.PageVO;
import com.slodon.b2b2c.core.response.PagerInfo;
import com.slodon.b2b2c.core.response.SldResponse;
import com.slodon.b2b2c.core.util.StringUtil;
import com.slodon.b2b2c.core.util.WebUtil;
import com.slodon.b2b2c.enums.ProvinceJson;
import com.slodon.b2b2c.enums.StatsConstant;
import com.slodon.b2b2c.enums.StatsTimeType;
import com.slodon.b2b2c.enums.TerminalJson;
import com.slodon.b2b2c.member.example.MemberExample;
import com.slodon.b2b2c.member.pojo.Member;
import com.slodon.b2b2c.model.member.MemberModel;
import com.slodon.b2b2c.model.statistics.MemberDayModel;
import com.slodon.b2b2c.model.statistics.PlatformDayModel;
import com.slodon.b2b2c.model.statistics.ProvinceDayModel;
import com.slodon.b2b2c.statistics.example.MemberDayExample;
import com.slodon.b2b2c.statistics.example.PlatformDayExample;
import com.slodon.b2b2c.statistics.example.ProvinceDayExample;
import com.slodon.b2b2c.statistics.pojo.PlatformDay;
import com.slodon.b2b2c.statistics.pojo.base.*;
import com.slodon.b2b2c.util.StatsModelUtil;
import com.slodon.b2b2c.vo.statistics.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;

@Api(tags = "admin-会员分析")
@RestController
@RequestMapping("v3/statistics/admin/member/analysis")
public class AdminMemberAnalysisController extends BaseController {

    @Resource
    private MemberDayModel memberDayModel;
    @Resource
    private PlatformDayModel platformDayModel;
    @Resource
    private ProvinceDayModel provinceDayModel;
    @Resource
    private StatsModelUtil statsModelUtil;
    @Resource
    private MemberModel memberModel;
    @Resource
    private MongoTemplate mongoTemplate;

    @ApiOperation("会员总览(会员总数)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "terminalType", value = "终端类型：Android,IOS,pc,H5,xcx 默认全部不传")
    })
    @GetMapping("memberNum")
    public JsonResult memberNum(HttpServletRequest request, String webSite,String terminalType) {
        MemberExample example = new MemberExample();
        if (!StringUtil.isEmpty(terminalType)) {
            example.setRegisterChannel(getMemberSource(terminalType));
        }
        example.setWebSite(webSite);
        Map<String, Integer> map = new HashMap<>();
        map.put("memberNum", memberModel.getMemberCount(example));
        return SldResponse.success(map);
    }

    @ApiOperation("会员总览")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "terminalType", value = "终端类型：Android,IOS,pc,H5,xcx 默认全部不传")
    })
    @GetMapping("goodsOverview")
    public JsonResult<MemberOverviewVO> goodsOverview(HttpServletRequest request,String webSite, Date startTime, Date endTime, String terminalType) {
        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, false);
        MemberOverviewVO vo = new MemberOverviewVO();
        //上期开始时间和结束时间
        Date preStartTime;
        Date preEndTime;
        int differentDay = StatsTimeType.getDifferentDay(startTime, endTime);
        if (timeType == StatsTimeType.DAY && differentDay != 1) {
            preStartTime = StatsTimeType.getPreStartTime(startTime, differentDay);
            preEndTime = StatsTimeType.getPreEndTime(endTime, differentDay);
        } else {
            preStartTime = StatsTimeType.getStartTime(startTime, timeType);
            preEndTime = StatsTimeType.getEndTime(endTime, timeType);
        }
        if (!StringUtil.isEmpty(terminalType)) {
            List<? extends TerminalBase> list = statsModelUtil.getTerminalList(timeType, startTime, endTime, terminalType);
            if (!CollectionUtils.isEmpty(list)) {
                TerminalBase terminalBase = list.get(0);
                //上期数据
                TerminalBase previousData = null;
                if (preStartTime != null) {
                    List<? extends TerminalBase> previousList = statsModelUtil.getTerminalList(timeType, preStartTime, preEndTime, terminalType);
                    if (!CollectionUtils.isEmpty(previousList)) {
                        previousData = previousList.get(0);
                    }
                }
                if (terminalBase != null) {
                    vo = new MemberOverviewVO(terminalBase, previousData);
                }
            }
        } else {
            List<? extends PlatformBase> list = statsModelUtil.getPlatformList(timeType,webSite, startTime, endTime);
            if (!CollectionUtils.isEmpty(list)) {
                PlatformBase platformBase = list.get(0);
                //上期数据
                PlatformBase previousData = null;
                if (preStartTime != null) {
                    List<? extends PlatformBase> previousList = statsModelUtil.getPlatformList(timeType, webSite, preStartTime, preEndTime);
                    if (!CollectionUtils.isEmpty(previousList)) {
                        previousData = previousList.get(0);
                    }
                }
                if (platformBase != null) {
                    vo = new MemberOverviewVO(platformBase, previousData);
                }
            }
        }
        return SldResponse.success(vo);
    }

    @ApiOperation("变化趋势")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true)
    })
    @GetMapping("changeTrend")
    public JsonResult<List<TerminalSalesVO>> changeTrend(HttpServletRequest request, Date startTime, Date endTime) {
        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, true);
        List<SalesTrendVO> list = statsModelUtil.getTerminalTrendList(timeType, startTime, endTime);
        List<TerminalSalesVO> vos = getTerminalChangeTrend(list);
        return SldResponse.success(vos);
    }

    @ApiOperation("会员偏好商品排行-TOP10")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "sort", value = "排序:1-浏览量；2-收藏数；3-支付订单数 默认不传按浏览量降序")
    })
    @GetMapping("preferGoodsRank")
    public JsonResult<List<GoodsRankVO>> preferGoodsRank(HttpServletRequest request, Date startTime, Date endTime,@RequestParam(name = "webSite", required = false,defaultValue = "1") String webSite, Integer sort) {
        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, false);
        List<? extends GoodsBase> list = statsModelUtil.getGoodsList(timeType, startTime, endTime,webSite, sort, "prefer", null);
        List<GoodsRankVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(goodsBase -> {
                //浏览量、收藏数和订单数三者必须有一个满足条件
                if (goodsBase.getViewNum() > 0 || goodsBase.getCollectionNum() > 0 || goodsBase.getOrderPayNum() > 0) {
                    vos.add(new GoodsRankVO(goodsBase.getGoodsId(), goodsBase.getGoodsName(), goodsBase.getGoodsImage(),
                            goodsBase.getViewNum(), goodsBase.getCollectionNum(), goodsBase.getOrderPayNum()));
                }
            });
        }
        return SldResponse.success(vos);
    }

    @ApiOperation("各终端会员占比")
    @GetMapping("memberPercent")
    public JsonResult<List<MemberPercentVO>> memberPercent(HttpServletRequest request) {
        MemberExample example = new MemberExample();
        List<Member> list = memberModel.getMemberList(example, null);
        List<MemberPercentVO> vos = getTerminalMemberPercent(list);
        return SldResponse.success(vos);
    }

    @ApiOperation("下单会员地域分布占比")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
    })
    @GetMapping("memberRegionPercent")
    public JsonResult<List<ProvincePercentVO>> memberRegionPercent(HttpServletRequest request, Date startTime, Date endTime) {
        StatsTimeType timeType = StatsTimeType.checkTimeType(startTime, endTime, false);
        List<? extends ProvinceBase> list;
        if (timeType.equals(StatsTimeType.DAY)) {
            ProvinceDayExample example = new ProvinceDayExample();
            example.setStatsTimeAfter(startTime);
            example.setStatsTimeBefore(endTime);
            example.setOrderBy("orderSubmitMemberNum DESC");
            list = provinceDayModel.getProvincePercentList(example);
        } else {
            list = statsModelUtil.getProvinceList(timeType, startTime, endTime, 3);
        }
        List<ProvincePercentVO> vos = getMemberRegionPercent(list);
        return SldResponse.success(vos);
    }

    @ApiOperation("地域分布")
    @GetMapping("regionDistribution")
    public JsonResult<List<ProvincePercentVO>> regionDistribution(HttpServletRequest request) {
        //查询行为类型是会员注册的
        Criteria criteria = Criteria.where("behaviorType").is(StatsConstant.MEMBER_REGISTER);
        // first("") 分组后，如果某属性(非分组属性)出现多个值 ,取第一个
        Aggregation aggregation = Aggregation.newAggregation(Aggregation.match(criteria),
                Aggregation.group("provinceCode").first("provinceCode").as("provinceCode").count().as("memberNum"));
        AggregationResults<ProvincePercentVO> results = mongoTemplate.aggregate(aggregation, "stats_member_behavior", ProvincePercentVO.class);
        List<ProvincePercentVO> list = getRegionDistributionPercent(results.getMappedResults());
        return SldResponse.success(list);
    }

    @ApiOperation("会员报表(按天)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:stats_time-时间;new_member_num-新增会员数;recharge_member_num-储值会员数;" +
                    "order_submit_member_num-下单人数;order_pay_member_num-支付人数;默认按时间降序排序"),
            @ApiImplicitParam(name = "pageSize", value = "分页大小", defaultValue = "20", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面位置", defaultValue = "1", paramType = "query")
    })
    @GetMapping("dayReport")
    public JsonResult<PageVO<PlatformMemberReportVO>> dayReport(HttpServletRequest request, Date startTime, Date endTime,
                                                                @RequestParam(value = "webSite", required = false, defaultValue = "1") String webSite,
                                                                @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                                                @RequestParam(value = "sort", required = false, defaultValue = "stats_time") String sort) {
        PagerInfo pager = WebUtil.handlerPagerInfo(request);
        PlatformDayExample example = new PlatformDayExample();
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setWebSite(webSite);
        example.setOrderBy(sort + " " + type);
        List<PlatformDay> list = platformDayModel.getPlatformDayList(example, pager);
        List<PlatformMemberReportVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(platformDay -> {
                vos.add(new PlatformMemberReportVO(platformDay));
            });
        }
        return SldResponse.success(new PageVO<>(vos, pager));
    }

    @ApiOperation("会员报表(按会员)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "memberName", value = "会员名称"),
            @ApiImplicitParam(name = "registerStartTime", value = "注册开始时间"),
            @ApiImplicitParam(name = "registerEndTime", value = "注册结束时间"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:registerTime-注册时间;rechargeAmount-累计充值金额;orderSubmitNum-下单数;" +
                    "orderSubmitAmount-下单金额;orderPayNum-支付订单数;orderPayAmount-支付金额;returnNum-退单数;returnAmount-退款金额;默认按注册时间降序排序"),
            @ApiImplicitParam(name = "pageSize", value = "分页大小", defaultValue = "20", paramType = "query"),
            @ApiImplicitParam(name = "current", value = "当前页面位置", defaultValue = "1", paramType = "query")
    })
    @GetMapping("memberReport")
    public JsonResult<PageVO<MemberReportVO>> memberReport(HttpServletRequest request, Date startTime, Date endTime, String memberName,
                                                           Date registerStartTime, Date registerEndTime,
                                                           @RequestParam(value = "webSite", required = false, defaultValue = "1") String webSite,
                                                           @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                                           @RequestParam(value = "sort", required = false, defaultValue = "registerTime") String sort) {
        PagerInfo pager = WebUtil.handlerPagerInfo(request);
        MemberDayExample example = new MemberDayExample();
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setMemberNameLike(memberName);
        example.setRegisterTimeAfter(registerStartTime);
        example.setRegisterTimeBefore(registerEndTime);
        example.setWebSite(webSite);
        example.setOrderBy(sort + " " + type);
        List<MemberBase> list = memberDayModel.getMemberList(example, pager);
        List<MemberReportVO> vos = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            list.forEach(memberBase -> {
                vos.add(new MemberReportVO(memberBase));
            });
        }
        return SldResponse.success(new PageVO<>(vos, pager));
    }

    @ApiOperation("导出报表(按天)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:stats_time-时间;new_member_num-新增会员数;recharge_member_num-储值会员数;" +
                    "order_submit_member_num-下单人数;order_pay_member_num-支付人数;默认按时间降序排序")
    })
    @GetMapping("dayExport")
    public JsonResult dayExport(HttpServletRequest request, HttpServletResponse response, Date startTime, Date endTime,
                                @RequestParam(value = "webSite", required = false, defaultValue = "1") String webSite,
                                @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                @RequestParam(value = "sort", required = false, defaultValue = "stats_time") String sort) {
        PlatformDayExample example = new PlatformDayExample();
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setWebSite(webSite);
        example.setOrderBy(sort + " " + type);
        platformDayModel.memberReportExport(request, response, example);
        return null;
    }

    @ApiOperation("导出报表(按会员)")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "startTime", value = "开始时间", required = true),
            @ApiImplicitParam(name = "endTime", value = "结束时间", required = true),
            @ApiImplicitParam(name = "webSite", value = "站点"),
            @ApiImplicitParam(name = "memberName", value = "会员名称"),
            @ApiImplicitParam(name = "registerStartTime", value = "注册开始时间"),
            @ApiImplicitParam(name = "registerEndTime", value = "注册结束时间"),
            @ApiImplicitParam(name = "type", value = "排序类型；desc-降序;asc-升序;默认类型为降序"),
            @ApiImplicitParam(name = "sort", value = "排序:registerTime-注册时间;rechargeAmount-累计充值金额;orderSubmitNum-下单数;" +
                    "orderSubmitAmount-下单金额;orderPayNum-支付订单数;orderPayAmount-支付金额;returnNum-退单数;returnAmount-退款金额;默认按注册时间降序排序")
    })
    @GetMapping("memberExport")
    public JsonResult memberExport(HttpServletRequest request, HttpServletResponse response, Date startTime, Date endTime, String memberName,
                                   Date registerStartTime, Date registerEndTime,
                                   @RequestParam(value = "webSite", required = false, defaultValue = "1") String webSite,
                                   @RequestParam(value = "type", required = false, defaultValue = "desc") String type,
                                   @RequestParam(value = "sort", required = false, defaultValue = "registerTime") String sort) {
        MemberDayExample example = new MemberDayExample();
        example.setStatsTimeAfter(startTime);
        example.setStatsTimeBefore(endTime);
        example.setMemberNameLike(memberName);
        example.setRegisterTimeAfter(registerStartTime);
        example.setRegisterTimeBefore(registerEndTime);
        example.setWebSite(webSite);
        example.setOrderBy(sort + " " + type);
        memberDayModel.memberReportExport(request, response, example);
        return null;
    }

    /**
     * 地域分布
     *
     * @param list
     * @return
     */
    public List<ProvincePercentVO> getRegionDistributionPercent(List<ProvincePercentVO> list) {
        List<ProvincePercentVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            //查询总会员数，用于计算各省份占比
            Integer totalNum = memberModel.getMemberCount(new MemberExample());
            //如果为0直接返回空数组
            if (totalNum == 0) {
                return result;
            }
            //省份大于10，记录前10个，剩余记为其他
            //其他省份会员
            int otherNum = totalNum;
            //其他省份占比
            BigDecimal otherPer = new BigDecimal(100);
            //循环列表,构造返回数据
            if (list.size() <= 10) {
                //省份少于等于10个，直接记录各省份的会员占比
                for (ProvincePercentVO provincePercentVO : list) {
                    //如果编码为空，按未知处理
                    if (!StringUtil.isEmpty(provincePercentVO.getProvinceCode())) {
                        String provinceName = ProvinceJson.provinceMap.get(provincePercentVO.getProvinceCode());

                        Integer memberNum = provincePercentVO.getMemberNum();
                        //如果为空，按未知处理
                        if (!StringUtil.isEmpty(provinceName) && memberNum > 0) {
                            ProvincePercentVO vo = new ProvincePercentVO();
                            vo.setProvinceName(provinceName);
                            vo.setMemberNum(memberNum);
                            BigDecimal numPer = new BigDecimal(memberNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                            vo.setMemberNumPercent(numPer.toString() + "%");
                            result.add(vo);

                            //数据计算
                            otherNum = otherNum - memberNum;
                            otherPer = otherPer.subtract(numPer);
                        }
                    }
                }
                //如果大于0说明，会员行为表数据有遗漏，按其他处理
                if (otherNum > 0) {
                    //其他
                    ProvincePercentVO vo = new ProvincePercentVO();
                    vo.setProvinceName(ProvinceJson.defaultProvinceName);
                    vo.setMemberNum(otherNum);
                    vo.setMemberNumPercent(otherPer.toString() + "%");
                    result.add(vo);
                }
            } else {
                for (int i = 0; i < list.size() && i < 10; i++) {
                    ProvincePercentVO provincePercentVO = list.get(i);
                    //如果编码为空，按其他处理
                    if (!StringUtil.isEmpty(provincePercentVO.getProvinceCode())) {
                        String provinceName = ProvinceJson.provinceMap.get(provincePercentVO.getProvinceCode());

                        Integer memberNum = provincePercentVO.getMemberNum();
                        //如果为空，按其他处理
                        if (!StringUtil.isEmpty(provinceName) && memberNum > 0) {
                            ProvincePercentVO vo = new ProvincePercentVO();
                            vo.setProvinceName(provinceName);
                            vo.setMemberNum(memberNum);
                            BigDecimal numPer = new BigDecimal(memberNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                            vo.setMemberNumPercent(numPer.toString() + "%");
                            result.add(vo);

                            //数据计算
                            otherNum = otherNum - memberNum;
                            otherPer = otherPer.subtract(numPer);
                        }
                    }
                }
                //其他
                if (otherNum > 0) {
                    ProvincePercentVO vo = new ProvincePercentVO();
                    vo.setProvinceName("其他");
                    vo.setMemberNum(otherNum);
                    vo.setMemberNumPercent(otherPer.toString() + "%");
                    result.add(vo);
                }
            }
        }
        return result;
    }

    /**
     * 下单会员地域分布占比
     *
     * @param list
     * @return
     */
    public List<ProvincePercentVO> getMemberRegionPercent(List<? extends ProvinceBase> list) {
        List<ProvincePercentVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            //总下单人数，用于计算各省份占比
            Integer totalNum = 0;
            for (ProvinceBase provinceBase : list) {
                totalNum += provinceBase.getOrderSubmitMemberNum();
            }
            if (totalNum == 0) {
                return result;
            }

            //循环列表,构造返回数据
            if (list.size() <= 10) {
                //省份少于等于10个，直接记录各省份的会员占比
                for (ProvinceBase provinceBase : list) {
                    ProvincePercentVO vo = new ProvincePercentVO();
                    vo.setProvinceName(provinceBase.getProvinceName());
                    vo.setMemberNum(provinceBase.getOrderSubmitMemberNum());
                    BigDecimal numPer = new BigDecimal(provinceBase.getOrderSubmitMemberNum()).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                    vo.setMemberNumPercent(numPer.toString() + "%");
                    result.add(vo);
                }
            } else {
                //省份大于10，记录前10个，剩余记为其他
                //其他省份会员
                int otherNum = totalNum;
                //其他省份占比
                BigDecimal otherPer = new BigDecimal(100);
                for (int i = 0; i < list.size() && i < 10; i++) {
                    ProvinceBase provinceBase = list.get(i);

                    Integer memberNum = provinceBase.getOrderSubmitMemberNum();

                    ProvincePercentVO vo = new ProvincePercentVO();
                    vo.setProvinceName(provinceBase.getProvinceName());
                    vo.setMemberNum(memberNum);
                    BigDecimal numPer = new BigDecimal(memberNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                    vo.setMemberNumPercent(numPer.toString() + "%");
                    result.add(vo);

                    //数据计算
                    otherNum = otherNum - memberNum;
                    otherPer = otherPer.subtract(numPer);
                }
                //其他
                ProvincePercentVO vo = new ProvincePercentVO();
                vo.setProvinceName("其他");
                vo.setMemberNum(otherNum);
                vo.setMemberNumPercent(otherPer.toString() + "%");
                result.add(vo);
            }
        }
        return result;
    }

    /**
     * 各终端会员占比
     *
     * @param list
     * @return
     */
    public List<MemberPercentVO> getTerminalMemberPercent(List<Member> list) {
        List<MemberPercentVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            //会员总数，用于计算各终端占比
            int totalNum = list.size();
            //key为终端名称，value为人数
            Map<String, Integer> map = new HashMap<>();
            for (Member member : list) {
                String terminalName = TerminalJson.terminalNameMap.get(member.getRegisterChannel());
                if (map.containsKey(terminalName)) {
                    map.put(terminalName, map.get(terminalName) + 1);
                } else {
                    //第一次进来默认1
                    map.put(terminalName, 1);
                }
            }
            for (Map.Entry<String, Integer> entry : map.entrySet()) {
                int memberNum = entry.getValue();
                MemberPercentVO vo = new MemberPercentVO();
                vo.setTerminalName(entry.getKey());
                vo.setMemberNum(memberNum);
                BigDecimal per = new BigDecimal(memberNum).multiply(new BigDecimal(100)).divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
                vo.setMemberNumPercent(per.toString() + "%");
                result.add(vo);
            }
            //补齐没有数据的终端
            Map<String, Integer> differentMap = getDifferentMap(map, TerminalJson.terminalNameMap);
            if (differentMap.size() > 0) {
                differentMap.forEach((name, num) -> {
                    MemberPercentVO vo = new MemberPercentVO();
                    vo.setTerminalName(name);
                    vo.setMemberNum(0);
                    vo.setMemberNumPercent(0 + "%");
                    result.add(vo);
                });
            }
        }
        return result;
    }

    /**
     * 获取terminalNameMap中有的数据，且该数据在target中未存在
     *
     * @param target          比较目标
     * @param terminalNameMap 需要比较的数据
     * @return terminalNameMap中比target多出的数据。
     */
    public Map<String, Integer> getDifferentMap(Map<String, Integer> target, Map<Integer, String> terminalNameMap) {
        Map<String, Integer> map = new HashMap<>();
        for (Map.Entry<Integer, String> entry : terminalNameMap.entrySet()) {
            String value = entry.getValue();
            //如果没有则存放到map
            if (!target.containsKey(value)) {
                map.put(value, 0);
            }
        }
        return map;
    }

    /**
     * 变化趋势
     *
     * @param list
     * @return
     */
    public List<TerminalSalesVO> getTerminalChangeTrend(List<SalesTrendVO> list) {
        List<TerminalSalesVO> result = new ArrayList<>();
        if (!CollectionUtils.isEmpty(list)) {
            //按照统计时间分组
            Map<String, List<TerminalSalesVO.TerminalVO>> timeMap = new HashMap<>();
            for (SalesTrendVO salesTrendVO : list) {
                TerminalSalesVO.TerminalVO terminalVO = new TerminalSalesVO.TerminalVO();
                if("pc".equals(salesTrendVO.getTerminalName())){
                    terminalVO.setTerminalName(salesTrendVO.getTerminalName());
                    terminalVO.setNewMemberNum(salesTrendVO.getNewMemberNum());
                    terminalVO.setRechargeMemberNum(salesTrendVO.getRechargeMemberNum());
                    terminalVO.setOrderSubmitMemberNum(salesTrendVO.getOrderSubmitMemberNum());
                    terminalVO.setOrderPayMemberNum(salesTrendVO.getOrderPayMemberNum());
                    //按照统计时间分组
                    if (timeMap.containsKey(salesTrendVO.getStatsTime())) {
                        timeMap.get(salesTrendVO.getStatsTime()).add(terminalVO);
                    } else {
                        //终端列表
                        List<TerminalSalesVO.TerminalVO> terminalList = new ArrayList<>();
                        terminalList.add(terminalVO);

                        timeMap.put(salesTrendVO.getStatsTime(), terminalList);
                    }
                }
            }
            timeMap.forEach((statsTime, terminalList) -> {
                TerminalSalesVO vo = new TerminalSalesVO();
                vo.setStatsTime(statsTime);
                vo.setTerminalList(terminalList);
                result.add(vo);
            });
            Collections.sort(result);
        }
        return result;
    }

    /**
     * 根据终端类型获取会员来源
     *
     * @param terminalType 终端类型：Android,IOS,pc,H5,xcx
     * @return
     */
    private Integer getMemberSource(String terminalType) {
        switch (terminalType) {
            case StatsConstant.TERMINAL_PC:
                return MemberConst.MEMBER_FROM_PC;
            case StatsConstant.TERMINAL_H5:
                return MemberConst.MEMBER_FROM_H5;
            case StatsConstant.TERMINAL_ANDROID:
                return MemberConst.MEMBER_FROM_Android;
            case StatsConstant.TERMINAL_IOS:
                return MemberConst.MEMBER_FROM_IOS;
            case StatsConstant.TERMINAL_WX_XCX:
                return MemberConst.MEMBER_FROM_WXMALL;
            case StatsConstant.TERMINAL_BD_XCX:
                return MemberConst.MEMBER_FROM_BDXCX;
            case StatsConstant.TERMINAL_ALI_XCX:
                return MemberConst.MEMBER_FROM_ALIXCX;
            case StatsConstant.TERMINAL_DY_XCX:
                return MemberConst.MEMBER_FROM_DYXCX;
            default:
                return MemberConst.MEMBER_FROM_PC;
        }
    }
}
