package com.njcn.device.device.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.device.common.service.GeneralDeviceService;
import com.njcn.device.device.service.OnLineRateService;
import com.njcn.device.common.mapper.onlinerate.OnLineRateMapper;
import com.njcn.device.pq.enums.RunFlagEnum;
import com.njcn.device.pq.pojo.dto.GeneralDeviceDTO;
import com.njcn.device.pq.pojo.param.DeviceInfoParam;
import com.njcn.device.pq.pojo.param.OnlineRateParam;
import com.njcn.device.pq.pojo.po.RStatOnlinerateD;
import com.njcn.device.pq.pojo.vo.DevDetail;
import com.njcn.device.pq.pojo.vo.RStatOnlineRateVO;
import com.njcn.device.pq.pojo.vo.common.DeviceOnlineRate;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wr
 * @description
 * @date 2025/11/26 10:26
 */
@Service
@RequiredArgsConstructor
public class OnLineRateServiceImpl extends ServiceImpl<OnLineRateMapper, RStatOnlinerateD> implements OnLineRateService {

    private final GeneralDeviceService deviceService;

    @Override
    public DeviceOnlineRate deviceOnlineRateInfo(DeviceInfoParam.BusinessParam param) {
        DeviceOnlineRate rate = new DeviceOnlineRate();
        List<Integer> devRun = ObjectUtil.isNull(param.getLineRunFlag()) ? null : Arrays.asList(param.getLineRunFlag());
        param.setLineRunFlag(null);
        //获取终端台账类信息
        List<GeneralDeviceDTO> deviceInfo = deviceService.getDeviceInfo(param, devRun, Arrays.asList(1));
        if (CollUtil.isNotEmpty(deviceInfo)) {
            List<String> deviceIds = deviceInfo.stream()
                    .flatMap(x -> x.getDeviceIndexes().stream()).collect(Collectors.toList())
                    .stream()
                    .distinct()
                    .collect(Collectors.toList());
            rate.setTotalNum(deviceIds.size());
            OnlineRateParam onlineRateParam = new OnlineRateParam();
            onlineRateParam.setIds(deviceIds);
            onlineRateParam.setStartTime(param.getSearchBeginTime());
            onlineRateParam.setEndTime(param.getSearchEndTime());
            //获取所有终端在线率
            List<RStatOnlineRateVO> onlineRateByDev = this.baseMapper.getOnlineRateByDevIds(onlineRateParam);

            //获取所有终端信息
            List<DevDetail> devInfoByIds = deviceService.getDevInfoByIds(deviceIds);
            rate.setBelowNum(CollUtil.isNotEmpty(onlineRateByDev) ? calculateOnLineRate(onlineRateByDev, 90, deviceIds.size()) : deviceIds.size());
            rate.setTotalOnlineRate(calculateOnLineRate(onlineRateByDev, deviceIds));
            List<DeviceOnlineRate.CitDetail> citDetailList = new ArrayList<>();
            DeviceOnlineRate.CitDetail citDetail;
            DeviceOnlineRate.Detail detail;
            for (GeneralDeviceDTO dto : deviceInfo) {
                //获取部门终端集合
                List<RStatOnlineRateVO> citDevOnRate = onlineRateByDev.stream().filter(x -> dto.getDeviceIndexes().contains(x.getDevIndex())).collect(Collectors.toList());
                Map<String, BigDecimal> onlineRateByDevMap = citDevOnRate.stream()
                        .collect(Collectors.toMap(x -> x.getDevIndex(), x -> x.getOnlineRate()));
                citDetail = new DeviceOnlineRate.CitDetail();
                citDetail.setCitName(dto.getName());
                citDetail.setCitTotalNum(dto.getDeviceIndexes().size());
                citDetail.setCitBelowNum(CollUtil.isNotEmpty(citDevOnRate) ? calculateOnLineRate(citDevOnRate, 90, dto.getDeviceIndexes().size()) : dto.getDeviceIndexes().size());
                citDetail.setCitTotalOnlineRate(calculateOnLineRate(onlineRateByDev, dto.getDeviceIndexes()));
                List<DeviceOnlineRate.Detail> detailList = new ArrayList<>();
                List<DevDetail> details = devInfoByIds.stream().filter(x -> dto.getDeviceIndexes().contains(x.getDevIndex())).collect(Collectors.toList());
                for (DevDetail dev : details) {
                    detail = new DeviceOnlineRate.Detail();
                    detail.setCit(dev.getDeptName());
                    detail.setCompany(dev.getGdName());
                    detail.setSubStation(dev.getBdzName());
                    detail.setDeviceId(dev.getDevIndex());
                    detail.setDeviceName(dev.getDevName());
                    detail.setManufacturer(dev.getManufacturer());
                    detail.setIp(dev.getIp());
                    detail.setRunFlag(RunFlagEnum.getRunFlagRemarkByStatus(dev.getRunFlag()));
                    detail.setComFlag(dev.getComFlag() == 0 ? "中断" : "正常");
                    detail.setTimeID(dev.getTimeID());
                    detail.setOnlineRate(onlineRateByDevMap.containsKey(dev.getDevIndex()) ? onlineRateByDevMap.get(dev.getDevIndex()) : BigDecimal.valueOf(0));
                    detailList.add(detail);
                }
                citDetail.setDetailList(detailList);
                citDetailList.add(citDetail);
            }
            rate.setCitDetailList(citDetailList);
        }
        return rate;
    }

    @Override
    public List<RStatOnlineRateVO> getOnlineRateByDevIds(OnlineRateParam onlineRateParam) {
        return this.baseMapper.getOnlineRateByDevIds(onlineRateParam);
    }

    private BigDecimal calculateOnLineRate(List<RStatOnlineRateVO> onlineRateByDev, List<String> deviceIds) {
        List<RStatOnlineRateVO> list = onlineRateByDev.stream().filter(x -> deviceIds.contains(x.getDevIndex())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(list)) {
            BigDecimal onlineMin = BigDecimal.valueOf(list.stream().mapToLong(RStatOnlineRateVO::getOnlineMin).sum());
            BigDecimal offlineMin = BigDecimal.valueOf(list.stream().mapToLong(RStatOnlineRateVO::getOfflineMin).sum());
            BigDecimal sumMin = onlineMin.add(offlineMin);
            if (BigDecimal.ZERO.compareTo(sumMin) == 0) {
                BigDecimal.valueOf(0);
            }
            return onlineMin.multiply(BigDecimal.valueOf(100.0)).divide(sumMin, 2, RoundingMode.HALF_UP);
        }
        return BigDecimal.valueOf(0);
    }

    private Integer calculateOnLineRate(List<RStatOnlineRateVO> onlineRateByDev, Integer limit, Integer count) {
        return count - onlineRateByDev.stream().filter(x -> x.getOnlineRate().doubleValue() >= limit).collect(Collectors.toList()).size();
    }


}
