package com.reyun.taskexecute;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.reyun.context.AppUtils;
import com.reyun.dic.ReportEnumType;
import com.reyun.model.Funnel;
import com.reyun.service.ConfigParamService;
import com.reyun.service.EventStatsService;
import com.reyun.service.ReportService;
import com.reyun.util.Constant;
import com.reyun.util.HttpClientUtil;
import com.reyun.util.SqlUtil;
import com.reyun.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * 漏斗和留存报表数据获取线程
 */
public class ReportCallable implements Callable<Map<String, List>> {

	protected static Logger logger = LoggerFactory.getLogger(ReportCallable.class);

    private EventStatsService eventStatsService = AppUtils.getApplicationContext().getBean(EventStatsService.class);
    private ReportService reportService = AppUtils.getApplicationContext().getBean(ReportService.class);
    private ConfigParamService configparamService = AppUtils.getApplicationContext().getBean(ConfigParamService.class);
    private String sql;
    private Funnel funnel;
    private String startDate;
    private String endDate;
    private String dimensionKey;
    private String dimensionValue;
    private boolean isCompare;
    private boolean isTotal;
    private int interval;
    private String reportView;
    private String userGroup;
    private String userGroupName;
    private String appKey;
    private String reportType;
    private Long appId;
    private Long accountId;

    private Map<String, List> result;
    private Map<String, String> eventAliasMap;
    private Map<String, String> dimensionMap;


    public ReportCallable(String reportType, String sql, Funnel funnel, String startDate, String endDate, String dimensionKey, boolean isCompare,
                          boolean isTotal, int interval, String reportView, String userGroup, String userGroupName,
                          Map<String, String> eventAliasMap, String dimensionValue, String appKey, Map<String, String> dimensionMap) {
        super();
        this.reportType = reportType;
		this.sql = sql;
		this.funnel = funnel;
		this.startDate = startDate;
		this.endDate = endDate;
		this.dimensionKey = dimensionKey;
		this.isCompare = isCompare;
		this.isTotal = isTotal;
		this.interval = interval;
		this.reportView = reportView;
		this.userGroup = userGroup;
		this.userGroupName = userGroupName;
		this.eventAliasMap = eventAliasMap;
		this.dimensionValue = dimensionValue;
		this.appKey = appKey;
		this.dimensionMap = dimensionMap;
	}

    public ReportCallable(String reportType, String sql, String dimensionKey, String startDate, String endDate, String reportView, Long appId, String appKey, Long accountId, String dimentioinValue) {
        this.reportType = reportType;
        this.sql = sql;
        this.dimensionKey = dimensionKey;
        this.startDate = startDate;
        this.endDate = endDate;
        this.reportView = reportView;
        this.appId = appId;
        this.appKey = appKey;
        this.accountId = accountId;
        this.dimensionValue = dimentioinValue;
    }

	public Map<String, List> getResult() {
		return result;
	}

	@Override
	public Map<String, List> call() throws Exception {

		logger.debug("thread start....................");

		Map<String, String> conditions = new HashMap<String, String>();
		conditions.put("sql", sql);
		conditions.put("dbtype", "presto");
		conditions.put("datatype", ReportEnumType.LIST.getCode());
        conditions.put("appid", appKey);

        String demoApps = configparamService.getConfigParamByKey("demo_appkey");
        List<String> demoAppList = Arrays.asList(demoApps.split(","));

        StringBuilder url = null;
        //DEMO账号处理
        if (demoAppList.contains(appKey)) {
            switch (reportType) {
                case "funnel":
                    List<String> events = Arrays.asList(funnel.getEvents().split(","));
                    url = new StringBuilder(Constant.demoUrl + "/api/trackingio/funnel/").append(events.size()).append("/")
                            .append(appKey).append((isTotal || StringUtil.isEmpty(dimensionKey) ? "" : "/" + dimensionKey));
                    url.append("/30");
                    break;
                case "retention":
                    url = new StringBuilder(Constant.demoUrl + "/api/trackingio/retentionall/").append(appKey);
                    switch (reportView) {
                        case "week":
                            url.append("/week/12");
                            break;
                        case "month":
                            url.append("/month/6");
                            break;
                        default:
                            url.append("/day/14");
                            break;
                    }

                    url.append(isTotal || StringUtil.isEmpty(dimensionKey) ? "" : "/" + dimensionKey);
                    break;
                case "eventstats":
                    url = new StringBuilder(Constant.demoUrl + "/api/trackingio/eventstats/" + appKey + "/" + reportView);
                    if (!dimensionKey.equals("total")) {
                        url.append("/" + dimensionKey);
                    }
                    break;
            }

        }


        switch (reportType) {
	        case "funnel":
	        	conditions.put("reportname", "funnel");
	            break;
	        case "retention":
	        	conditions.put("reportname", "retention");
	
	            break;
	        case "eventstats":
	        	conditions.put("reportname", "eventstats");
	            break;
	    }

        Map<String, List> responseJson = new HashMap<>();

        if (url == null) {
            try {
                String responseStr = HttpClientUtil.doHttpPostRequest(url.toString(), "trackingio", conditions);
                ObjectMapper mapper = new ObjectMapper();
                responseJson = mapper.readValue(responseStr, Map.class);
            } catch (Exception e) {
                logger.error("fail to get demo data......");
            }

        } else {
            //请求数据
            responseJson = reportService.reportBySql(conditions);
        }




        //结果处理
        switch (reportType) {
            case "funnel":
                result = SqlUtil.format4Funnel(responseJson, Arrays.asList(funnel.getEvents().split(",")), isCompare, dimensionKey,
                        startDate, endDate, isTotal, this.userGroup, this.userGroupName, this.eventAliasMap, dimensionValue, dimensionMap);
                break;
            case "retention":
                result = SqlUtil.format4Retention(responseJson, this.interval, dimensionKey, this.reportView, this.userGroup,
                        this.userGroupName, dimensionValue, dimensionMap);

                break;
            case "eventstats":
                //事件处理
                result = eventStatsService.formatEventStatsReportData(responseJson, dimensionKey, appId, accountId, startDate, endDate, reportView);
                break;
        }

		logger.debug("thread end....................");

		return result;
	}
	
}
