package org.jeecg.modules.adweb.dmp.vo.report;

import com.fasterxml.jackson.annotation.JsonIgnore;

import lombok.Data;

import org.apache.commons.collections4.CollectionUtils;
import org.jeecg.modules.adweb.common.util.DateUtil;
import org.jeecg.modules.adweb.common.util.NumberUtil;

import java.util.List;

/**
 * 网站综合统计数据VO, GA流量，询盘数据等
 *
 * @author wfansh
 */
@Data
public class SiteOverviewStatsVO {

    // 加和数据
    private int totalUsers; // 总访客数 UV

    private int sessions; // 总会话数

    private int pageViews; // 总浏览量 PV

    private int enquires; // 总询盘数

    private int unreadEnquires; // 未读询盘数

    // 计算数据
    private double dailyTotalUsers; // 日均访问量

    private String avgTimeOnPage; // 平均访问时长 - 如35.2秒，1分36秒

    private double pageViewsPerSession; // 平均访问页面数

    private String bounceRate; // 跳出率

    private String enquiryConversionRate; // UV到询盘转化率

    private List<DailyStatsVO> dailyStats;

    @Data
    public static class DailyStatsVO {

        private String date;

        private int totalUsers;

        @JsonIgnore private int sessions;

        @JsonIgnore private double bounceRate;

        @JsonIgnore private double avgSessionDuration;

        private int pageViews;

        @JsonIgnore private double pageViewsPerSession;

        private int enquires;

        @JsonIgnore private int unreadEnquires;
    }

    public static SiteOverviewStatsVO fromDailyStats(List<DailyStatsVO> dailyStatsVOs) {
        if (CollectionUtils.isEmpty(dailyStatsVOs)) {
            return null;
        }

        SiteOverviewStatsVO siteOverviewStatsVO = new SiteOverviewStatsVO();
        // 1. 加和数据
        int totalUsers = dailyStatsVOs.stream().mapToInt(DailyStatsVO::getTotalUsers).sum();
        int sessions = dailyStatsVOs.stream().mapToInt(DailyStatsVO::getSessions).sum();
        int pageViews = dailyStatsVOs.stream().mapToInt(DailyStatsVO::getPageViews).sum();
        int enquires = dailyStatsVOs.stream().mapToInt(DailyStatsVO::getEnquires).sum();
        int unreadEnquires = dailyStatsVOs.stream().mapToInt(DailyStatsVO::getUnreadEnquires).sum();

        siteOverviewStatsVO.setTotalUsers(totalUsers);
        siteOverviewStatsVO.setSessions(sessions);
        siteOverviewStatsVO.setPageViews(pageViews);
        siteOverviewStatsVO.setEnquires(enquires);
        siteOverviewStatsVO.setUnreadEnquires(unreadEnquires);

        // 2. 计算数据
        int numDays = dailyStatsVOs.size();

        // 2.1 日均访问量
        siteOverviewStatsVO.setDailyTotalUsers(
                NumberUtil.formatDecimal(NumberUtil.safeDivide(totalUsers, numDays), 2)
                        .doubleValue());

        // 2.2 平均访问时长
        // -- SUM (avgSessionDuration * sessions)
        double sessionDurationSum =
                dailyStatsVOs.stream()
                        .mapToDouble(
                                dailyStatsVO ->
                                        dailyStatsVO.getAvgSessionDuration()
                                                * dailyStatsVO.getSessions())
                        .sum();
        siteOverviewStatsVO.setAvgTimeOnPage(
                DateUtil.formatDuration(NumberUtil.safeDivide(sessionDurationSum, sessions)));

        // 2.3 平均访问页面数
        siteOverviewStatsVO.setPageViewsPerSession(
                NumberUtil.formatDecimal(NumberUtil.safeDivide(pageViews, sessions), 2)
                        .doubleValue());

        // 2.4 跳出率
        // -- SUM (bounceRate * * sessions)
        double bounceSum =
                dailyStatsVOs.stream()
                        .mapToDouble(
                                dailyStatsVO ->
                                        dailyStatsVO.getBounceRate() * dailyStatsVO.getSessions())
                        .sum();
        siteOverviewStatsVO.setBounceRate(
                NumberUtil.formatPercentage(NumberUtil.safeDivide(bounceSum, sessions), 2));

        // 2.5 UV到询盘转化率
        siteOverviewStatsVO.setEnquiryConversionRate(
                NumberUtil.formatPercentage(NumberUtil.safeDivide(enquires, totalUsers), 2));

        siteOverviewStatsVO.setDailyStats(dailyStatsVOs);

        return siteOverviewStatsVO;
    }
}
