package com.zksy.electricity.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.electricity.domain.MessageParseResult;
import com.zksy.electricity.domain.vo.MessageParseVo;
import com.zksy.electricity.domain.vo.PowerLoadDistributionVo;
import com.zksy.electricity.domain.vo.VoltageCurrentTrendVo;
import com.zksy.electricity.mapper.MessageParseResultMapper;
import com.zksy.electricity.service.MessageParseResultService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @version 1.0
 * @project dh-server-micro
 * @description
 * @date 2025/2/20 10:55:03
 */
@Service
public class MessageParseResultServiceImpl extends ServiceImpl<MessageParseResultMapper, MessageParseResult> implements MessageParseResultService {
    @Autowired
    private MessageParseResultMapper messageParseResultMapper;
    @Override
    public Integer saveMessageParseResult(MessageParseResult result) {
        return messageParseResultMapper.insert(result);
    }

    /**
     * 按 tableNumber 分组统计各参数
     */
    @Override
    public List<MessageParseVo> getSummaryByTableNumber() {
        List<MessageParseResult> allData = this.list();

        Map<String, List<MessageParseResult>> grouped = allData.stream()
                .collect(Collectors.groupingBy(MessageParseResult::getTableNumber));

        List<MessageParseVo> resultList = new ArrayList<>();

        for (Map.Entry<String, List<MessageParseResult>> entry : grouped.entrySet()) {
            String tableNumber = entry.getKey();
            List<MessageParseResult> records = entry.getValue();

            MessageParseVo vo = new MessageParseVo();
            vo.setTableNumber(tableNumber);

            BigDecimal totalElectricity = records.stream()
                    .map(MessageParseResult::getTotalElectricity)
                    .map(this::parseNumber)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            vo.setTotalElectricity(totalElectricity);

            vo.setAvgAVoltage(avg(records, MessageParseResult::getAVoltage));
            vo.setAvgBVoltage(avg(records, MessageParseResult::getBVoltage));
            vo.setAvgCVoltage(avg(records, MessageParseResult::getCVoltage));
            vo.setAvgACurrent(avg(records, MessageParseResult::getACurrent));
            vo.setAvgBCurrent(avg(records, MessageParseResult::getBCurrent));
            vo.setAvgCCurrent(avg(records, MessageParseResult::getCCurrent));
            vo.setAvgTotalActivePower(avg(records, MessageParseResult::getTotalActivePower));

            resultList.add(vo);
        }

        return resultList;
    }

    @Override
    public VoltageCurrentTrendVo getVoltageCurrentTrend(String startTimeStr, String endTimeStr, String tableNumber) {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date startTime;
        Date endTime;
        try {
            startTime = sdf.parse(startTimeStr);
            endTime = sdf.parse(endTimeStr);
        } catch (ParseException e) {
            throw new IllegalArgumentException("时间格式错误，应为 yyyy-MM-dd HH:mm:ss");
        }


        List<MessageParseResult> data = this.list(
                Wrappers.<MessageParseResult>lambdaQuery()
                        .between(MessageParseResult::getCreateTime, startTime, endTime)
                        .eq(tableNumber != null && !tableNumber.isEmpty(), MessageParseResult::getTableNumber, tableNumber)
                        .orderByAsc(MessageParseResult::getCreateTime)
        );

        List<String> timeList = new ArrayList<>();
        List<BigDecimal> aVoltageList = new ArrayList<>();
        List<BigDecimal> bVoltageList = new ArrayList<>();
        List<BigDecimal> cVoltageList = new ArrayList<>();
        List<BigDecimal> aCurrentList = new ArrayList<>();
        List<BigDecimal> bCurrentList = new ArrayList<>();
        List<BigDecimal> cCurrentList = new ArrayList<>();

        SimpleDateFormat sdff = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (MessageParseResult r : data) {
            timeList.add(sdff.format(r.getCreateTime()));
            aVoltageList.add(parseNumber(r.getAVoltage()));
            bVoltageList.add(parseNumber(r.getBVoltage()));
            cVoltageList.add(parseNumber(r.getCVoltage()));
            aCurrentList.add(parseNumber(r.getACurrent()));
            bCurrentList.add(parseNumber(r.getBCurrent()));
            cCurrentList.add(parseNumber(r.getCCurrent()));
        }

        VoltageCurrentTrendVo vo = new VoltageCurrentTrendVo();
        vo.setTime(timeList);
        vo.setAVoltage(aVoltageList);
        vo.setBVoltage(bVoltageList);
        vo.setCVoltage(cVoltageList);
        vo.setACurrent(aCurrentList);
        vo.setBCurrent(bCurrentList);
        vo.setCCurrent(cCurrentList);
        return vo;
    }

    @Override
    public List<PowerLoadDistributionVo> getPowerLoadDistribution(String tableNumber, String startTime, String endTime) {
        List<MessageParseResult> records;

        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Date start = sdf.parse(startTime);
            Date end = sdf.parse(endTime);

            records = this.list(new QueryWrapper<MessageParseResult>()
                    .eq(tableNumber != null, "table_number", tableNumber)
                    .ge("create_time", start)
                    .le("create_time", end)
            );
        } catch (ParseException e) {
            return new ArrayList<>();
        } catch (Exception e) {
            return new ArrayList<>();
        }

        Map<String, List<MessageParseResult>> grouped = records.stream()
                .collect(Collectors.groupingBy(MessageParseResult::getTableNumber));

        List<PowerLoadDistributionVo> resultList = new ArrayList<>();

        for (Map.Entry<String, List<MessageParseResult>> entry : grouped.entrySet()) {
            String tn = entry.getKey();
            List<MessageParseResult> recs = entry.getValue();

            PowerLoadDistributionVo vo = new PowerLoadDistributionVo();
            vo.setTableNumber(tn);

            BigDecimal totalElectricity = recs.stream()
                    .map(MessageParseResult::getTotalElectricity)
                    .map(this::parseNumber)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal sharp = recs.stream()
                    .map(MessageParseResult::getSharpActivePowerConsumption)
                    .map(this::parseNumber)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal peak = recs.stream()
                    .map(MessageParseResult::getPeakActivePowerConsumption)
                    .map(this::parseNumber)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal average = recs.stream()
                    .map(MessageParseResult::getAverageActivePowerConsumption)
                    .map(this::parseNumber)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal valley = recs.stream()
                    .map(MessageParseResult::getValleyActivePower)
                    .map(this::parseNumber)
                    .filter(Objects::nonNull)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            vo.setTotalElectricity(totalElectricity);
            vo.setSharp(sharp);
            vo.setPeak(peak);
            vo.setAverage(average);
            vo.setValley(valley);

            if (totalElectricity.compareTo(BigDecimal.ZERO) > 0) {
                vo.setSharpRatio(sharp.divide(totalElectricity, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                vo.setPeakRatio(peak.divide(totalElectricity, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                vo.setAverageRatio(average.divide(totalElectricity, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
                vo.setValleyRatio(valley.divide(totalElectricity, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100)));
            } else {
                vo.setSharpRatio(BigDecimal.ZERO);
                vo.setPeakRatio(BigDecimal.ZERO);
                vo.setAverageRatio(BigDecimal.ZERO);
                vo.setValleyRatio(BigDecimal.ZERO);
            }

            resultList.add(vo);
        }

        return resultList;
    }
    /**
     * 将带单位的字符串解析为 BigDecimal
     */
    private BigDecimal parseNumber(String val) {
        if (val == null || val.trim().isEmpty()) return BigDecimal.ZERO;
        try {
            // 去掉非数字、小数点、负号的字符
            String cleaned = val.trim().replaceAll("[^0-9.\\-]", "");
            if (cleaned.isEmpty()) return BigDecimal.ZERO;
            return new BigDecimal(cleaned);
        } catch (Exception e) {
            return BigDecimal.ZERO;
        }
    }

    /**
     * 计算平均值
     */
    private BigDecimal avg(List<MessageParseResult> records, Function<MessageParseResult, String> getter) {
        List<BigDecimal> nums = records.stream()
                .map(getter)
                .map(this::parseNumber)
                .collect(Collectors.toList());

        if (nums.isEmpty()) {
            return BigDecimal.ZERO;
        }
        BigDecimal sum = nums.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        return sum.divide(BigDecimal.valueOf(nums.size()), 2, RoundingMode.HALF_UP);
    }
}
