
package com.tmerclub.cloud.flow.service.impl;

import com.tmerclub.cloud.api.delivery.feign.AreaFeignClient;
import com.tmerclub.cloud.common.constant.Constant;
import com.tmerclub.cloud.common.order.vo.AreaVO;
import com.tmerclub.cloud.common.util.Arith;
import com.tmerclub.cloud.common.util.BeanUtil;
import com.tmerclub.cloud.flow.bo.FlowRegionalBO;
import com.tmerclub.cloud.flow.bo.FlowSystemBO;
import com.tmerclub.cloud.flow.bo.FlowUserFootprintBO;
import com.tmerclub.cloud.flow.constant.SystemTypeEnum;
import com.tmerclub.cloud.flow.dto.FlowAnalysisDTO;
import com.tmerclub.cloud.flow.service.SystemAnalyseMongoService;
import com.tmerclub.cloud.flow.service.UserAnalyseMongoService;
import com.tmerclub.cloud.flow.service.UserVisitAnalysisService;
import com.tmerclub.cloud.flow.util.FlowUtil;
import com.tmerclub.cloud.flow.vo.FlowUserAnalysisVO;
import com.tmerclub.cloud.flow.vo.UserAnalysisDataExcelVO;
import com.tmerclub.cloud.flow.vo.UserAnalysisVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 流量分析—用户访问数据
 *
 * @author YXF
 * @date 2021-05-21 15:25:19
 */
@Service
public class UserVisitAnalysisServiceImpl implements UserVisitAnalysisService {

    @DubboReference
    private AreaFeignClient areaFeignClient;
    @Autowired
    private UserAnalyseMongoService userAnalyseMongoService;
    @Autowired
    private SystemAnalyseMongoService systemAnalyseMongoService;

    @Override
    public FlowUserAnalysisVO getUserAnalysisData(FlowAnalysisDTO flowAnalysisDTO) {
        FlowUtil.handleTime(flowAnalysisDTO);
        // 访问深度
        List<FlowUserFootprintBO> flowUserFootprintList = userAnalyseMongoService.listUserFootprint(flowAnalysisDTO.getStartTime(), flowAnalysisDTO.getEndTime(), flowAnalysisDTO.getDateType());
        // 访问地域
        List<FlowRegionalBO> flowRegionalList = userAnalyseMongoService.listFlowRegional(flowAnalysisDTO.getStartTime(), flowAnalysisDTO.getEndTime(), flowAnalysisDTO.getDateType());
        // 系统设备
        List<FlowSystemBO> flowSystemList = systemAnalyseMongoService.listFlowSystem(flowAnalysisDTO.getStartTime(), flowAnalysisDTO.getEndTime(), flowAnalysisDTO.getDateType());
        // 拼接数据
        FlowUserAnalysisVO flowUserAnalysisVO = new FlowUserAnalysisVO();

        // 处理访问深度的数据
        flowUserAnalysisVO.setVisitPageList(this.getVisitPageList(flowUserFootprintList));

        // 处理访问地域分布的数据
        List<AreaVO> areaList = areaFeignClient.listProvinceArea();
        Map<Long, String> areaMap = areaList.stream().collect(Collectors.toMap(AreaVO::getAreaId, AreaVO::getAreaName));
        flowUserAnalysisVO.setVisitUserList(this.getUserAccessData(flowRegionalList, areaMap));
        flowSystemList.forEach(flowSystemBO -> {
            if(Objects.isNull(flowSystemBO.getVisitUser())){
                flowSystemBO.setVisitUser(0);
            }
        });
        Map<Integer, Integer> flowSystemMap = flowSystemList.stream().collect(Collectors.toMap(FlowSystemBO::getSystemType, FlowSystemBO::getVisitUser));
        // 系统设备访问情况
        for (SystemTypeEnum systemTypeEnum : SystemTypeEnum.values()) {
            Integer visitUser = flowSystemMap.getOrDefault(systemTypeEnum.value(), 0);

            switch (Objects.requireNonNull(SystemTypeEnum.instance(systemTypeEnum.value()))) {
                case H5:
                    flowUserAnalysisVO.setH5(visitUser);
                    break;
                case PC:
                    flowUserAnalysisVO.setPc(visitUser);
                    break;
                case IOS:
                    flowUserAnalysisVO.setIos(visitUser);
                    break;
                case ANDROID:
                    flowUserAnalysisVO.setAndroid(visitUser);
                    break;
                case APPLETS:
                    flowUserAnalysisVO.setApplets(visitUser);
                    break;
                default:
                    break;
            }
        }
        return flowUserAnalysisVO;
    }

    @Override
    public List<UserAnalysisDataExcelVO> listUserAnalysisDataExcel(FlowAnalysisDTO flowAnalysisDTO) {
        FlowUserAnalysisVO userAnalysisData = getUserAnalysisData(flowAnalysisDTO);
        List<UserAnalysisVO> visitUserList = userAnalysisData.getVisitUserList();
        List<UserAnalysisDataExcelVO> userAnalysisDataExcelList = BeanUtil.mapAsList(visitUserList, UserAnalysisDataExcelVO.class);
        for (UserAnalysisDataExcelVO userAnalysisVO : userAnalysisDataExcelList) {
            if (Objects.isNull(userAnalysisVO.getPlusShopCart())) {
                userAnalysisVO.setPlusShopCart(0L);
            }
            if (Objects.isNull(userAnalysisVO.getVisitNums())) {
                userAnalysisVO.setVisitNums(0);
            }
            if (Objects.isNull(userAnalysisVO.getClickNums())) {
                userAnalysisVO.setClickNums(0);
            }
            if (Objects.isNull(userAnalysisVO.getProdVisitUser())) {
                userAnalysisVO.setProdVisitUser(0);
            }
            if (Objects.isNull(userAnalysisVO.getProdVisitNums())) {
                userAnalysisVO.setProdVisitNums(0);
            }
            if (Objects.isNull(userAnalysisVO.getPayAmount())) {
                userAnalysisVO.setPayAmount(0D);
            }
            if (Objects.isNull(userAnalysisVO.getPlaceOrderAmount())) {
                userAnalysisVO.setPlaceOrderAmount(0D);
            }
            userAnalysisVO.setPayAmount(Arith.div(userAnalysisVO.getPayAmount(), 100, 2));
            userAnalysisVO.setPlaceOrderAmount(Arith.div(userAnalysisVO.getPlaceOrderAmount(), 100, 2));
        }
        return userAnalysisDataExcelList;
    }

    /**
     * 获取访问深度数据
     * @param flowUserFootprintList
     * @return
     */
    private List<FlowUserAnalysisVO.VisitNum> getVisitPageList(List<FlowUserFootprintBO> flowUserFootprintList) {
        // 访问深度Map
        Map<Integer, Integer> map = flowUserFootprintList.stream()
                .collect(Collectors.toMap(FlowUserFootprintBO::getVisitId, FlowUserFootprintBO::getUserNums));

        List<FlowUserAnalysisVO.VisitNum> visitNumList = new ArrayList<>();
        for (int i = 1; i <= Constant.EIGHT; i++) {
            FlowUserAnalysisVO.VisitNum visitNum;
            visitNum = new FlowUserAnalysisVO.VisitNum(i, map.getOrDefault(i, 0));
            visitNumList.add(visitNum);
        }
        return visitNumList;
    }

    /**
     * 获取访问地域分布数据
     * @param flowRegionalList
     * @param areaMap
     * @return
     */
    private List<UserAnalysisVO> getUserAccessData(List<FlowRegionalBO> flowRegionalList, Map<Long, String> areaMap) {
        List<UserAnalysisVO> userAnalysisList = new ArrayList<>();
        for (FlowRegionalBO flowRegionalBO : flowRegionalList) {
            UserAnalysisVO userAnalysisVO = new UserAnalysisVO();
            // 省名称
            if (Objects.nonNull(flowRegionalBO.getProvinceId())) {
                userAnalysisVO.setProvinceName(areaMap.getOrDefault(flowRegionalBO.getProvinceId().longValue(), "未知"));
            }
            // 浏览量、浏览用户
            userAnalysisVO.setVisitNums(flowRegionalBO.getVisitNum());
            userAnalysisVO.setVisitUserNum(flowRegionalBO.getVisitUserNum());
            //  商品访客数、商品浏览量
            userAnalysisVO.setProdVisitNums(flowRegionalBO.getSpuVisitNum());
            userAnalysisVO.setProdVisitUser(flowRegionalBO.getSpuVisitUserNum());
            // 加购数量
            userAnalysisVO.setPlusShopCart(flowRegionalBO.getPlusShopCartNum());
            // 下单金额、支付金额
            userAnalysisVO.setPlaceOrderAmount(flowRegionalBO.getPlaceOrderAmount());
            userAnalysisVO.setPayAmount(flowRegionalBO.getPayAmount());
            userAnalysisList.add(userAnalysisVO);
        }
        return userAnalysisList;
    }
}
