package com.dcs.equipment.service.impl;

import com.dcs.dcs.domain.vo.DcsEquipmentFormVo;
import com.dcs.equipment.domain.InfluxDBQuery;
import com.dcs.equipment.service.InfluxDBService;
import com.dcs.framework.config.InfluxDBConfig;
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;
    }

    @Override
    public void saveDataToInfluxDB(String bucket, List<DcsEquipmentFormVo> 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 (DcsEquipmentFormVo equipmentFormVo : equipmentFormVoList) {
            Object value = equipmentFormVo.getValue();
            if (value == null) continue;
            String dataType = equipmentFormVo.getDataType();
            String equipmentCode = equipmentFormVo.getEquipmentCode();
            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> queryWithFluxQL(InfluxDBQuery query) {
        InfluxDBClient client = influxDBConfig.getClient(query.getBucket());
        return client.getQueryApi().query(query.buildFluxQL());
    }

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