package com.securitycontrol.screen.service.impl;

import com.securitycontrol.common.core.constant.Constant;
import com.securitycontrol.common.core.utils.aes.DateTimeHelper;
import com.securitycontrol.common.core.web.domain.AjaxResult;
import com.securitycontrol.entity.screen.dto.ScreenParamDto;
import com.securitycontrol.entity.screen.vo.ConstrQuality;
import com.securitycontrol.entity.screen.vo.MapRiskVo;
import com.securitycontrol.entity.system.SystemGlobal;
import com.securitycontrol.screen.mapper.IScIndexMapper;
import com.securitycontrol.screen.service.IScIndexService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * @author：cwchen
 * @date：2024-03-27-10:14
 * @version：1.0
 * @description：省侧大屏-业务逻辑层
 */
@Slf4j
@Service(value = "IScIndexService")
public class ScIndexServiceImpl implements IScIndexService {

    @Resource(name = "IScIndexMapper")
    private IScIndexMapper mapper;

    @Resource(name = "testTaskExecutor")
    private ThreadPoolTaskExecutor testTaskExecutor;

    @Override
    public AjaxResult proStatusStatistics(ScreenParamDto dto) {
        Map<Object, Object> dataMap = new HashMap<>(16);
        List<Map<String, Object>> list = new ArrayList<>(16);
        int zjNum = 0, djNum = 0, tcNum = 0, tgNum = 0;
        try {
            list = mapper.proStatusStatistics(dto);
            for (Map<String, Object> map : list) {
                String name = String.valueOf(map.get("name"));
                if (Objects.equals(name, Constant.ZJ)) {
                    zjNum = Integer.parseInt(String.valueOf(map.get("num")));
                } else if (Objects.equals(name, Constant.DJ)) {
                    djNum = Integer.parseInt(String.valueOf(map.get("num")));
                } else if (Objects.equals(name, Constant.TC)) {
                    tcNum = Integer.parseInt(String.valueOf(map.get("num")));
                } else if (Objects.equals(name, Constant.TG)) {
                    tgNum = Integer.parseInt(String.valueOf(map.get("num")));
                }
            }
        } catch (Exception e) {
            log.error("工程统计", e);
        }
        dataMap.put("zjNum", zjNum);
        dataMap.put("djNum", djNum);
        dataMap.put("tcNum", tcNum);
        dataMap.put("tgNum", tgNum);
        dataMap.put("allNum", zjNum + djNum + tcNum + tgNum);
        return AjaxResult.success(dataMap);
    }

    @Override
    public AjaxResult riskStatistics(ScreenParamDto dto) {
        List<MapRiskVo> list = new ArrayList<>(500);
        try {
            list = mapper.riskStatistics(dto);
        } catch (Exception e) {
            log.error("地图风险点", e);
        }
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult constrQuality(ScreenParamDto dto) {
        List<ConstrQuality> dataList = new ArrayList<>(160);
        List<ConstrQuality> list = new ArrayList<>(2000);
        try {
            list = mapper.constrQuality(dto);
            Map<String, List<ConstrQuality>> map = list.stream().collect(Collectors.groupingBy(item -> {
                return item.getTeamId();
            }));
            map.forEach((k, v) -> {
                ConstrQuality vo = new ConstrQuality();
                BigDecimal score = new BigDecimal("0");
                BigDecimal multipleValue = new BigDecimal("20");
                for (int i = 0; i < v.size(); i++) {
                    String constrQuality = v.get(i).getConstrQuality();
                    boolean flag = isNumeric(constrQuality);
                    if (flag) {
                        BigDecimal value = new BigDecimal(constrQuality);
                        score = score.add(value);
                    }
                }
                // 分数 * 20 在除以分组数量
                BigDecimal divideValue = BigDecimal.valueOf(v.size());
                score = score.multiply(multipleValue);
                score = score.divide(divideValue, 0, BigDecimal.ROUND_HALF_UP);
                BeanUtils.copyProperties(v.get(0), vo);
                vo.setScore(score.doubleValue());
                dataList.add(vo);
            });
        } catch (Exception e) {
            log.error("施工质量", e);
        }
        List<ConstrQuality> sortDataList = dataList.stream().sorted(Comparator.comparing(ConstrQuality::getScore, Comparator.reverseOrder())).collect(Collectors.toList());
        return AjaxResult.success(sortDataList);
    }

    public static boolean isNumeric(String str) {
        if (str == null || str.isEmpty()) {
            return false;
        }
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    @Override
    public AjaxResult alarmReminder(ScreenParamDto dto) {
        List<Map<String, String>> list = new ArrayList<>();
        try {
            list = mapper.alarmReminder(dto);
        } catch (Exception e) {
            log.error("告警提醒", e);
        }
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult environmentDetection(ScreenParamDto dto) {
        Map<String, Object> map = new HashMap<>(6);
        List<Map<String, Object>> list = new ArrayList<>();
        List<Map<String, Object>> dataMapList = new ArrayList<>();
        // 空气质量 正常/异常 噪声水平 正常/异常  灰层浓度 正常/异常
        int aqiNormalNum = 0, aqiErrorNum = 0, dbNormalNum = 0, dbErrorNum = 0, hcNormalNum = 0, hcErrorNum = 0;
        try {
            dto.setTypeCode(SystemGlobal.HJ_TYPE);
            list = mapper.environmentDetection(dto);
            if (CollectionUtils.isNotEmpty(list)) {
                for (Map<String, Object> dataMap : list) {
                    if (Objects.nonNull(dataMap.get("modelName"))) {
                        String modelName = String.valueOf(dataMap.get("modelName"));
                        String warn = String.valueOf(dataMap.get("warn"));
                        if (Constant.NOISE_LEVEL.contains(modelName) && Objects.equals(warn, Constant.NOT_WARN)) {
                            dbNormalNum++;
                        } else if (Constant.NOISE_LEVEL.contains(modelName) && Objects.equals(warn, Constant.WARN)) {
                            dbErrorNum++;
                        }else if (Constant.AIR_QUALITY.contains(modelName) && Objects.equals(warn, Constant.NOT_WARN)) {
                            aqiNormalNum++;
                        }else if (Constant.AIR_QUALITY.contains(modelName) && Objects.equals(warn, Constant.WARN)) {
                            aqiErrorNum++;
                        }else if (Constant.GRAY_LAYER.contains(modelName) && Objects.equals(warn, Constant.NOT_WARN)) {
                            hcNormalNum++;
                        }else if (Constant.GRAY_LAYER.contains(modelName) && Objects.equals(warn, Constant.WARN)) {
                            hcErrorNum++;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("环境监测分析", e);
        }
        map.put("aqiNormalNum", aqiNormalNum);
        map.put("aqiErrorNum", aqiErrorNum);
        map.put("dbNormalNum", dbNormalNum);
        map.put("dbErrorNum", dbErrorNum);
        map.put("hcNormalNum", hcNormalNum);
        map.put("hcErrorNum", hcErrorNum);
        dataMapList.add(map);
        return AjaxResult.success(dataMapList);
    }

    @Override
    public AjaxResult deviceStatus(ScreenParamDto dto) {
        Map<Object, Object> returnMap = new HashMap<>(16);
        List<Map<String, Object>> dataList = new ArrayList<>(256);
        List<Map<String, Object>> list = new ArrayList<>();
        int allTotalNum = 0, onlineTotalNum = 0, offTotalNum = 0;
        try {
            list = mapper.deviceStatus(dto);
            Map<String, List<Map<String, Object>>> map = list.stream().collect(Collectors.groupingBy(item -> {
                return String.valueOf(item.get("bidCode"));
            }));
            map.forEach((k, v) -> {
                Map<String, Object> dataMap = new HashMap<>(3);
                int onlineNum = 0, offNum = 0, totalNum = 0;
                for (int i = 0; i < v.size(); i++) {
                    String status = String.valueOf(v.get(i).get("status"));
                    if (Objects.equals(status, Constant.ONLINE)) {
                        onlineNum++;
                    } else {
                        offNum++;
                    }
                    totalNum++;
                }
                dataMap.put("proName", v.get(0).get("proName"));
                dataMap.put("onlineNum", onlineNum);
                dataMap.put("offLineNum", offNum);
                dataMap.put("totalNum", totalNum);
                dataList.add(dataMap);
            });
            for (Map<String, Object> objectMap : dataList) {
                allTotalNum += Integer.parseInt(String.valueOf(objectMap.get("totalNum")));
                onlineTotalNum += Integer.parseInt(String.valueOf(objectMap.get("onlineNum")));
                offTotalNum += Integer.parseInt(String.valueOf(objectMap.get("offLineNum")));
            }
        } catch (Exception e) {
            log.error("设备状态", e);
        }
        returnMap.put("valueList", dataList);
        returnMap.put("allTotalNum", allTotalNum);
        returnMap.put("onlineTotalNum", onlineTotalNum);
        returnMap.put("offTotalNum", offTotalNum);
        return AjaxResult.success(returnMap);
    }

    @Override
    public AjaxResult potentialSafetyHazard(ScreenParamDto dto) {
        List<Map<String, Object>> list = new ArrayList<>(16);
        try {
            String currentWeekTime = DateTimeHelper.getCurrentWeekTime();
            String[] timeArr = currentWeekTime.split(",");
            dto.setStartTime(timeArr[0]);
            dto.setEndTime(timeArr[1]);
            list = mapper.potentialSafetyHazard(dto);
            // 获取隐患数
            list.forEach(item -> {
                int num = 0;
                List<Map<String, Object>> dangerList = mapper.getDangerNum(String.valueOf(item.get("orgId")), dto);
                for (Map<String, Object> map : dangerList) {
                    Integer dangerNum = Integer.parseInt(String.valueOf(map.get("num")));
                    if (dangerNum > 0) {
                        num++;
                    }
                }
                item.put("dangerNum", num);
            });
        } catch (Exception e) {
            log.error("工程安全隐患分析", e);
        }
        return AjaxResult.success(list);
    }

    @Override
    public AjaxResult resourceUse(ScreenParamDto dto) {
        Map<String, Object> map = new HashMap<>(3);
        // 人员利用率 设备使用率 能源使用情况
        Double personnelRate = new Double(0), deviceRate = new Double(0), energyValue = new Double(1201);
        try {
            Future<Double> future = testTaskExecutor.submit(() -> {
                log.info("人员利用率-执行线程{}", Thread.currentThread().getName());
                List<Integer> personnelList = personnelList = mapper.getPersonnel(dto);
                if (personnelList.get(0) == 0 || personnelList.get(1) == 0) {
                    return new Double(0);
                }
                BigDecimal value = new BigDecimal("0");
                BigDecimal multipleValue = new BigDecimal("100");
                BigDecimal classPeople = BigDecimal.valueOf(personnelList.get(0));
                BigDecimal teamPeople = BigDecimal.valueOf(personnelList.get(1));
                value = classPeople.divide(teamPeople, 3, BigDecimal.ROUND_HALF_UP);
                value = value.multiply(multipleValue);
                return value.doubleValue();
            });
            Future<Double> future2 = testTaskExecutor.submit(() -> {
                log.info("设备使用率-执行线程{}", Thread.currentThread().getName());
                List<Map<String, Object>> list = new ArrayList<>();
                list = mapper.allDeviceStatus(dto);
                if (CollectionUtils.isEmpty(list)) {
                    return new Double(0);
                }
                int onlineNum = 0, totalNum = list.size();
                for (Map<String, Object> objectMap : list) {
                    if (Objects.equals(objectMap.get("status"), Constant.ONLINE)) {
                        onlineNum++;
                    }
                }
                BigDecimal onlineValue = BigDecimal.valueOf(onlineNum);
                BigDecimal totalValue = BigDecimal.valueOf(totalNum);
                return onlineValue.divide(totalValue, 3, BigDecimal.ROUND_HALF_UP).doubleValue();
            });
            personnelRate = future.get();
            deviceRate = future2.get();
        } catch (Exception e) {
            log.error("资源利用", e);
        }
        map.put("personnelRate", personnelRate);
        map.put("deviceRate", deviceRate);
        map.put("energyValue", energyValue);
        return AjaxResult.success(map);
    }

    @Override
    public AjaxResult efficiencyAnalysis(ScreenParamDto dto) {
        List<Map<String, Object>> dataList = new ArrayList<>();
        List<Map<String, Object>> list = new ArrayList<>();
        try {
            list = mapper.efficiencyAnalysis(dto);
            Map<String, List<Map<String, Object>>> map = list.stream().collect(Collectors.groupingBy(item -> {
                return String.valueOf(item.get("bidCode"));
            }));
            map.forEach((k, v) -> {
                // 根据每个工程的工序计划及进度填报计算效率
                Map<String, Object> dataMap = new HashMap<>(16);
                BigDecimal value = new BigDecimal("0");
                BigDecimal multipleValue = new BigDecimal("100");
                for (int i = 0; i < v.size(); i++) {
                    if (Objects.nonNull(v.get(i).get("planId")) && Objects.nonNull(v.get(i).get("planProgress")) && Objects.nonNull(v.get(i).get("gxWeight"))) {
                        BigDecimal bigDecimal = new BigDecimal(String.valueOf(v.get(i).get("gxWeight")));
                        BigDecimal bigDecimal2 = new BigDecimal(String.valueOf(v.get(i).get("planProgress")));
                        value = value.add(bigDecimal.multiply(bigDecimal2).divide(multipleValue, 3, BigDecimal.ROUND_HALF_UP));
                    }
                }
                dataMap.put("proName", v.get(0).get("proName"));
                dataMap.put("value", value.doubleValue());
                dataList.add(dataMap);
            });
        } catch (Exception e) {
            log.error("效率分析(工程进度分析)", e);
        }
        return AjaxResult.success(dataList);
    }
}
