package com.zksy.base.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zksy.base.domain.EquipmentBase;
import com.zksy.base.domain.EquipmentPointRel;
import com.zksy.base.domain.EquipmentType;
import com.zksy.base.domain.MonitorPoint;
import com.zksy.base.environment.domain.ERealTimeData;
import com.zksy.base.environment.mapper.ERealTimeDataMapper;
import com.zksy.base.gas.domain.GasMonitorData;
import com.zksy.base.gas.mapper.GasMonitorDataMapper;
import com.zksy.base.mapper.EquipmentBaseMapper;
import com.zksy.base.mapper.EquipmentPointRelMapper;
import com.zksy.base.mapper.EquipmentTypeMapper;
import com.zksy.base.mapper.MonitorPointMapper;
import com.zksy.base.service.GasMonitorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GasMonitorServiceImpl implements GasMonitorService {

    @Autowired
    private MonitorPointMapper monitorPointMapper;
    @Autowired
    private EquipmentPointRelMapper equipmentPointRelMapper;
    @Autowired
    private EquipmentBaseMapper equipmentBaseMapper;
    @Autowired
    private GasMonitorDataMapper gasMonitorDataMapper;
    @Autowired
    private ERealTimeDataMapper eRealTimeDataMapper;
    @Autowired
    private EquipmentTypeMapper equipmentTypeMapper;

    private static final DateTimeFormatter DT_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /** 燃气设备父类ID */
    private static final String GAS_PARENT_TYPE_ID = "3";

    @Override
    public List<Map<String, Object>> getPoints() {
        List<MonitorPoint> points = monitorPointMapper.selectList(
                new LambdaQueryWrapper<MonitorPoint>()
                        .eq(MonitorPoint::getPointType, "GAS")
                        .eq(MonitorPoint::getDelFlag, "0")
        );

        Set<String> gasParentTypeIds = getGasParentTypeIds();

        List<Map<String, Object>> result = new ArrayList<>();
        for (MonitorPoint p : points) {
            Map<String, Object> item = new LinkedHashMap<>();
            item.put("pointId", p.getPointId());
            item.put("pointCode", p.getPointCode());
            item.put("pointName", p.getPointName());
            item.put("location", p.getLocation());
            item.put("status", "0");
            item.put("stationCode", p.getPointCode());

            // 查关联设备
            List<EquipmentPointRel> rels = equipmentPointRelMapper.selectList(
                    new LambdaQueryWrapper<EquipmentPointRel>()
                            .eq(EquipmentPointRel::getPointId, p.getPointId())
                            .eq(EquipmentPointRel::getDelFlag, "0")
            );

            if (!rels.isEmpty()) {
                List<String> equipmentIds = rels.stream().map(EquipmentPointRel::getEquipmentId).collect(Collectors.toList());
                List<EquipmentBase> equipments = equipmentBaseMapper.selectBatchIds(equipmentIds);
                item.put("deviceCount", equipments.size());

                for (EquipmentBase eq : equipments) {
                    if (gasParentTypeIds.contains(eq.getEquipmentTypeId())) {
                        // 气体设备: mac_address = equipment_code
                        GasMonitorData latestGas = getLatestGasData(eq.getEquipmentCode());
                        if (latestGas != null) {
                            double methane = latestGas.getGasConcentration() != null ? latestGas.getGasConcentration().doubleValue() : 0;
                            item.put("methaneValue", Math.round(methane * 10.0) / 10.0);
                            item.put("lastUpdateTime", latestGas.getReportTime() != null ? latestGas.getReportTime().format(DT_FMT) : "");
                            item.put("alertStatus", methane > 20.0);
                        }
                    }
                    if (eq.getEquipmentTypeId() != null && eq.getEquipmentTypeId().contains("ENV")) {
                        // 环境设备: device_id = Integer(equipment_code)
                        ERealTimeData latestEnv = getLatestEnvData(parseIntSafe(eq.getEquipmentCode()));
                        if (latestEnv != null) {
                            double temp = latestEnv.getTem() != null ? latestEnv.getTem().doubleValue() : 0;
                            item.put("temperature", Math.round(temp * 10.0) / 10.0);
                        }
                    }
                }
            }

            // 默认值
            item.putIfAbsent("methaneValue", 0.0);
            item.putIfAbsent("methaneThreshold", 20.0);
            item.putIfAbsent("temperature", 0.0);
            item.putIfAbsent("lastUpdateTime", "");
            item.putIfAbsent("deviceCount", 0);
            item.putIfAbsent("alertStatus", false);

            result.add(item);
        }
        return result;
    }

    @Override
    public Map<String, Object> getTrend(String pointId, int hours) {
        Map<String, Object> result = new LinkedHashMap<>();
        String gasEquipmentCode = findGasEquipmentCode(pointId);
        if (gasEquipmentCode == null) {
            result.put("times", new ArrayList<>());
            result.put("methaneValues", new ArrayList<>());
            result.put("threshold", 20.0);
            return result;
        }

        // 查询该设备的所有数据，按时间排序
        List<GasMonitorData> allData = gasMonitorDataMapper.selectList(
                new LambdaQueryWrapper<GasMonitorData>()
                        .eq(GasMonitorData::getMacAddress, gasEquipmentCode)
                        .orderByAsc(GasMonitorData::getReportTime)
        );

        // 找出数据的时间范围
        LocalDateTime dataStart = allData.isEmpty() ? LocalDateTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0)
                : allData.get(0).getReportTime();
        LocalDateTime dataEnd = allData.isEmpty() ? dataStart.plusHours(23)
                : allData.get(allData.size() - 1).getReportTime();

        // 按小时分组聚合
        Map<String, Double> hourMap = new LinkedHashMap<>();
        for (GasMonitorData d : allData) {
            if (d.getReportTime() == null || d.getGasConcentration() == null) continue;
            String hourKey = d.getReportTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
            hourMap.merge(hourKey, d.getGasConcentration().doubleValue(), (a, b) -> (a + b) / 2);
        }

        // 构建24小时时间线，从dataStart的0点到dataEnd的23点
        LocalDateTime rangeStart = dataStart.withHour(0).withMinute(0).withSecond(0).withNano(0);
        LocalDateTime rangeEnd = dataEnd.withHour(23).withMinute(0).withSecond(0).withNano(0);
        if (rangeEnd.isBefore(rangeStart.plusHours(23))) {
            rangeEnd = rangeStart.plusHours(23);
        }

        List<String> times = new ArrayList<>();
        List<Double> values = new ArrayList<>();
        double lastVal = 0;
        LocalDateTime cursor = rangeStart;
        while (!cursor.isAfter(rangeEnd)) {
            times.add(cursor.format(DateTimeFormatter.ofPattern("HH:mm")));
            String key = cursor.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH"));
            Double val = hourMap.getOrDefault(key, null);
            if (val != null) {
                lastVal = val;
            }
            values.add(Math.round(lastVal * 10.0) / 10.0);
            cursor = cursor.plusHours(1);
        }

        result.put("times", times);
        result.put("methaneValues", values);
        result.put("threshold", 20.0);
        return result;
    }

    // ========== 私有辅助方法 ==========

    /** 查监测点关联的气体设备equipment_code */
    private String findGasEquipmentCode(String pointId) {
        List<EquipmentPointRel> rels = equipmentPointRelMapper.selectList(
                new LambdaQueryWrapper<EquipmentPointRel>()
                        .eq(EquipmentPointRel::getPointId, pointId)
                        .eq(EquipmentPointRel::getDelFlag, "0")
        );
        if (rels.isEmpty()) return null;
        List<String> eqIds = rels.stream().map(EquipmentPointRel::getEquipmentId).collect(Collectors.toList());
        List<EquipmentBase> eqs = equipmentBaseMapper.selectBatchIds(eqIds);
        Set<String> gasParentTypeIds = getGasParentTypeIds();
        for (EquipmentBase eq : eqs) {
            if (gasParentTypeIds.contains(eq.getEquipmentTypeId())) {
                return eq.getEquipmentCode();
            }
        }
        return null;
    }

    private GasMonitorData getLatestGasData(String macAddress) {
        List<GasMonitorData> list = gasMonitorDataMapper.selectList(
                new LambdaQueryWrapper<GasMonitorData>()
                        .eq(GasMonitorData::getMacAddress, macAddress)
                        .orderByDesc(GasMonitorData::getReportTime)
                        .last("limit 1")
        );
        return list.isEmpty() ? null : list.get(0);
    }

    private ERealTimeData getLatestEnvData(int deviceId) {
        List<ERealTimeData> list = eRealTimeDataMapper.selectList(
                new LambdaQueryWrapper<ERealTimeData>()
                        .eq(ERealTimeData::getDeviceId, deviceId)
                        .orderByDesc(ERealTimeData::getCreateTime)
                        .last("limit 1")
        );
        return list.isEmpty() ? null : list.get(0);
    }

    private int parseIntSafe(String s) {
        try { return Integer.parseInt(s); } catch (Exception e) { return 0; }
    }

    /**
     * 查询父类ID为3（燃气）的所有设备类型ID集合
     */
    private Set<String> getGasParentTypeIds() {
        List<EquipmentType> gasTypes = equipmentTypeMapper.selectList(
                new LambdaQueryWrapper<EquipmentType>()
                        .eq(EquipmentType::getParentTypeId, GAS_PARENT_TYPE_ID));
        return gasTypes.stream()
                .map(EquipmentType::getId)
                .collect(Collectors.toSet());
    }
}
