package com.skr.mdm.api.statistics.service.impl;


import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.skr.mdm.api.statistics.service.StatisticsService;
import com.skr.mdm.bean.vo.statistics.*;
import com.skr.mdm.constant.SendCmdTypeConstants;
import com.skr.mdm.dao.*;
import com.skr.mdm.dto.LoginAdminDTO;
import com.skr.mdm.entity.ClientUpgradeUserDO;
import com.skr.mdm.enums.LogAdminTypeEnum;
import com.skr.mdm.enums.StrategyEquipmentStateEnum;
import com.skr.mdm.handle.LogAdminHandler;
import com.skr.mdm.result.ResponseResult;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author nfq
 * @date 2021/1/25 10:45
 */
@Service
public class StatisticsServiceImpl implements StatisticsService {

    @Autowired
    private AppInstallDao appInstallDao;
    @Autowired
    private ClientUpgradeDao clientUpgradeDao;
    @Autowired
    private ClientUpgradeUserDao clientUpgradeUserDao;
    @Autowired
    private SysSendMsgDao sendMsgDao;
    @Autowired
    private LogAdminHandler logAdminHandler;

    @Override
    public ResponseResult appInstallStatistics(Integer companyId, String startTime, String endTime) {
        List<AppInstallCountVO> appInstallCountVOList = appInstallDao.listAppInstallCount(companyId, startTime, endTime, 15);
        return ResponseResult.success(appInstallCountVOList);
    }

    @Override
    public ResponseResult clientUpgradeStatistics(Integer companyId, String startTime, String endTime) {
        List<ClientUpgradeStatisticsVO> clientUpgradeStatisticsVOList = clientUpgradeDao.listClientUpgradeStatistics(companyId, startTime, endTime);
        if (CollectionUtils.isNotEmpty(clientUpgradeStatisticsVOList)) {
            clientUpgradeStatisticsVOList.forEach(clientUpgradeStatisticsVO -> {
                Long count = new LambdaQueryChainWrapper<>(clientUpgradeUserDao)
                        .eq(ClientUpgradeUserDO::getClientUpgradeId, clientUpgradeStatisticsVO.getId())
                        .eq(ClientUpgradeUserDO::getState, StrategyEquipmentStateEnum.EXECUTING.getState())
                        .count();
                clientUpgradeStatisticsVO.setSuccessNumber(count);
            });
        }
        return ResponseResult.success(clientUpgradeStatisticsVOList);
    }

    @Override
    public ResponseResult cmdStatistics(Integer companyId, String startTime, String endTime) throws ParseException {
        List<String> betweenDays = com.skr.mdm.util.DateUtil.getBetweenDays(startTime, endTime);
        List<CmdDayStatisticsVO> cmdDayStatisticsVOList = new ArrayList<>(betweenDays.size());
        if (CollectionUtils.isNotEmpty(betweenDays)) {
            betweenDays.forEach(cmdDate -> {
                CmdDayStatisticsVO cmdDayStatisticsVO = new CmdDayStatisticsVO();
                cmdDayStatisticsVO.setCmdAllCount(0);
                cmdDayStatisticsVO.setStrategyCmdCount(0);
                cmdDayStatisticsVO.setCmdDate(cmdDate);
                List<CmdTypeStatisticsVO> cmdTypeStatisticsVOList = sendMsgDao.cmdStatisticsGroupByCmdType(companyId, cmdDate);
                if (CollectionUtils.isNotEmpty(cmdTypeStatisticsVOList)) {
                    List<CmdTypeStatisticsVO> cmdTypeStatisticsVOS = new ArrayList<>();
                    List<CmdTypeStatisticsVO> strategyCmdTypeStatisticsVOS = new ArrayList<>();
                    for (int i = 0; i < cmdTypeStatisticsVOList.size(); i++) {
                        CmdTypeStatisticsVO cmdTypeStatisticsVO = cmdTypeStatisticsVOList.get(i);
                        CmdTypeStatisticsVO strategyCmdTypeStatisticsVO = cmdTypeStatisticsVOList.get(i);
                        if (filterCmd(cmdTypeStatisticsVO.getCmdType(), cmdTypeStatisticsVO)) {
                            cmdTypeStatisticsVOS.add(cmdTypeStatisticsVO);
                        }
                        if (filterStrategyCmd(cmdTypeStatisticsVO.getCmdType(), strategyCmdTypeStatisticsVO)) {
                            strategyCmdTypeStatisticsVOS.add(strategyCmdTypeStatisticsVO);
                        }
                    }

                    if (CollectionUtils.isNotEmpty(cmdTypeStatisticsVOS)) {
                        Integer reduce = cmdTypeStatisticsVOS.stream().mapToInt(CmdTypeStatisticsVO::getCmdCount).sum();
                        cmdDayStatisticsVO.setCmdAllCount(reduce);
                        int lossCount = cmdTypeStatisticsVOS.stream()
                                .filter(cmdTypeStatisticsVO -> "丢失".equals(cmdTypeStatisticsVO.getCmdType()))
                                .mapToInt(CmdTypeStatisticsVO::getCmdCount)
                                .sum();
                        if (lossCount > 0) {
                            cmdTypeStatisticsVOS = cmdTypeStatisticsVOS.stream()
                                    .filter(cmdTypeStatisticsVO -> !"丢失".equals(cmdTypeStatisticsVO.getCmdType()))
                                    .collect(Collectors.toList());
                            CmdTypeStatisticsVO cmdTypeStatisticsVO = new CmdTypeStatisticsVO();
                            cmdTypeStatisticsVO.setCmdType("丢失");
                            cmdTypeStatisticsVO.setCmdCount(lossCount);
                            cmdTypeStatisticsVOS.add(cmdTypeStatisticsVO);
                        }
                    }

                    if (CollectionUtils.isNotEmpty(strategyCmdTypeStatisticsVOS)) {
                        Integer reduce = strategyCmdTypeStatisticsVOS.stream().mapToInt(CmdTypeStatisticsVO::getCmdCount).sum();
                        cmdDayStatisticsVO.setStrategyCmdCount(reduce);
                    }

                    cmdDayStatisticsVO.setCmdTypeStatisticsVOList(cmdTypeStatisticsVOS);
                    cmdDayStatisticsVO.setStrategyTypeStatisticsVOList(strategyCmdTypeStatisticsVOS);
                }
                cmdDayStatisticsVOList.add(cmdDayStatisticsVO);
            });

        }
        return ResponseResult.success(cmdDayStatisticsVOList);
    }

    @Override
    public void export(LoginAdminDTO loginAdminDTO, String startTime, String endTime, HttpServletResponse response) throws IOException, ParseException {
        ExcelWriter excelWriter = null;

        try {
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("数据统计(" + startTime + "-" + endTime + ")", "UTF-8");
            response.setHeader("Content-disposition", "attachment;fileName=" + fileName +".xlsx");
            // 这里 指定文件
            excelWriter = EasyExcel.write(response.getOutputStream()).build();

            // 应用安装分析
            WriteSheet writeSheet0 = EasyExcel.writerSheet(0, "应用安装分析").head(AppInstallCountVO.class).build();
            List<AppInstallCountVO> appInstallCountVOList = appInstallDao.listAppInstallCount(loginAdminDTO.getCompanyId(), startTime, endTime, 15);
            excelWriter.write(appInstallCountVOList, writeSheet0);

            // 客户端升级分析
            WriteSheet writeSheet4 = EasyExcel.writerSheet(1, "客户端升级分析").head(ClientUpgradeStatisticsVO.class).build();
            List<ClientUpgradeStatisticsVO> clientUpgradeStatisticsVOList = clientUpgradeDao.listClientUpgradeStatistics(loginAdminDTO.getCompanyId(), startTime, endTime);
            if (CollectionUtils.isNotEmpty(clientUpgradeStatisticsVOList)) {
                clientUpgradeStatisticsVOList.forEach(clientUpgradeStatisticsVO -> {
                    Long count = new LambdaQueryChainWrapper<>(clientUpgradeUserDao)
                            .eq(ClientUpgradeUserDO::getClientUpgradeId, clientUpgradeStatisticsVO.getId())
                            .eq(ClientUpgradeUserDO::getState, StrategyEquipmentStateEnum.EXECUTE_SUCCESS.getState())
                            .count();
                    clientUpgradeStatisticsVO.setSuccessNumber(count);
                    Long issuedSuccessCount = new LambdaQueryChainWrapper<>(clientUpgradeUserDao)
                            .eq(ClientUpgradeUserDO::getClientUpgradeId, clientUpgradeStatisticsVO.getId())
                            .ge(ClientUpgradeUserDO::getState, StrategyEquipmentStateEnum.ISSUED_SUCCESS.getState())
                            .count();
                    clientUpgradeStatisticsVO.setIssuedSuccessNumber(issuedSuccessCount);
                });
            }
            excelWriter.write(clientUpgradeStatisticsVOList, writeSheet4);
            String module = "数据统计-导出";
            logAdminHandler.log(loginAdminDTO, "", LogAdminTypeEnum.OTHER_TYPE.getLogType(), "", module);

        } finally {
            // 千万别忘记finish 会帮忙关闭流
            if (excelWriter != null) {
                excelWriter.finish();
            }
        }
    }

    private boolean filterCmd(String cmdType, CmdTypeStatisticsVO cmdTypeStatisticsVO) {
        boolean flag;
        switch (cmdType) {
            case SendCmdTypeConstants.SEND_MSG:
                cmdType = "通知";
                flag = true;
                break;
            case SendCmdTypeConstants.RING_BELL:
                cmdType = "铃声";
                flag = true;
                break;
            case SendCmdTypeConstants.SET_LOCATION_TIME:
                cmdType = "设置回传";
                flag = true;
                break;
            case SendCmdTypeConstants.LOCK_SCREEN:
                cmdType = "锁屏";
                flag = true;
                break;
            case SendCmdTypeConstants.UNLOCK_SCREEN:
                cmdType = "解锁";
                flag = true;
                break;
            case SendCmdTypeConstants.CHANGE_SAFETY_SCOPE:
                cmdType = "切入安全域";
                flag = true;
                break;
            case SendCmdTypeConstants.FLOW_CONTROLLER:
                cmdType = "流量阈值";
                flag = true;
                break;
            case SendCmdTypeConstants.TASK_PHOTO:
                cmdType = "拍照";
                flag = true;
                break;
            case SendCmdTypeConstants.SCREE_CAPTURE:
                cmdType = "截屏";
                flag = true;
                break;
            case SendCmdTypeConstants.ROLL_CALL:
                cmdType = "点名";
                flag = true;
                break;
            case SendCmdTypeConstants.LOSS_EQ_CLEAR_DATA:
            case SendCmdTypeConstants.LOSS_EQ_DATA:
                cmdType = "丢失";
                flag = true;
                break;
            case SendCmdTypeConstants.BACK_EQ:
                cmdType = "找回";
                flag = true;
                break;
            case SendCmdTypeConstants.RESTORE_FACTORY:
                cmdType = "淘汰";
                flag = true;
                break;
            case SendCmdTypeConstants.OPEN_MOBILE_DATA:
                cmdType = "开启移动数据";
                flag = true;
                break;
            case SendCmdTypeConstants.ONLY_RESTORE_FACTORY:
                cmdType = "恢复出厂设置";
                flag = true;
                break;
            default:
                flag = false;
        }
        cmdTypeStatisticsVO.setCmdType(cmdType);
        return flag;
    }

    private boolean filterStrategyCmd(String cmdType, CmdTypeStatisticsVO cmdTypeStatisticsVO) {
        boolean flag;
        switch (cmdType) {
            case "issuedRailStrategy":
                cmdType = "功能";
                flag = true;
                break;
            case "issuedConfigStrategy":
                cmdType = "配置";
                flag = true;
                break;
            case "issuedComplianceStrategy":
                cmdType = "合规";
                flag = true;
                break;
            case "issuedCallDisplay":
                cmdType = "来电显示";
                flag = true;
                break;
            case "issuedCallWhitelist":
                cmdType = "通话白名单";
                flag = true;
                break;
            case "NewAppStrategy":
                cmdType = "应用";
                flag = true;
                break;
            default:
                flag = false;
        }
        cmdTypeStatisticsVO.setCmdType(cmdType);
        return flag;
    }

}