package com.gyee.dataadapter.dao_mqtt_influxdb_taos;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.gyee.dataadapter.dao.IHistoryDao;
import com.gyee.dataadapter.entity.PointData;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class TaosDataService implements IHistoryDao {

    @Resource
    TaosConfig config;

    @Override
    public Map<String, PointData> getLatest(List<String> tagNames) throws Exception {
        Map<String, PointData> tsDataMap = new HashMap<>();
        if(CollUtil.isEmpty(tagNames)) return tsDataMap;
        Statement st = config.getInstance().createStatement();
        String collect = tagNames.stream().map(s -> "'" + s.toLowerCase() + "'").collect(Collectors.joining(","));
        StringBuilder sql = new StringBuilder();
        sql.append("select last_row(*),tbname from ").append(config.getDbName()).append(".")
                .append(config.getAIStableName()).append(" where tbname in (").append(collect).append(") group by tbname");
        ResultSet rs = st.executeQuery(sql.toString());
        while (rs.next()) {
            tsDataMap.put(rs.getString(3).toUpperCase(), new PointData(rs.getDate(1), rs.getDouble(2)));
        }
        return tsDataMap;
    }

    @Override
    public List<PointData> getHistoryRaw(String tagName, Date startTime, Date endTime) throws Exception {
        List<PointData> tsDataList = new ArrayList<>();
        if(StrUtil.isBlank(tagName)) return tsDataList;
        Statement st = config.getInstance().createStatement();
        String sql = getHistoryRawSql(tagName, startTime.getTime(), endTime.getTime());
        ResultSet rs = st.executeQuery(sql);
        while (rs.next()) {
            tsDataList.add(new PointData(rs.getDate(1), rs.getDouble(2)));
        }
        return tsDataList;
    }

    private String getHistoryRawSql(String tagName, long startTs, long endTs) {
        StringBuilder sb = new StringBuilder();
        sb.append("select * from ").append(config.getDbName()).append(".").append(tagName.toLowerCase())
                .append(" where ts between ").append(startTs).append(" and ").append(endTs);
        return sb.toString();
    }

    private String getHistorySnapSql(String tagName, long startTs, long endTs, Integer interval) {
        StringBuilder sb = new StringBuilder();
        sb.append("select _irowts,interp(val,1) from ").append(config.getDbName()).append(".").append(tagName.toLowerCase())
                .append(" range(").append(startTs).append(",").append(endTs).append(") every(")
                .append(interval).append("s) fill(prev)");
        return sb.toString();
    }

    @Override
    public List<PointData> getHistorySnap(String tagName, Date startTime, Date endTime, Integer interval) throws Exception {
        List<PointData> tsDataList = new ArrayList<>();
        if(StrUtil.isBlank(tagName)) return tsDataList;
        Statement st = config.getInstance().createStatement();
        String sql = getHistorySnapSql(tagName, startTime.getTime(), endTime.getTime(), interval);
        ResultSet rs = st.executeQuery(sql);
        while (rs.next()) {
            tsDataList.add(new PointData(rs.getDate(1), rs.getDouble(2)));
        }
        return tsDataList;
    }

    @Override
    public List<PointData> getHistoryStat(String tagName, Date startTime, Date endTime, Integer interval, Integer type) throws Exception {
        List<PointData> result = new ArrayList<>();
        if(StrUtil.isBlank(tagName)) return result;
        Statement st = config.getInstance().createStatement();
        StringBuilder sb = new StringBuilder();
        if (type == 2) {
            sb.append("select max(val) from ");
        } else if (type == 3) {
            sb.append("select min(val) from ");
        } else {
            sb.append("select avg(val) from ");
        }
        sb.append(config.getDbName()).append(".").append(tagName.toLowerCase())
                .append(" where ts between ").append(startTime.getTime()).append(" and ").append(endTime.getTime())
                .append(" interval(").append(interval).append("s)");
        ResultSet rs = st.executeQuery(sb.toString());
        while (rs.next()) {
            result.add(new PointData(endTime, rs.getDouble(1)));
        }
        return result;
    }


    @Override
    public List<PointData> getHistoryStat2(String tagName, Date startTime, Date endTime, Integer type) throws Exception {
        List<PointData> result = new ArrayList<>();
        if(StrUtil.isBlank(tagName)) return result;
        Statement st = config.getInstance().createStatement();
        StringBuilder sb = new StringBuilder();
        if (type == 2) {
            sb.append("select max(val) from ");
        } else if (type == 3) {
            sb.append("select min(val) from ");
        } else {
            sb.append("select avg(val) from ");
        }
        sb.append(config.getDbName()).append(".").append(tagName.toLowerCase())
                .append(" where ts between ").append(startTime.getTime()).append(" and ").append(endTime.getTime())
                .append("s)");
        ResultSet rs = st.executeQuery(sb.toString());
        while (rs.next()) {
            result.add(new PointData(endTime, rs.getDouble(1)));
        }
        return result;
    }



    @Override
    public PointData getHistoryStat0(String tagName, Date startTime, Date endTime, Integer type) throws Exception {
        PointData pd = new PointData(endTime, 0);
        if(StrUtil.isBlank(tagName)) return pd;
        Statement st = config.getInstance().createStatement();
        StringBuilder sb = new StringBuilder();
        if (type == 2) {
            sb.append("select max(val) from ");
        } else if (type == 3) {
            sb.append("select min(val) from ");
        } else {
            sb.append("select avg(val) from ");
        }
        sb.append(config.getDbName()).append(".").append(tagName.toLowerCase())
                .append(" where ts between ").append(startTime.getTime()).append(" and ").append(endTime.getTime());
        ResultSet rs = st.executeQuery(sb.toString());
        while (rs.next()) {
            return new PointData(endTime, rs.getDouble(1));
        }
        return pd;
    }

    @Override
    public Map<String, PointData> getHistorySection(Date ts, List<String> tagNames) throws Exception {
        Map<String, PointData> tsDataMap = new HashMap<>();
        if(CollUtil.isEmpty(tagNames)) return tsDataMap;
        Statement st = config.getInstance().createStatement();
        String collect = tagNames.stream().map(s -> "'" + s.toLowerCase() + "'").collect(Collectors.joining(","));
        StringBuilder sql = new StringBuilder();
//        sql.append("select interp(val,1),tbname from ").append(config.getDbName()).append(".")
//                .append(config.getAIStableName()).append(" where tbname in (").append(collect)
//                .append(") partition by tbname range(").append(ts.getTime()).append(") fill(prev)");
        sql.append("select last_row(*),tbname from ").append(config.getDbName()).append(".")
                .append(config.getAIStableName()).append(" where ts <= ").append(ts.getTime())
                .append(" and tbname in (").append(collect).append(") group by tbname");

        ResultSet rs = st.executeQuery(sql.toString());
        while (rs.next()) {
            tsDataMap.put(rs.getString(3).toUpperCase(), new PointData(rs.getDate(1), rs.getDouble(2)));
        }
        return tsDataMap;
    }
}
