package com.purui.prims;

import com.purui.prims.auth.api.authentication.pojo.User;
import com.purui.prims.common.pojo.Aggregator;
import com.purui.prims.common.pojo.DateConf;
import com.purui.prims.common.pojo.Order;
import com.purui.prims.common.pojo.enums.AggOperatorEnum;
import com.purui.prims.common.pojo.enums.QueryType;
import com.purui.prims.headless.api.pojo.request.QuerySqlReq;
import com.purui.prims.headless.api.pojo.request.QueryStructReq;
import com.purui.prims.headless.api.pojo.request.SemanticQueryReq;
import com.purui.prims.headless.api.pojo.response.SemanticQueryResp;
import com.purui.prims.headless.server.persistence.dataobject.DomainDO;
import com.purui.prims.headless.server.persistence.repository.DomainRepository;
import com.purui.prims.headless.server.service.SemanticLayerService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import static java.time.LocalDate.now;

public class BaseTest extends TestApplication {

    @Autowired
    protected SemanticLayerService semanticLayerService;

    @Autowired
    private DomainRepository domainRepository;

    protected SemanticQueryResp queryBySql(String sql) throws Exception {
        return queryBySql(sql, User.getFakeUser());
    }

    protected SemanticQueryResp queryBySql(String sql, User user) throws Exception {
        return queryByReq(buildQuerySqlReq(sql));
    }

    protected SemanticQueryResp queryByReq(SemanticQueryReq queryReq) throws Exception {
        return semanticLayerService.queryByReq(queryReq, User.getFakeUser());
    }

    protected SemanticQueryReq buildQuerySqlReq(String sql) {
        QuerySqlReq querySqlCmd = new QuerySqlReq();
        querySqlCmd.setSql(sql);
        return querySqlCmd;
    }

    protected QueryStructReq buildQueryStructReq(List<String> groups) {
        return buildQueryStructReq(groups, QueryType.METRIC);
    }

    protected QueryStructReq buildQueryStructReq(List<String> groups, QueryType queryType) {
        QueryStructReq queryStructReq = new QueryStructReq();
        queryStructReq.setQueryType(queryType);
        Aggregator aggregator = new Aggregator();
        aggregator.setFunc(AggOperatorEnum.SUM);
        aggregator.setColumn("pv");
        queryStructReq.setAggregators(Arrays.asList(aggregator));

        if (CollectionUtils.isNotEmpty(groups)) {
            queryStructReq.setGroups(groups);
        }

        DateConf dateConf = new DateConf();
        dateConf.setDateMode(DateConf.DateMode.BETWEEN);
        dateConf.setEndDate(now().plusDays(0).toString());
        dateConf.setStartDate(now().plusDays(-365).toString());
        queryStructReq.setDateInfo(dateConf);

        List<Order> orders = new ArrayList<>();
        Order order = new Order();
        order.setColumn("pv");
        orders.add(order);
        queryStructReq.setOrders(orders);
        return queryStructReq;
    }

    protected QueryStructReq buildQueryStructReq(List<String> groups,
                                                 Aggregator aggregator) {
        return buildQueryStructReq(groups, aggregator, QueryType.METRIC);
    }

    protected QueryStructReq buildQueryStructReq(List<String> groups,
                                                 Aggregator aggregator, QueryType queryType) {
        QueryStructReq queryStructReq = new QueryStructReq();
        queryStructReq.setQueryType(queryType);

        if (aggregator != null) {
            queryStructReq.setAggregators(Arrays.asList(aggregator));
        }

        if (CollectionUtils.isNotEmpty(groups)) {
            queryStructReq.setGroups(groups);
        }

        DateConf dateConf = new DateConf();
        dateConf.setDateMode(DateConf.DateMode.BETWEEN);
        dateConf.setEndDate(now().plusDays(0).toString());
        dateConf.setStartDate(now().plusDays(-365).toString());
        queryStructReq.setDateInfo(dateConf);
        return queryStructReq;
    }

    protected void setDomainNotOpenToAll() {
        Long s2Domain = 1L;
        DomainDO domainDO = domainRepository.getDomainById(s2Domain);
        domainDO.setIsOpen(0);
        domainRepository.updateDomain(domainDO);
    }

}
