package com.usoftchina.bi.server.service.chart;

import com.usoftchina.bi.core.base.RepCode;
import com.usoftchina.bi.core.base.RepEntity;
import com.usoftchina.bi.core.utils.CalculationJudgeUtil;
import com.usoftchina.bi.core.utils.CollectionUtils;
import com.usoftchina.bi.server.dao.chart.ChartsConfigMapper;
import com.usoftchina.bi.server.dao.chart.ShowChartsMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.usoftchina.bi.server.model.bo.*;
import com.usoftchina.bi.server.model.vo.configVo.HistogramConfigInfo;
import com.usoftchina.bi.server.model.vo.dataVo.ChartsDataInfo;
import com.usoftchina.bi.core.jdbc.DynamicDataSourceContextHolder;
import com.usoftchina.bi.server.utils.ScreenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Repository
public class ShowHistogramService {
    @Autowired
    ShowChartsMapper showChartsMapper;
    @Autowired
    TimeConverterUtil timeConverterUtil;
    @Autowired
    ChartsConfigMapper chartsConfigMapper;
    @Autowired
    ObjectMapper objectMapper;
    @Autowired
    GetChartsDataUtilService getChartsDataUtilService;
    @Autowired
    ScreenUtil screenUtil;
    @Autowired
    ChartsUtilService chartsUtilService;

    /*
    柱状图数据展示
     */
    @Cacheable(value = "Histogram", key = "#histogramConfigInfo.toString()+#dashId")
    public RepEntity<ChartsDataInfo> showHistogram(HistogramConfigInfo histogramConfigInfo, String token, int dashId){
        Assert.notNull(histogramConfigInfo, "请求参数不能为空");
        /* 变量定义 */
        ChartsDataInfo chartsDataInfo = new ChartsDataInfo();
        String xColumn = histogramConfigInfo.getxAxis().getColumnRename(),
               yColumn = histogramConfigInfo.getyAxis().getColumnRename(),
               yType = histogramConfigInfo.getyAxis().getShowDataType(),
               xColumnType = histogramConfigInfo.getxAxis().getColumnType(),
               yAxisType = CalculationJudgeUtil.Judge(yType),
               xAxisType = histogramConfigInfo.getxAxis().getShowDataType(),
               sort = StringUtils.isEmpty(histogramConfigInfo.getSort()) ? xColumn : histogramConfigInfo.getSort(),
               rule = StringUtils.isEmpty(histogramConfigInfo.getRule()) ? "ASC" : histogramConfigInfo.getRule();
        List<String> groupBy = histogramConfigInfo.getGroups(),         //分组
                     xAxisData = new ArrayList<String>();               //X轴自己用
        List<Double> value = new ArrayList<Double>();
        List<Series> serieses = new ArrayList<Series>();                //生成柱状图的系列
        int id = histogramConfigInfo.getId();
        int baseId = getChartsDataUtilService.getBaseId(id);
        List<Screen> filters = histogramConfigInfo.getFilters();
        ScreenStr screenStr = new ScreenStr();
        String screen = "",               //正常筛选条件
               screenToColumn = "",       //跟目标列相同的筛选条件
               screenToColumnS = "";      //跟目标列相同的筛选条件
        String tableName = chartsUtilService.getSqlStr(token, id, dashId);
        ChartsColumnConfig chartsColumnConfig = chartsConfigMapper.getChartsColumn(id);
        /* 参数校验 */
        if (StringUtils.isEmpty(xColumn) || StringUtils.isEmpty(yColumn)){
            return new RepEntity(RepCode.nullAxis);
        }
        if (ObjectUtils.isEmpty(chartsColumnConfig)){
            return new RepEntity(RepCode.Null);
        }
        if (StringUtils.isEmpty(tableName)){
            return new RepEntity(RepCode.NoAuthority);
        }
        /* 取数逻辑 */
        try{
            if (!DynamicDataSourceContextHolder.isContainsDataSource(baseId)) {
                return new RepEntity(RepCode.DataSourceNull);
            } else {
                DynamicDataSourceContextHolder.setDataSourceType(baseId);
            }
            //条件语句处理
            if (!CollectionUtils.isEmpty(filters)){
                screenStr = screenUtil.screensUtil(filters, xColumn, xColumnType);
                screen = screenStr.getRet();
                screenToColumn = screenStr.getWithColumnRet();
                if (StringUtils.isEmpty(screenToColumn)){
                    if (screen.startsWith(" and ")) {
                        screenToColumnS = screen.substring(5);
                    }else {
                        screenToColumnS = screen;
                    }
                } else {
                    if (screenToColumn.startsWith(" and ")) {
                        screenToColumnS = screenToColumn.substring(5) + screen;
                    }else {
                        screenToColumnS = screenToColumn + screen;
                    }
                }
            }else {
                screenToColumnS = " 1 = 1 ";
            }
            chartsDataInfo.setChartsColumnConfig(chartsColumnConfig);
            if ("time".equals(xColumnType)) {
                xColumn = TimeConverterUtil.convertToOracleDateStr(xColumn, xAxisType);
            }
            String fieldName = yAxisType + "(" + yColumn + ") as value,nvl(" + xColumn + ",'空') as name ";
            String condition = screenToColumnS + " GROUP BY " + xColumn;
            sort = xColumn;
            if (CollectionUtils.isEmpty(groupBy)) {
                List<HistogramData> histogramList = showChartsMapper.getHistogramValueWithoutGroup(fieldName, tableName, condition, sort, rule);
                if (histogramList.size() > histogramConfigInfo.getMaxCount()) {
                    chartsDataInfo.setTooMany(true);
                }
                histogramList = histogramList.subList(0, histogramConfigInfo.getMaxCount());
                xAxisData = histogramList.stream().map(HistogramData::getName).collect(Collectors.toList());
                chartsDataInfo.setxAxis(xAxisData);
                value = histogramList.stream().map(HistogramData::getValue).collect(Collectors.toList());
                Series series = new Series(xColumn, value, null);
                serieses.add(series);
            }else {
                fieldName = fieldName + ", nvl(" + groupBy.get(0) + ",'空') as groupName ";
                condition = screenToColumnS;
                String groupCondition = xColumn + "," + groupBy.get(0);
                List<HistogramGroupData> histogramGroupList  = showChartsMapper.getHistogramValueWithGroup(fieldName, tableName, condition, groupCondition, sort, rule);
                //X轴数据
                xAxisData = histogramGroupList.stream().map(HistogramGroupData::getName).distinct().collect(Collectors.toList());
                if (CollectionUtils.isEmpty(xAxisData)) {
                    return new RepEntity(RepCode.Null);
                }
                if (xAxisData.size() > histogramConfigInfo.getMaxCount()) {
                    xAxisData = xAxisData.subList(0, histogramConfigInfo.getMaxCount());
                }
                chartsDataInfo.setxAxis(xAxisData);
                /* 数据处理 */
                List<String> groupList = histogramGroupList.stream().map(HistogramGroupData::getGroupName).distinct().limit(5).collect(Collectors.toList());
                Map<String, List<HistogramGroupData>> histogramNameMap = histogramGroupList.stream().collect(Collectors.groupingBy(HistogramGroupData::getName));
                Set<String> keyset = histogramNameMap.keySet();
                Iterator<String> keyIt= keyset.iterator();
                List<HistogramGroupData> histogramGroupListAfterHandle = new ArrayList<>();
                while (keyIt.hasNext()) {
                    String key = keyIt.next();
                    List<HistogramGroupData> histogramGroupDataList = histogramNameMap.get(key);
                    groupList.forEach(groupName -> {
                        boolean matched = histogramGroupDataList.stream().noneMatch(histogramGroupData -> groupName.equals(histogramGroupData.getGroupName()));
                        if (matched) {
                            histogramGroupDataList.add(new HistogramGroupData(key, null, groupName));
                        }
                    });
                    histogramGroupListAfterHandle.addAll(histogramGroupDataList);
                }
                /* 返回数据对象组装 */
                int i = 0;
                Map<String, List<HistogramGroupData>> histogramGroupMap = histogramGroupListAfterHandle.stream().sorted(Comparator.comparing(HistogramGroupData::getName)).filter(histogramGroupData -> groupList.contains(histogramGroupData.getGroupName())).collect(Collectors.groupingBy(HistogramGroupData::getGroupName));
                Set<String> groupSet = histogramGroupMap.keySet();
                Iterator<String> it= groupSet.iterator();
                do {
                    i++;
                    String key = it.next();
                    List<HistogramGroupData> histogramGroupDataList = histogramGroupMap.get(key);
                    value = histogramGroupDataList.stream().map(HistogramGroupData::getValue).collect(Collectors.toList()).subList(0, xAxisData.size());
                    Series series = new Series(key, value, groupBy.get(0));
                    serieses.add(series);
                }while (it.hasNext() && i <= 20);
            }
            chartsDataInfo.setSerieses(serieses);
        }catch (Exception e){
            e.printStackTrace();
            if (e.getCause().getMessage().contains("ORA-00904:")) {
                return new RepEntity(RepCode.erro.getCode(), "数据源" + e.getCause().getMessage().replace("ORA-00904:", "").replaceAll("标识符", "列"), null);
            }
            return new RepEntity(RepCode.erro.getCode(), e.getCause().getMessage(), null);
        }finally {
            DynamicDataSourceContextHolder.clearDataSourceType();
        }

        return new RepEntity(RepCode.success, chartsDataInfo);
    }

}
