package com.wecloud.im.appmanager;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.entity.ImConversation;
import com.wecloud.im.entity.ImMessage;
import com.wecloud.im.entity.ImStatistics;
import com.wecloud.im.sdk.enums.ChatTypeEnum;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.service.ImMessageService;
import com.wecloud.im.service.ImStatisticsService;
import com.wecloud.imserver.client.api.ImOverview;
import com.wecloud.imserver.client.model.vo.LineChart;
import com.wecloud.imserver.client.model.vo.OverviewVo;
import com.wecloud.imserver.client.model.vo.StatisticsVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@DubboService
public class ImOverviewImpl implements ImOverview {

    @Autowired
    private ImMessageService imMessageService;
    @Autowired
    private ImClientService imClientService;
    @Autowired
    private ImConversationService imConversationService;
    @Autowired
    private ImStatisticsService imStatisticsService;

    @Override
    public OverviewVo overview(Long appId) {
        OverviewVo overviewVo = new OverviewVo();
        //今日活跃用户
        Integer activeUser = imMessageService.count(new LambdaQueryWrapper<ImMessage>()
                .eq(ImMessage::getFkAppid, appId)
                .ge(ImMessage::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN))
                .groupBy(ImMessage::getSender)
                .select(ImMessage::getSender)
        );
        overviewVo.setActiveUser(activeUser);
        //总注册用户数
        Integer registerUser = imClientService.count(new LambdaQueryWrapper<ImClient>()
                .eq(ImClient::getFkAppid,appId)
        );
        overviewVo.setRegisterUser(registerUser);
        //七天内活跃群组数
        List<Long> ids = imMessageService.list(new LambdaQueryWrapper<ImMessage>()
                .ge(ImMessage::getCreateTime, LocalDateTime.now().minusDays(7))
                .le(ImMessage::getCreateTime, LocalDateTime.now())
                .groupBy(ImMessage::getFkConversationId)
                .select(ImMessage::getFkConversationId)
        ).stream().map(ImMessage::getFkConversationId).collect(Collectors.toList());

        Integer activeGroup = imConversationService.count(new LambdaQueryWrapper<ImConversation>()
                .eq(ImConversation::getFkAppid, appId)
                .eq(ImConversation::getChatType, ChatTypeEnum.NORMAL_GROUP.getCode())
                .eq(ImConversation::getChatType, ChatTypeEnum.THOUSAND_GROUP.getCode())
                .in(ImConversation::getId, ids)
        );
        overviewVo.setActiveGroup(activeGroup);
        //总群组数
        Integer group = imConversationService.count(new LambdaQueryWrapper<ImConversation>()
                .eq(ImConversation::getFkAppid,appId)
                .eq(ImConversation::getChatType, ChatTypeEnum.NORMAL_GROUP.getCode())
                .eq(ImConversation::getChatType, ChatTypeEnum.THOUSAND_GROUP.getCode())
        );
        overviewVo.setGroup(group);

        return overviewVo;
    }

    @Override
    public StatisticsVo groupStatistics(Long appId, LocalDateTime start, LocalDateTime end) {
        if(start == null && end ==null){
            start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN.minusHours(24 * 8));
            end = start.plusDays(7);
        }

        StatisticsVo statisticsVo = new StatisticsVo();
        //活跃群组数（前1天）
        ImStatistics statistics = imStatisticsService.getOne(new LambdaQueryWrapper<ImStatistics>()
                .eq(ImStatistics::getFkAppid, appId)
                .eq(ImStatistics::getType, 2)
                .between(ImStatistics::getTime,
                        LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(1),
                        LocalDateTime.of(LocalDate.now(), LocalTime.MAX).minusDays(1))
        );
        Integer activeGroup = statistics == null ? 0 : statistics.getData();
        statisticsVo.setActiveGroup(activeGroup);

        //新增群组数（前1天）
        Integer newGroup = imConversationService.count(new LambdaQueryWrapper<ImConversation>()
                .eq(ImConversation::getFkAppid, appId)
                .eq(ImConversation::getChatType, ChatTypeEnum.NORMAL_GROUP.getCode())
                .eq(ImConversation::getChatType, ChatTypeEnum.THOUSAND_GROUP.getCode())
                .between(ImConversation::getCreateTime,
                        LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(1),
                        LocalDateTime.of(LocalDate.now(), LocalTime.MAX).minusDays(1))
        );
        statisticsVo.setNewGroup(newGroup);

        //todo 解散群组数，暂时未能查询
        statisticsVo.setDismissGroup(0);

        //活跃群组平均成员数
        Integer avgMember = statistics == null ? 0 : statistics.getGroupMember()/statistics.getData();
        statisticsVo.setAvgActiveGroup(avgMember);

        //活跃群组折线图
        List<ImStatistics> imStatistics = imStatisticsService.activeUserOrGroup(appId, 2, start, end);
        List<LineChart> activeGroupLine = new ArrayList<>();
        for (ImStatistics imStatistic : imStatistics) {
            LineChart lineChart = new LineChart();
            lineChart.setCount(imStatistic.getData());
            lineChart.setDate(imStatistic.getTime());
            activeGroupLine.add(lineChart);
        }
        statisticsVo.setActiveGroupLine(activeGroupLine);

        //新增群组折线图
        Long days = ChronoUnit.DAYS.between(start, end);
        List<LineChart> newGroupLine = new ArrayList<>();
        for (int i = days.intValue();i>0;i--){
            LineChart lineChart = new LineChart();
            Integer count = imConversationService.count(new LambdaQueryWrapper<ImConversation>()
                    .eq(ImConversation::getFkAppid, appId)
                    .eq(ImConversation::getChatType, ChatTypeEnum.NORMAL_GROUP.getCode())
                    .eq(ImConversation::getChatType, ChatTypeEnum.THOUSAND_GROUP.getCode())
                    .between(ImConversation::getCreateTime, LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(i), LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(i - 1))
            );
            lineChart.setDate(LocalDateTime.of(LocalDate.now(), LocalTime.MIN).minusDays(i));
            lineChart.setCount(count);
            newGroupLine.add(lineChart);
        }
        statisticsVo.setNewGroupLine(newGroupLine);

        //todo 解散群组折线图
        List<LineChart> dismissGroupLine = new ArrayList<>();
        statisticsVo.setDismissGroupLine(dismissGroupLine);

        //活跃群组平均成员数
        List<LineChart> avgActiveGroupLine = new ArrayList<>();
        for (ImStatistics imStatistic : imStatistics) {
            LineChart lineChart = new LineChart();
            lineChart.setCount(imStatistic.getGroupMember()/imStatistic.getData());
            lineChart.setDate(imStatistic.getTime());
            avgActiveGroupLine.add(lineChart);
        }
        statisticsVo.setAvgActiveGroupLine(avgActiveGroupLine);

        return statisticsVo;
    }

    @Override
    public List<LineChart> activeUser(Long appId, LocalDateTime start, LocalDateTime end) {
        if(start == null && end ==null){
            start = LocalDateTime.of(LocalDate.now(), LocalTime.MIN.minusHours(24 * 8));
            end = start.plusDays(7);
        }
        //活跃用户数
        List<ImStatistics> imStatistics = imStatisticsService.activeUserOrGroup(appId, 1, start, end);
        List<LineChart> activeUser = new ArrayList<>();
        for (ImStatistics imStatistic : imStatistics) {
            LineChart lineChart = new LineChart();
            lineChart.setCount(imStatistic.getData());
            lineChart.setDate(imStatistic.getTime());
            activeUser.add(lineChart);
        }
        return activeUser;
    }
}
