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.pojo.dto.LineParamDTO;
import com.njcn.csdevice.pojo.po.CsLedger;
import com.njcn.csdevice.pojo.vo.CsLedgerVO;
import com.njcn.csharmonic.mapper.CsHarmonicMapper;
import com.njcn.csharmonic.pojo.dto.PhaseData;
import com.njcn.csharmonic.pojo.po.CsEventUserPO;
import com.njcn.csharmonic.pojo.po.CsHarmonic;
import com.njcn.csharmonic.pojo.po.RStatLimitRateDetailDPO;
import com.njcn.csharmonic.pojo.vo.HarmonicDetailVO;
import com.njcn.csharmonic.pojo.vo.HarmonicVO;
import com.njcn.csharmonic.service.CsEventUserPOService;
import com.njcn.csharmonic.service.ICsHarmonicService;
import com.njcn.csharmonic.service.IRStatLimitRateDetailDService;
import com.njcn.harmonic.utils.PublicDataUtils;
import com.njcn.web.utils.RequestUtil;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xy
 * @since 2026-03-13
 */
@AllArgsConstructor
@Service
public class CsHarmonicServiceImpl extends ServiceImpl<CsHarmonicMapper, CsHarmonic> implements ICsHarmonicService {

    private static final Map<String, String> VALUE_TYPE_MAP = new HashMap<String, String>() {{
        put("max", "最大值");
        put("min", "最小值");
        put("avg", "平均值");
        put("cp95", "95%概率值");
        put("MAX", "最大值");
        put("MIN", "最小值");
        put("AVG", "平均值");
        put("CP95", "95%概率值");
    }};

    private final CsLedgerFeignClient csLedgerFeignClient;
    private final CsEventUserPOService csEventUserPOService;
    private final IRStatLimitRateDetailDService rStatLimitRateDetailDService;
    private final CsCommTerminalFeignClient csCommTerminalFeignClient;

    @Override
    public Page<HarmonicVO.LineHarmonicDetail> queryAppList(LineParamDTO param) {
        Page<HarmonicVO.LineHarmonicDetail> result = new Page<>();
        Page<CsHarmonic> page = new Page<> (param.getPageNum(), param.getPageSize());
        HarmonicVO vo = new HarmonicVO();
        List<CsLedger> lineLedger = csLedgerFeignClient.queryLine(param).getData();
        if (CollectionUtil.isNotEmpty(lineLedger)) {
            List<String> lineIds = lineLedger.stream().map(CsLedger::getId).collect(Collectors.toList());
            //根据用户获取设备数据权限
            List<String> ownerList = csCommTerminalFeignClient.getLineIdsByUser(RequestUtil.getUserIndex()).getData();
            List<String> combinedLineIds = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(ownerList)) {
                combinedLineIds = lineIds.stream()
                        .filter(ownerList::contains)
                        .distinct()
                        .collect(Collectors.toList());
            }
            List<CsHarmonic> list = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(combinedLineIds)) {
                LambdaQueryWrapper<CsHarmonic> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.in(CsHarmonic::getLineId, combinedLineIds)
                        .ge(StrUtil.isNotBlank(param.getTime()), CsHarmonic::getTime, PublicDataUtils.calculateMonthStart(param.getTime()))
                        .le(StrUtil.isNotBlank(param.getTime()), CsHarmonic::getTime, PublicDataUtils.calculateMonthEnd(param.getTime()))
                        .orderByDesc(CsHarmonic::getTime);
                Page<CsHarmonic> csHarmonicPage = this.baseMapper.selectPage(page,queryWrapper);
                BeanUtil.copyProperties(csHarmonicPage, result);
                list = csHarmonicPage.getRecords();
            }

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

                List<HarmonicVO.LineHarmonicDetail> lineHarmonicDetails = new ArrayList<>();
                //获取用户推送事件
                List<CsEventUserPO> userEvents = csEventUserPOService.queryEventListByUserId(RequestUtil.getUserIndex(), list.stream().map(CsHarmonic::getId).collect(Collectors.toList()));
                list.forEach(item->{
                    CsLedger ledger = lineLedger.stream().filter(item1->item1.getId().equals(item.getLineId())).findFirst().orElse(null);
                    HarmonicVO.LineHarmonicDetail lineHarmonicDetail = new HarmonicVO.LineHarmonicDetail();
                    lineHarmonicDetail.setEventId(item.getId());
                    lineHarmonicDetail.setEngineeringName(ledgerMap.get(ledger.getPids().split(",")[1]).getName());
                    lineHarmonicDetail.setProjectName(ledgerMap.get(ledger.getPids().split(",")[2]).getName());
                    lineHarmonicDetail.setDevName(ledgerMap.get(ledger.getPids().split(",")[3]).getName());
                    lineHarmonicDetail.setLineId(item.getLineId());
                    lineHarmonicDetail.setLineName(ledger.getName());
                    lineHarmonicDetail.setStatisticsDate(item.getTime());
                    lineHarmonicDetail.setOverLimitDesc(item.getTag());
                    lineHarmonicDetail.setIsRead(userEvents.stream().filter(item1->item1.getEventId().equals(item.getId())).findFirst().map(CsEventUserPO::getStatus).orElse(1));
                    lineHarmonicDetails.add(lineHarmonicDetail);
                });
                vo.setList(lineHarmonicDetails);
                result.setRecords(lineHarmonicDetails);
            }
        }
        return result;
    }

    @Override
    public List<HarmonicDetailVO> queryHarmonicDetail(LineParamDTO param) {
        List<HarmonicDetailVO> list = new ArrayList<>();
        //先获取越限详细数据
        List<RStatLimitRateDetailDPO> overData = rStatLimitRateDetailDService.monitorIdsGetLimitRateInfo(param.getTime(), Collections.singletonList(param.getLineId()));

        //定义监测项配置：字段名 -> 名称前缀
        Map<String, String> simpleFields = new LinkedHashMap<>();
        simpleFields.put("freqDevOvertime", "频率偏差");
        simpleFields.put("voltageDevOvertime", "电压偏差");
        simpleFields.put("ubalanceOvertime", "三相电压不平衡度");
        simpleFields.put("flickerOvertime", "闪变");
        simpleFields.put("uaberranceOvertime", "电压总谐波畸变率");
        simpleFields.put("iNegOvertime", "负序电流");

        //根据数据组装
        overData.forEach(item->{
            // 处理简单字段
            simpleFields.forEach((fieldName, targetName) -> {
                String json = reflectGetValue(item, fieldName);
                addHarmonicData(list, json, targetName);
            });

            // 处理谐波电压含有率 (2-25 次)
            for (int i = 2; i <= 25; i++) {
                String json = reflectGetValue(item, "uharm" + i + "Overtime");
                addHarmonicData(list, json, i + "次谐波电压含有率");
            }

            // 处理谐波电流有效值 (2-25 次)
            for (int i = 2; i <= 25; i++) {
                String json = reflectGetValue(item, "iharm" + i + "Overtime");
                addHarmonicData(list, json, i + "次谐波电流有效值");
            }

            // 处理间谐波电压含有率 (0.5-15.5 次)
            for (int i = 1; i <= 16; i++) {
                String json = reflectGetValue(item, "inuharm" + i + "Overtime");
                addHarmonicData(list, json, (i-0.5) + "次间谐波电压含有率");
            }
        });
        return list;
    }

    @Override
    public HarmonicVO queryAppHarmonicCounts(LineParamDTO param) {
        HarmonicVO vo = new HarmonicVO();
        List<CsLedger> lineLedger = csLedgerFeignClient.queryLine(param).getData();
        if (CollectionUtil.isNotEmpty(lineLedger)) {
            List<String> lineIds = lineLedger.stream().map(CsLedger::getId).collect(Collectors.toList());
            //根据用户获取设备数据权限
            List<String> ownerList = csCommTerminalFeignClient.getLineIdsByUser(RequestUtil.getUserIndex()).getData();
            List<String> combinedLineIds = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(ownerList)) {
                combinedLineIds = lineIds.stream()
                        .filter(ownerList::contains)
                        .distinct()
                        .collect(Collectors.toList());
            }
            if (CollectionUtil.isNotEmpty(combinedLineIds)) {
                //查询数量
                vo = this.baseMapper.getHarmonicCounts(
                        PublicDataUtils.calculateMonthStart(param.getTime())
                        ,PublicDataUtils.calculateMonthEnd(param.getTime())
                        ,combinedLineIds);
                //查询日期
                List<String> overDays = this.baseMapper.getOverDays(
                        PublicDataUtils.calculateMonthStart(param.getTime())
                        ,PublicDataUtils.calculateMonthEnd(param.getTime())
                        ,combinedLineIds);
                vo.setOverDaysList(overDays);
            }
        }
        return vo;
    }

    @Override
    public Page<HarmonicVO.LineHarmonicOverDays> queryAppHarmonicLine(LineParamDTO param) {
        Page<HarmonicVO.LineHarmonicOverDays> page = new Page<> (param.getPageNum(), param.getPageSize());
        List<CsLedger> lineLedger = csLedgerFeignClient.queryLine(param).getData();
        if (CollectionUtil.isNotEmpty(lineLedger)) {
            List<String> lineIds = lineLedger.stream().map(CsLedger::getId).collect(Collectors.toList());
            //根据用户获取设备数据权限
            List<String> ownerList = csCommTerminalFeignClient.getLineIdsByUser(RequestUtil.getUserIndex()).getData();
            List<String> combinedLineIds = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(ownerList)) {
                combinedLineIds = lineIds.stream()
                        .filter(ownerList::contains)
                        .distinct()
                        .collect(Collectors.toList());
            }
            if (CollectionUtil.isNotEmpty(combinedLineIds)) {
                page = this.baseMapper.getLineHarmonicOverDays(page
                        ,PublicDataUtils.calculateMonthStart(param.getTime())
                        ,PublicDataUtils.calculateMonthEnd(param.getTime())
                        ,combinedLineIds);
                List<HarmonicVO.LineHarmonicOverDays> lineHarmonicOverDays = page.getRecords();
                if (CollectionUtil.isNotEmpty(lineHarmonicOverDays)) {
                    //获取所有台账数据
                    List<CsLedgerVO> ledgers = csLedgerFeignClient.getAllLedger().getData();
                    Map<String,CsLedgerVO> ledgerMap = ledgers.stream().collect(Collectors.toMap(CsLedgerVO::getId, item->item));
                    lineHarmonicOverDays.forEach(item->{
                        CsLedger ledger = lineLedger.stream().filter(item1->item1.getId().equals(item.getLineId())).findFirst().orElse(null);
                        item.setEngineeringName(ledgerMap.get(ledger.getPids().split(",")[1]).getName());
                        item.setProjectName(ledgerMap.get(ledger.getPids().split(",")[2]).getName());
                        item.setDevName(ledgerMap.get(ledger.getPids().split(",")[3]).getName());
                        item.setLineId(item.getLineId());
                        item.setLineName(ledger.getName());
                        item.setTimeList(Arrays.asList(item.getTimeString().split(", ")));
                    });
                    //对告警天数进行降序排序
                    lineHarmonicOverDays.sort((item1, item2) -> {
                        int size1 = item1.getTimeList() != null ? item1.getTimeList().size() : 0;
                        int size2 = item2.getTimeList() != null ? item2.getTimeList().size() : 0;
                        return Integer.compare(size2, size1);
                    });
                    page.setRecords(lineHarmonicOverDays);
                }
            }
        }
        return page;
    }


    /**
     * 添加谐波数据到列表
     * @param list 结果列表
     * @param jsonData JSON 数据
     * @param targetName 监测项名称
     */
    private void addHarmonicData(List<HarmonicDetailVO> list, String jsonData, String targetName) {
        if (ObjectUtil.isNotNull(jsonData)) {
            HarmonicDetailVO vo = new HarmonicDetailVO();
            vo.setTargetName(targetName);
            vo.setHarmDetailList(AnalyzeData(jsonData));
            list.add(vo);
        }
    }

    /**
     * 使用反射获取对象的字段值
     * @param obj 对象实例
     * @param fieldName 字段名
     * @return 字段值
     */
    private String reflectGetValue(Object obj, String fieldName) {
        try {
            Field field = obj.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            Object value = field.get(obj);
            return value == null ? null : value.toString();
        } catch (Exception e) {
            return null;
        }
    }


    public List<HarmonicDetailVO.HarmDetail> AnalyzeData(String jsonString) {
        List<HarmonicDetailVO.HarmDetail> result;
        ObjectMapper mapper = new ObjectMapper();
        List<PhaseData> phaseDataList = null;
        try {
            phaseDataList = mapper.readValue(jsonString, new TypeReference<List<PhaseData>>() {});
            // 合并数据
            Map<String, Map<String, String>> mergedData = new TreeMap<>(new TimeComparator());
            for (PhaseData phaseData : phaseDataList) {
                String[] times = phaseData.time.split(",");
                String[] values = phaseData.value.split(",");

                for (int i = 0; i < times.length; i++) {
                    String time = times[i].trim();
                    mergedData.putIfAbsent(time, new HashMap<>());
                    mergedData.get(time).put(phaseData.phasic, values[i].trim());
                }
            }

            // 构建所有详情列表
            List<HarmonicDetailVO.HarmDetail> allDetails = new ArrayList<>();
            for (Map.Entry<String, Map<String, String>> entry : mergedData.entrySet()) {
                String time = entry.getKey();
                Map<String, String> values = entry.getValue();

                HarmonicDetailVO.HarmDetail detail = new HarmonicDetailVO.HarmDetail();
                detail.setStatisticsTime(time);
                detail.setDataA(formatValue(values.get("A")));
                detail.setDataB(formatValue(values.get("B")));
                detail.setDataC(formatValue(values.get("C")));
                detail.setDataT(formatValue(values.get("T")));
                detail.setValueType(VALUE_TYPE_MAP.get(phaseDataList.get(0).valueType));
                detail.setOverLimitData(phaseDataList.get(0).overLimitValue);
                detail.setHasT(values.containsKey("T"));
                allDetails.add(detail);
            }

            // 选取最严重的 10 条记录（按 dataT 的绝对值排序，如果没有则取其他相）
            List<HarmonicDetailVO.HarmDetail> top10Details = allDetails.stream()
                    .sorted((d1, d2) -> {
                        Double v1 = getNumericValue(d1);
                        Double v2 = getNumericValue(d2);
                        return Double.compare(Math.abs(v2), Math.abs(v1));
                    })
                    .limit(10)
                    .collect(Collectors.toList());

            // 按时间排序后返回
            result = top10Details.stream()
                    .sorted((d1, d2) -> {
                        String t1 = d1.getStatisticsTime();
                        String t2 = d2.getStatisticsTime();
                        if (t1 == null || t2 == null) {
                            return 0;
                        }
                        String[] parts1 = t1.split(":");
                        String[] parts2 = t2.split(":");
                        for (int i = 0; i < 3; i++) {
                            int cmp = Integer.compare(Integer.parseInt(parts1[i]), Integer.parseInt(parts2[i]));
                            if (cmp != 0) return cmp;
                        }
                        return 0;
                    })
                    .collect(Collectors.toList());

        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 获取用于比较严重程度的数值
     * @param detail 谐波详情
     * @return 各相数据的绝对值之和
     */
    private Double getNumericValue(HarmonicDetailVO.HarmDetail detail) {
        double sum = 0.0;
        // 累加 dataA
        String dataA = detail.getDataA();
        if (dataA != null && !"/".equals(dataA)) {
            try {
                sum += Math.abs(Double.parseDouble(dataA));
            } catch (NumberFormatException e) {
                // 忽略解析失败的数据
            }
        }
        // 累加 dataB
        String dataB = detail.getDataB();
        if (dataB != null && !"/".equals(dataB)) {
            try {
                sum += Math.abs(Double.parseDouble(dataB));
            } catch (NumberFormatException e) {
                // 忽略解析失败的数据
            }
        }
        // 累加 dataC
        String dataC = detail.getDataC();
        if (dataC != null && !"/".equals(dataC)) {
            try {
                sum += Math.abs(Double.parseDouble(dataC));
            } catch (NumberFormatException e) {
                // 忽略解析失败的数据
            }
        }
        // 累加 dataT
        String dataT = detail.getDataT();
        if (dataT != null && !"/".equals(dataT)) {
            try {
                sum += Math.abs(Double.parseDouble(dataT));
            } catch (NumberFormatException e) {
                // 忽略解析失败的数据
            }
        }
        return sum;
    }


    /**
     * 格式化数值：有值则保留两位小数，无值则返回 /
     * @param value 原始字符串值
     * @return 格式化后的字符串
     */
    private String formatValue(String value) {
        if (value == null || value.trim().isEmpty() || "/".equals(value.trim())) {
            return "/";
        }
        try {
            DecimalFormat df = new DecimalFormat("0.00");
            return df.format(Double.parseDouble(value));
        } catch (NumberFormatException e) {
            return "/";
        }
    }

    static class TimeComparator implements Comparator<String> {
        @Override
        public int compare(String t1, String t2) {
            String[] parts1 = t1.split(":");
            String[] parts2 = t2.split(":");
            for (int i = 0; i < 3; i++) {
                int cmp = Integer.compare(Integer.parseInt(parts1[i]), Integer.parseInt(parts2[i]));
                if (cmp != 0) return cmp;
            }
            return 0;
        }
    }
}
