package com.njcn.csharmonic.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.njcn.csdevice.api.CsCommTerminalFeignClient;
import com.njcn.csdevice.api.CsLedgerFeignClient;
import com.njcn.csdevice.api.EquipmentFeignClient;
import com.njcn.csdevice.pojo.dto.CsEquipmentDeliveryDTO;
import com.njcn.csdevice.pojo.dto.LineParamDTO;
import com.njcn.csdevice.pojo.po.CsLedger;
import com.njcn.csdevice.pojo.vo.CsLedgerVO;
import com.njcn.csharmonic.mapper.CsAlarmMapper;
import com.njcn.csharmonic.pojo.po.CsAlarm;
import com.njcn.csharmonic.pojo.po.CsAlarmData;
import com.njcn.csharmonic.pojo.po.CsEventPO;
import com.njcn.csharmonic.pojo.po.CsEventUserPO;
import com.njcn.csharmonic.pojo.vo.AlarmVO;
import com.njcn.csharmonic.service.CsEventPOService;
import com.njcn.csharmonic.service.CsEventUserPOService;
import com.njcn.csharmonic.service.ICsAlarmService;
import com.njcn.system.api.DictTreeFeignClient;
import com.njcn.system.api.EpdFeignClient;
import com.njcn.system.pojo.po.EleEpdPqd;
import com.njcn.system.pojo.po.SysDicTreePO;
import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import static com.njcn.harmonic.utils.PublicDataUtils.calculateMonthEnd;
import static com.njcn.harmonic.utils.PublicDataUtils.calculateMonthStart;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xy
 * @since 2026-03-16
 */
@Service
@AllArgsConstructor
public class CsAlarmServiceImpl extends ServiceImpl<CsAlarmMapper, CsAlarm> implements ICsAlarmService {

    private final CsLedgerFeignClient csLedgerFeignClient;
    private final CsEventUserPOService csEventUserPOService;
    private final CsCommTerminalFeignClient csCommTerminalFeignClient;
    private final CsEventPOService csEventPOService;
    private final EpdFeignClient epdFeignClient;
    private final EquipmentFeignClient equipmentFeignClient;
    private final DictTreeFeignClient dictTreeFeignClient;

    @Override
    public  Page<AlarmVO> queryAlarmList(LineParamDTO param) {
        Page<AlarmVO> page1 = new Page<>();
        Page<CsAlarm> page2 = new Page<> (param.getPageNum(), param.getPageSize());
        List<CsLedger> lineLedger = csLedgerFeignClient.queryLine(param).getData();
        if (CollectionUtil.isNotEmpty(lineLedger)) {
            List<CsLedger> devLedger = new ArrayList<>();
            //获取所有台账数据
            List<CsLedgerVO> ledgers = csLedgerFeignClient.getAllLedger().getData();
            ledgers.forEach(item->{
                lineLedger.forEach(item2->{
                    if (Objects.equals(item.getId(), item2.getPid())) {
                        devLedger.add(item2);
                    }
                });
            });
            if (CollectionUtil.isNotEmpty(devLedger)) {
                List<String> ownerDevList = csCommTerminalFeignClient.getDevIdsByUser(RequestUtil.getUserIndex()).getData();
                List<String> devList = devLedger.stream().map(CsLedger::getPid).distinct().collect(Collectors.toList());

                // 取 ownerDevList 和 devList 的交集
                if (CollectionUtil.isNotEmpty(ownerDevList)) {
                    devList = devList.stream()
                            .filter(ownerDevList::contains)
                            .distinct()
                            .collect(Collectors.toList());
                } else {
                    devList = new ArrayList<>();
                }

                LambdaQueryWrapper<CsAlarm> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.ge(StrUtil.isNotBlank(param.getTime()), CsAlarm::getTime, calculateMonthStart(param.getTime()))
                        .le(StrUtil.isNotBlank(param.getTime()), CsAlarm::getTime, calculateMonthEnd(param.getTime()))
                        .orderByDesc(CsAlarm::getTime);
                Page<CsAlarm> csAlarmPage = this.baseMapper.selectPage(page2,queryWrapper);
                BeanUtil.copyProperties(csAlarmPage, page1);
                List<CsAlarm> list = csAlarmPage.getRecords();

                if (CollectionUtil.isNotEmpty(list)) {
                    List<CsEventUserPO> userEvents = csEventUserPOService.queryEventListByUserId(RequestUtil.getUserIndex(), list.stream().map(CsAlarm::getId).collect(Collectors.toList()));

                    List<String> finalDevList = devList;
                    List<AlarmVO> result = list.stream().map(alarm -> {
                                AlarmVO alarmVO = new AlarmVO();
                                alarmVO.setEventId(alarm.getId());
                                alarmVO.setDate(alarm.getTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));

                                String devListStr = alarm.getDevList();
                                String[] devIds = devListStr.split(",");
                                List<String> matchedDevIds = Arrays.stream(devIds)
                                        .filter(devId -> StrUtil.isNotBlank(devId.trim()))
                                        .filter(finalDevList::contains)
                                        .collect(Collectors.toList());
                                alarmVO.setWarnNums(matchedDevIds.size());
                                alarmVO.setDevIds(matchedDevIds);
                                alarmVO.setIsRead(userEvents.stream().filter(item1->item1.getEventId().equals(alarm.getId())).findFirst().map(CsEventUserPO::getStatus).orElse(1));

                                int warnCounts = 0;
                                ObjectMapper objectMapper = new ObjectMapper();
                                List<CsAlarmData> resultList;
                                List<List<String>> resultList2;
                                try {
                                    resultList = objectMapper.readValue(alarm.getInterruptEvent(), new TypeReference<List<CsAlarmData>>() {});
                                    resultList2 = objectMapper.readValue(alarm.getAlarmEvent(), new TypeReference<List<List<String>>>() {});
                                } catch (JsonProcessingException e) {
                                    throw new RuntimeException(e);
                                }

                                for (String matchedDevId : matchedDevIds) {
                                    for (int j = 0; j < devIds.length; j++) {
                                        if (Objects.equals(matchedDevId, devIds[j])) {
                                            warnCounts = warnCounts + (Objects.isNull(resultList2.get(j)) ? 0 : resultList2.get(j).size());
                                        }
                                    }
                                }

                                List<CsAlarmData.OnlineRateAlarm> list1 = new ArrayList<>();
                                List<CsAlarmData.IntegrityAlarm.MonitorPointIntegrity> list2 = new ArrayList<>();
                                //根据resultList 来查询在线率和完整是否有true的，如果有就设置alarmVO的属性
                                resultList.forEach(item->{
                                    if (item == null) {
                                        return;
                                    }
                                    list1.add(item.getOnlineRate());
                                    list2.addAll(item.getIntegrity().getMonitorPoints());
                                    // 判断 onlineRate 是否有异常
                                    boolean hasOnlineRateAbnormal = list1.stream()
                                            .anyMatch(CsAlarmData.OnlineRateAlarm::getIsAbnormal);
                                    // 判断 monitorPoints 是否有异常
                                    boolean hasMonitorPointAbnormal = list2.stream()
                                            .anyMatch(CsAlarmData.IntegrityAlarm.MonitorPointIntegrity::getIsAbnormal);
                                    alarmVO.setOnlineRateIsWarn(hasOnlineRateAbnormal);
                                    alarmVO.setIntegrityIsWarn(hasMonitorPointAbnormal);
                                });
                                alarmVO.setWarnCounts(warnCounts);
                                return alarmVO;
                            })
                            .filter(alarmVO -> alarmVO.getWarnNums() > 0)
                            .sorted((a1, a2) -> a2.getDate().compareTo(a1.getDate()))
                            .collect(Collectors.toList());
                    page1.setRecords(result);
                }
            }
        }
        return page1;
    }

    @Override
    public List<AlarmVO.AlarmDetail> queryAlarmDetail(LineParamDTO.DevParamDTO param) {
        List<AlarmVO.AlarmDetail> result = new ArrayList<>();
        LambdaQueryWrapper<CsAlarm> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(StrUtil.isNotBlank(param.getTime()), CsAlarm::getTime, param.getTime());
        CsAlarm alarm = getOne(queryWrapper);
        if (ObjectUtil.isNotNull(alarm)) {

            //获取所有台账数据
            List<CsLedgerVO> ledgers = csLedgerFeignClient.getAllLedger().getData();
            Map<String,CsLedgerVO> ledgerMap = ledgers.stream().collect(Collectors.toMap(CsLedgerVO::getId, item->item));

            String devStr = alarm.getDevList();
            String[] devIds = devStr.split(",");
            for (int i = 0; i < devIds.length; i++) {
                for (int i1 = 0; i1 < param.getDevList().size(); i1++) {
                    if (Objects.equals(devIds[i], param.getDevList().get(i1))) {

                        CsLedgerVO csLedgerVO = ledgerMap.get(devIds[i]);

                        AlarmVO.AlarmDetail alarmDetail = new AlarmVO.AlarmDetail();
                        alarmDetail.setEngineeringName(ledgerMap.get(csLedgerVO.getPids().split(",")[1]).getName());
                        alarmDetail.setProjectName(ledgerMap.get(csLedgerVO.getPids().split(",")[2]).getName());
                        alarmDetail.setDevName(csLedgerVO.getName());
                        //添加设备类型
                        CsEquipmentDeliveryDTO dto = equipmentFeignClient.queryDeviceById(Collections.singletonList(csLedgerVO.getId())).getData().get(0);
                        SysDicTreePO po = dictTreeFeignClient.queryById(dto.getDevType()).getData();
                        alarmDetail.setDevType(Objects.isNull(po)?null:po.getCode());

                        if (ObjectUtil.isNotNull(alarm.getInterruptEvent())) {
                            String interruptEvent = alarm.getInterruptEvent();
                            List<CsAlarmData> resultList = new ArrayList<>();
                            if (StrUtil.isNotBlank(interruptEvent)) {
                                try {
                                    ObjectMapper objectMapper = new ObjectMapper();
                                    resultList = objectMapper.readValue(interruptEvent, new TypeReference<List<CsAlarmData>>() {});
                                    alarmDetail.setDataDetails(resultList.get(i));
                                } catch (JsonProcessingException e) {
                                    e.printStackTrace();
                                }
                            }
                        }
                        if (ObjectUtil.isNotNull(alarm.getAlarmEvent())) {
                            String alarmEvent = alarm.getAlarmEvent();
                            List<List<String>> resultList = new ArrayList<>();
                            if (StrUtil.isNotBlank(alarmEvent)) {
                                try {
                                    ObjectMapper objectMapper = new ObjectMapper();
                                    resultList = objectMapper.readValue(alarmEvent, new TypeReference<List<List<String>>>() {});
                                } catch (JsonProcessingException e) {
                                    e.printStackTrace();
                                }
                            }
                            List<String> eventDetails = resultList.get(i);
                            if (CollectionUtil.isNotEmpty(eventDetails)) {
                                alarmDetail.setWarnCounts(eventDetails.size());
                                //获取告警时间详情
                                List<CsEventPO> csEventPOList = csEventPOService.getEvents(eventDetails);
                                alarmDetail.setWarnDetails(csEventPOList.stream()
                                        .map(event -> {
                                            AlarmVO.AlarmDetail.WarnDetail warnDetail = new AlarmVO.AlarmDetail.WarnDetail();
                                            warnDetail.setWarnEventTime(event.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                                            EleEpdPqd eleEpdPqd = epdFeignClient.findByName(event.getTag()).getData();
                                            warnDetail.setWarnEventDesc(Objects.isNull(eleEpdPqd) ? event.getTag() : eleEpdPqd.getShowName());
                                            return warnDetail;
                                        }).collect(Collectors.toList())
                                );
                                alarmDetail.setWarnDetails(alarmDetail.getWarnDetails().stream().sorted((a1, a2) -> a2.getWarnEventTime().compareTo(a1.getWarnEventTime())).collect(Collectors.toList()));
                            }
                        }
                        result.add(alarmDetail);
                    }
                }
            }
        }
        return result;
    }
}
