package com.dcs.equipment.service.impl;

import com.dcs.equipment.constants.FluxConstants;
import com.dcs.equipment.domain.InfluxDBQuery;
import com.dcs.equipment.domain.vo.DataTwinInfluxDBVO;
import com.dcs.equipment.service.InfluxDBService;
import com.dcs.framework.config.InfluxDBConfig;
import com.dcs.hnyz.domain.vo.EquipmentParamFormVO;
import com.influxdb.client.InfluxDBClient;
import com.influxdb.client.WriteApiBlocking;
import com.influxdb.client.domain.WritePrecision;
import com.influxdb.client.write.Point;
import com.influxdb.query.FluxTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

import static com.dcs.equipment.constants.ModbusConstants.*;
import static com.dcs.equipment.utils.ModbusUtil.*;

/**
 * @author: wangpx
 * @date: 2025-03-07 14:47
 */
@Service
public class InfluxDBServiceImpl implements InfluxDBService {
    private final InfluxDBConfig influxDBConfig;

    @Autowired
    public InfluxDBServiceImpl(InfluxDBConfig influxDBConfig) {
        this.influxDBConfig = influxDBConfig;
    }

    // TODO 待优化，将数据写入到InfluxDB中 传入值限制为一个saveInfluxDBItemList 包含 measurementName和 value
    @Override
    public void saveDataToInfluxDB(String bucket, List<EquipmentParamFormVO> equipmentFormVoList) {
        InfluxDBClient client = influxDBConfig.getClient(bucket);
        WriteApiBlocking writeApiBlocking = client.getWriteApiBlocking();
        List<Point> points = new ArrayList<>();
        long time = System.currentTimeMillis();
        // 创建存储数据的Point对象
        Point coilPoint = new Point("bool");
        Point dataPoint = new Point("data");
        Point point = new Point("string");
        // 设置Point的时间戳
        coilPoint.time(time, WritePrecision.MS);
        dataPoint.time(time, WritePrecision.MS);
        point.time(time, WritePrecision.MS);
        // 遍历EquipmentFormVo列表，添加数据到Point对象中
        for (EquipmentParamFormVO equipmentFormVo : equipmentFormVoList) {
            Object value = equipmentFormVo.getValue();
            if (value == null) continue;
            String dataType = equipmentFormVo.getDataType();
            String equipmentCode = equipmentFormVo.getCode();
            switch (dataType) {
                case COIL_DATA_TYPE: // 线圈数据为布尔类型
                    coilPoint.addField(equipmentCode, objToBoolean(value));
                    break;
                case INT_DATA_TYPE:
                    dataPoint.addField(equipmentCode, objToInt(value));
                    break;
                case FLOAT_DATA_TYPE:
                    dataPoint.addField(equipmentCode, objToFloat(value));
                    break;
                default: // 默认为字符串类型
                    point.addField(equipmentCode, value.toString());
            }
        }
        // 添加Point对象到列表中
        if (coilPoint.hasFields()) points.add(coilPoint);
        if (dataPoint.hasFields()) points.add(dataPoint);
        if (point.hasFields()) points.add(point);
        // 写入数据到InfluxDB
        if (points.size() > 0) writeApiBlocking.writePoints(points);
    }

    @Override
    public List<FluxTable> queryWithFlux(InfluxDBQuery query) {
        InfluxDBClient client = influxDBConfig.getClient(query.getBucket());
        return client.getQueryApi().query(query.buildFlux());
    }

    @Override
    public List<DataTwinInfluxDBVO> queryTemperatureByDay() {
        // 构建查询条件
        InfluxDBQuery query = new InfluxDBQuery();
        query.setBucket("shanghai_dcs_bucket");
        query.setMeasurement("data");
        query.setTimeRangeStart(FluxConstants.TIME_ONE_DAY);
        query.setWindowPeriod("4h");
        query.setAggregateFunction(FluxConstants.AGGREGATE_FUNCTION_FIRST);
        query.setFields(new String[]{"S2wdsj", "S1wdsj"});
        query.setFill(0.0d);
        // 查询数据
        List<FluxTable> fluxTables = queryWithFlux(query);
        // 数据列表
        List<DataTwinInfluxDBVO> dataTwinInfluxDBVOList = new ArrayList<>();
        // S1
        FluxTable S1FluxTable = fluxTables.get(0);
        DataTwinInfluxDBVO S1InfluxDBVO = new DataTwinInfluxDBVO();
        S1InfluxDBVO.setName("S1");
        S1InfluxDBVO.fillItems(S1FluxTable.getRecords());
        // S2
        FluxTable S2FluxTable = fluxTables.get(1);
        DataTwinInfluxDBVO S2InfluxDBVO = new DataTwinInfluxDBVO();
        S2InfluxDBVO.setName("S2");
        S2InfluxDBVO.fillItems(S2FluxTable.getRecords());
        // 添加到列表中
        dataTwinInfluxDBVOList.add(S1InfluxDBVO);
        dataTwinInfluxDBVOList.add(S2InfluxDBVO);
        return dataTwinInfluxDBVOList;
    }

    @Override
    public List<DataTwinInfluxDBVO> queryTemperatureByWeek() {
        // 构建查询条件
        InfluxDBQuery query = new InfluxDBQuery();
        query.setBucket("shanghai_dcs_bucket");
        query.setMeasurement("data");
        query.setTimeRangeStart(FluxConstants.TIME_ONE_WEEK);
        query.setWindowPeriod("28h");
        query.setAggregateFunction(FluxConstants.AGGREGATE_FUNCTION_FIRST);
        query.setFields(new String[]{"S2wdsj", "S1wdsj"});
        // 查询数据
        List<FluxTable> fluxTables = queryWithFlux(query);
        // 数据列表
        List<DataTwinInfluxDBVO> dataTwinInfluxDBVOList = new ArrayList<>();
        // S1
        FluxTable S1FluxTable = fluxTables.get(0);
        DataTwinInfluxDBVO S1InfluxDBVO = new DataTwinInfluxDBVO();
        S1InfluxDBVO.setName("S1");
        S1InfluxDBVO.fillItems(S1FluxTable.getRecords());
        // S2
        FluxTable S2FluxTable = fluxTables.get(1);
        DataTwinInfluxDBVO S2InfluxDBVO = new DataTwinInfluxDBVO();
        S2InfluxDBVO.setName("S2");
        S2InfluxDBVO.fillItems(S2FluxTable.getRecords());
        // 添加到列表中
        dataTwinInfluxDBVOList.add(S1InfluxDBVO);
        dataTwinInfluxDBVOList.add(S2InfluxDBVO);
        return dataTwinInfluxDBVOList;
    }

    @Override
    public List<DataTwinInfluxDBVO> queryTemperatureByMonth() {
        // 构建查询条件
        InfluxDBQuery query = new InfluxDBQuery();
        query.setBucket("shanghai_dcs_bucket");
        query.setMeasurement("data");
        query.setTimeRangeStart(FluxConstants.TIME_ONE_MONTH);
        query.setWindowPeriod("5d");
        query.setAggregateFunction(FluxConstants.AGGREGATE_FUNCTION_FIRST);
        query.setFields(new String[]{"S2wdsj", "S1wdsj"});
        // 查询数据
        List<FluxTable> fluxTables = queryWithFlux(query);
        // 数据列表
        List<DataTwinInfluxDBVO> dataTwinInfluxDBVOList = new ArrayList<>();
        // S1
        FluxTable S1FluxTable = fluxTables.get(0);
        DataTwinInfluxDBVO S1InfluxDBVO = new DataTwinInfluxDBVO();
        S1InfluxDBVO.setName("S1");
        S1InfluxDBVO.fillItems(S1FluxTable.getRecords());
        // S2
        FluxTable S2FluxTable = fluxTables.get(1);
        DataTwinInfluxDBVO S2InfluxDBVO = new DataTwinInfluxDBVO();
        S2InfluxDBVO.setName("S2");
        S2InfluxDBVO.fillItems(S2FluxTable.getRecords());
        // 添加到列表中
        dataTwinInfluxDBVOList.add(S1InfluxDBVO);
        dataTwinInfluxDBVOList.add(S2InfluxDBVO);
        return dataTwinInfluxDBVOList;
    }
}
