package com.njcn.event.influxdb;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import com.njcn.event.pojo.po.EventDetail;
import com.njcn.event.pojo.po.RmpEventDetailPO;
import com.njcn.event.pojo.vo.EventDetailCount;
import com.njcn.influx.config.InfluxDbConfig;
import com.njcn.influx.deprecated.InfluxDBPublicParam;
import com.njcn.influx.utils.InfluxDbUtils;
import org.apache.commons.lang3.StringUtils;
import org.influxdb.dto.QueryResult;
import org.influxdb.querybuilder.SelectQueryImpl;
import org.influxdb.querybuilder.SelectionQueryImpl;
import org.influxdb.querybuilder.clauses.Clause;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;


import static org.influxdb.querybuilder.BuiltQuery.QueryBuilder.eq;

/**
 * 表PqsEventDetail 查询封装
 *
 * @author : zhaojun
 * @version : 1.0.0
 * @date : 2022年07月04日 18:36
 */
@Component
public class PqsEventDetailQuery extends QueryBuilder {

    @Resource
    private InfluxDbConfig influxDbConfig;

    protected PqsEventDetailQuery(InfluxDbUtils influxDbUtils) {
        super(influxDbUtils);
    }

    /**
     * line_id or条件
     *
     * @param lineIds line_id
     * @return line_id or条件
     */
    public static List<Clause> lineIdOr(List<String> lineIds) {
        List<Clause> lineIdOr = new ArrayList<>();
        for (String lineId : lineIds) {
            Clause clause = eq("line_id", lineId);
            lineIdOr.add(clause);
        }
        return lineIdOr;
    }

    /**
     * 指定查询数据库和表
     *
     * @param column select count 条件
     * @see SelectQueryImpl
     */
    private SelectQueryImpl fromTable(SelectionQueryImpl column) {
        return column.from(influxDbConfig.getDatabase(), InfluxDBPublicParam.PQS_EVENT_DETAIL);
    }

    /**
     * 查询方法
     * SELECT在包括一个tag时，必须至少指定一个field
     *
     * @param columnNames 显示的字段名，查询需要指定，减少数据加载
     * @param or          or条件
     * @param and         and条件
     * @return 结果
     */
    public List<EventDetail> selectList(List<String> columnNames, List<Clause> or, List<Clause> and) {
        SelectionQueryImpl selectAppendColumnNames = selectAppendColumnNames(columnNames);
        SelectQueryImpl selectAppendTable = fromTable(selectAppendColumnNames);
        QueryResult query = getQueryResult(or, and, selectAppendTable);
        return toPOJO(query, EventDetail.class);
    }

    /**
     * Count方法
     *
     * @param columnNames 显示的字段名，查询需要指定，减少数据加载
     * @param or          or条件
     * @param and         and条件
     * @return 结果
     */
    public Integer selectCount(List<String> columnNames, List<Clause> or, List<Clause> and) {
        SelectionQueryImpl selectAppendColumnNames = countAppendColumnNames(columnNames);
        SelectQueryImpl selectAppendTable = fromTable(selectAppendColumnNames);
        QueryResult query = getQueryResult(or, and, selectAppendTable);
        List<EventDetailCount> eventDetailCounts = toPOJO(query, EventDetailCount.class);
        if (CollUtil.isEmpty(eventDetailCounts)) {
            return 0;
        }
        return eventDetailCounts.get(0).getCount();
    }

    public Integer selectCountUp(List<String> columnNames, List<List<Clause>> or, List<Clause> and) {
        SelectionQueryImpl selectAppendColumnNames = countAppendColumnNames(columnNames);
        SelectQueryImpl selectAppendTable = fromTable(selectAppendColumnNames);
        QueryResult query = getQueryResultUp(or, and, selectAppendTable);
        List<EventDetailCount> eventDetailCounts = toPOJO(query, EventDetailCount.class);
        if (CollUtil.isEmpty(eventDetailCounts)) {
            return 0;
        }
        return eventDetailCounts.get(0).getCount();
    }

    /**
     * where条件 时间和reason_type
     *
     * @param beginOfDay 开始时间
     * @param endOfDay   结束时间
     * @param type       字段 reason_type
     * @param reasonId   字段 reason_type 值
     * @return 构建查询and条件
     */
    public static List<Clause> timeAndType(String beginOfDay, String endOfDay, String type, String reasonId) {
        List<Clause> clauses = timeAnd(beginOfDay, endOfDay);
        clauses.add(eq(type, reasonId));
        return clauses;
    }

    /**
     * 统计lineIndex的数据
     *
     * @param eventDetailList influxdb数据
     * @return 个数
     */
    public static Function<List<String>, Long> countLineIndexes(List<RmpEventDetailPO> eventDetailList) {
        return lineIndexes -> eventDetailList.stream().filter(t -> lineIndexes.contains(t.getLineId())).count();
    }

    /**
     * 统计eventass_index字段非空的个数
     *
     * @return 个数
     */
    public static Function<List<RmpEventDetailPO>, Long> countEventassIndexIsNoEmpty() {
        return eventDetails -> eventDetails.stream().filter(t -> StringUtils.isNotEmpty(t.getEventassIndex())).count();
    }

    /**
     * 时间段内的数据
     *
     * @param eventDetailList influxdb数据
     * @return 数据
     */
    public static BiFunction<DateTime, DateTime, List<RmpEventDetailPO>> getBetweenTimeEventDetailList(List<RmpEventDetailPO> eventDetailList) {
        ZoneId zone = ZoneId.systemDefault();
        return (beginTime, endTime) -> eventDetailList.stream().filter(eventDetail -> {
            Instant timeId = eventDetail.getStartTime().atZone(zone).toInstant();
            return timeId.isAfter(beginTime.toInstant()) && timeId.isBefore(endTime.toInstant());
        }).collect(Collectors.toList());
    }

}
