package cn.ibizlab.core.extensions.cql;

import cn.ibizlab.core.extensions.domain.ResultsMQMsg;
import com.datastax.driver.core.*;
import com.datastax.driver.core.schemabuilder.SchemaBuilder;
import com.datastax.driver.mapping.Mapper;
import com.datastax.driver.mapping.MappingManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.stereotype.Repository;

import java.sql.Timestamp;
import java.util.List;
import java.util.UUID;

import static com.datastax.driver.core.DataType.*;
import static com.datastax.driver.core.querybuilder.QueryBuilder.*;

@Slf4j
@Repository
@ConditionalOnExpression("!''.equals('${cassandra.host:}')")
public class ExecResultRepository {

    private Mapper<ExecResult> mapper;
    private Mapper<ExecResult2> mapper2;
    private Session session;

    private static final String TABLE = "ru_execresult";
    private static final String TABLE2 = "ru_execresult2";


    public ExecResultRepository(MappingManager mappingManager) {
        createTable(mappingManager.getSession());
        this.mapper = mappingManager.mapper(ExecResult.class);
        this.mapper2 = mappingManager.mapper(ExecResult2.class);
        this.session = mappingManager.getSession();
    }

    private void createTable(Session session) {
        session.execute(
                SchemaBuilder.createTable(TABLE)
                        .ifNotExists()
                        .addPartitionKey("ruleid", text())
                        .addPartitionKey("retvalue", cint())
                        .addClusteringColumn("dimfield", text())
                        .addClusteringColumn("timefield", date())
                        .addClusteringColumn("domainsfield", text())
                        .addClusteringColumn("keyvaluefield", text())
                        .addColumn("ruexecresultname", text())
                        .addColumn("updatedate", date())
                        .addColumn("rulename", text())
                        .addColumn("metricfield", cdouble())
                        .addColumn("ext_1field", text())
                        .addColumn("ext_2field", text())
                        .addColumn("businesscat", text())
                        .withOptions().clusteringOrder("dimfield", SchemaBuilder.Direction.ASC).clusteringOrder("timefield", SchemaBuilder.Direction.DESC).clusteringOrder("domainsfield", SchemaBuilder.Direction.ASC).clusteringOrder("keyvaluefield", SchemaBuilder.Direction.ASC)
        );

        session.execute(
                SchemaBuilder.createTable(TABLE2)
                        .ifNotExists()
                        .addPartitionKey("ruleid", text())
                        .addPartitionKey("keyvaluefield", text())
                        .addClusteringColumn("dimfield", text())
                        .addClusteringColumn("domainsfield", text())
                        .addClusteringColumn("timefield", date())
                        .withOptions().clusteringOrder("dimfield", SchemaBuilder.Direction.ASC).clusteringOrder("domainsfield", SchemaBuilder.Direction.ASC).clusteringOrder("timefield", SchemaBuilder.Direction.DESC)
        );
    }

    public ExecResult find(String country, String firstName, String secondName, UUID id) {
        return mapper.get(country, firstName, secondName, id);
    }

    public List<ExecResult> findAll() {
        final ResultSet result = session.execute(select().all().from(TABLE));
        return mapper.map(result).all();
    }

    public ExecResult save(ExecResult execResult) {
        ExecResult2 execResult2=new ExecResult2();
        execResult2.setRuleid(execResult.getRuleid());
        execResult2.setKeyvaluefield(execResult.getKeyvaluefield());
        execResult2.setDimfield(execResult.getDimfield());
        execResult2.setDomainsfield(execResult.getDomainsfield());
        execResult2.setTimefield(execResult.getTimefield());
        try{
            mapper.save(execResult);
        }catch(Exception ex){
            ex.printStackTrace();
        }
        try{
            mapper2.save(execResult2);
        }catch(Exception ex){
            ex.printStackTrace();
        }
        return execResult;
    }

    public void saveResultsMQMsg(ResultsMQMsg resultsMQMsg) {
        final ResultSet result = session.execute(select().all().from(TABLE2).where(in("ruleid",resultsMQMsg.getRules())).and(eq("keyvaluefield",resultsMQMsg.getKeyValueField())));
        List<ExecResult2> list = mapper2.map(result).all();
        for(ExecResult2 execResult2:list) {
            ExecResult execResult=new ExecResult();
            execResult.setRuleid(execResult2.getRuleid());
            execResult.setRetvalue(1);
            execResult.setDimfield(execResult2.getDimfield());
            execResult.setTimefield(execResult2.getTimefield());
            execResult.setDomainsfield(execResult2.getDomainsfield());
            execResult.setKeyvaluefield(execResult2.getKeyvaluefield());
            try{
                mapper.delete(execResult);
            }catch(Exception ex){}
            try{
                mapper2.delete(execResult2);
            }catch(Exception ex){}
        }
        List<ExecResult> results = resultsMQMsg.getDatas();
        if(results != null && results.size() > 0){
            for(ExecResult saveResult : results){
                save(saveResult);
            }
        }
    }



    public List<ExecResult> sum(List<String> ruleids, Integer retValue, List<String> dims, Timestamp start, Timestamp end) {
        LocalDate st = ExecResult.time2LocalDate(start);
        LocalDate ed = ExecResult.time2LocalDate(end);
        final ResultSet result = session.execute(select().column("ruleid").column("retvalue").column("dimfield").sum("metricfield").as("metricfield").
                from(TABLE).
                where(in("ruleid", ruleids)).
                and(eq("retvalue", retValue)).
                and(in("dimfield", dims)).
                and(gte("timefield", st)).and(lte("timefield", ed)).groupBy("ruleid", "retvalue", "dimfield").limit(5000).setReadTimeoutMillis(200000));
        return mapper.map(result).all();
    }

    public List<ExecResult> avg(List<String> ruleids, Integer retValue, List<String> dims, Timestamp start, Timestamp end) {
        LocalDate st = ExecResult.time2LocalDate(start);
        LocalDate ed = ExecResult.time2LocalDate(end);
        final ResultSet result = session.execute(select().column("ruleid").column("retvalue").column("dimfield").avg("metricfield").as("metricfield").
                from(TABLE).
                where(in("ruleid", ruleids)).
                and(eq("retvalue", retValue)).
                and(in("dimfield", dims)).
                and(gte("timefield", st)).and(lte("timefield", ed)).groupBy("ruleid", "retvalue", "dimfield").limit(5000).setReadTimeoutMillis(200000));
        return mapper.map(result).all();
    }

    public List<ExecResult> group(List<String> ruleids, Integer retValue, List<String> dims, String type, Timestamp start, Timestamp end) {
        if (type.equalsIgnoreCase("avg"))
            return avg(ruleids, retValue, dims, start, end);
        else
            return sum(ruleids, retValue, dims, start, end);
    }

    public List<ExecResult> group(List<String> ruleids, Integer retValue, List<String> dims, Timestamp start, Timestamp end) {

        return group(ruleids, retValue, dims, "sum", start, end);
    }

    /**
     * 根据规则ID、单位和时间查询相应的规则结果数据
     *
     * @param ruleid
     * @param retValue
     * @param dims
     * @param start
     * @param end
     * @return
     */
    public ResultSet getPageData(String ruleid, PagingState pagingState, Integer retValue, String dims, Timestamp start, Timestamp end) {
        final int RESULTS_PER_PAGE = 1000;
        LocalDate st = ExecResult.time2LocalDate(start);
        LocalDate ed = ExecResult.time2LocalDate(end);
        Statement statement = select().column("keyvaluefield").
                from(TABLE).
                where(eq("ruleid", ruleid)).
                and(eq("retvalue", retValue)).
                and(eq("dimfield", dims)).
                and(gte("timefield", st)).and(lte("timefield", ed)).setReadTimeoutMillis(200000);
        statement.setFetchSize(RESULTS_PER_PAGE);
        if (pagingState != null) {
            statement.setPagingState(pagingState);
        }
        final ResultSet result = session.execute(statement);
        return result;
    }

    /**
     * 计算绩效数据的信访件数
     *
     * @param ruleids
     * @param retValue
     * @param dims
     * @param start
     * @param end
     * @return
     */
    public List<ExecResult> sumPerformancePiece(List<String> ruleids, Integer retValue, List<String> dims, Timestamp start, Timestamp end) {
        LocalDate st = ExecResult.time2LocalDate(start);
        LocalDate ed = ExecResult.time2LocalDate(end);
        final ResultSet result = session.execute(select().column("dimfield").column("keyvaluefield").
                from(TABLE).
                where(in("ruleid", ruleids)).
                and(eq("retvalue", retValue)).
                and(in("dimfield", dims)).
                and(gte("timefield", st)).and(lte("timefield", ed)).limit(5000).setReadTimeoutMillis(200000));
        return mapper.map(result).all();
    }

}
