package vip.xiaonuo.coldchain.core.bean.influxdb.flux;

/**
 * @author jackzhou
 * @version 1.0
 * @project jfcloud-coldchain
 * @description
 * @date 2024/11/22 19:48:34
 */

import com.influxdb.annotations.Column;
import com.influxdb.annotations.Measurement;

import java.lang.reflect.Field;
import java.util.List;

public class FluxQueryBuilder {

    /**
     * 构建 Flux 查询语句
     *
     * @param clazz 实体类
     * @param filters 过滤条件（标签和字段）
     * @param startTime 查询开始时间
     * @param endTime 查询结束时间
     * @return 构建的 Flux 查询语句
     */
    public static String buildQuery(Class<?> clazz, List<FilterCondition> filters, String startTime, String endTime) {
        StringBuilder fluxQuery = new StringBuilder();

        // 获取 measurement 名称
        String measurement = getMeasurement(clazz);
        fluxQuery.append("from(bucket: \"").append(getBucketName()).append("\") ")
                .append("|> range(start: ").append(startTime).append(", stop: ").append(endTime).append(") ")
                .append("|> filter(fn: (r) => r._measurement == \"").append(measurement).append("\") ");

        // 根据字段类型（tag 或 field）添加过滤条件
        for (FilterCondition filter : filters) {
            if (isTagField(clazz, filter.getField())) {
                // 标签字段过滤
                fluxQuery.append("|> filter(fn: (r) => r[\"").append(filter.getField()).append("\"] == \"").append(filter.getValue()).append("\") ");
            } else {
                // 字段过滤
                fluxQuery.append("|> filter(fn: (r) => r._field == \"").append(filter.getField()).append("\" and r._value ").append(filter.getOperator().getOperator()).append(" ").append(filter.getValue()).append(") ");
            }
        }

        // 默认排序和限制
        fluxQuery.append("|> sort(columns: [\"_time\"], desc: true) ");
        fluxQuery.append("|> limit(n: 1)");

        return fluxQuery.toString();
    }

    /**
     * 判断字段是否为标签字段
     *
     * @param clazz 类
     * @param fieldName 字段名称
     * @return true 如果是标签字段，false 如果是普通字段
     */
    private static boolean isTagField(Class<?> clazz, String fieldName) {
        try {
            Field field = clazz.getDeclaredField(fieldName);
            // 判断字段是否带有 @Column 并且 tag=true
            Column column = field.getAnnotation(Column.class);
            return column != null && column.tag();
        } catch (NoSuchFieldException e) {
            return false;
        }
    }

    /**
     * 获取 Measurement 名称
     *
     * @param clazz 类类型
     * @return Measurement 名称
     */
    private static String getMeasurement(Class<?> clazz) {
        Measurement measurement = clazz.getAnnotation(Measurement.class);
        return (measurement != null) ? measurement.name() : "default_measurement";
    }

    /**
     * 获取桶名
     *
     * @return 桶名
     */
    private static String getBucketName() {
        return "default_bucket";
    }
}
