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.usoftchina.bi.server.model.bo.*;
import com.usoftchina.bi.server.model.vo.configVo.LineConfigInfo;
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.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class ShowLineService {
    @Autowired
    ShowChartsMapper showChartsMapper;
    @Autowired
    TimeConverterUtil timeConverterUtil;
    @Autowired
    ChartsConfigMapper chartsConfigMapper;
    @Autowired
    GetChartsDataUtilService getChartsDataUtilService;
    @Autowired
    ScreenUtil screenUtil;
    @Autowired
    ChartsUtilService chartsUtilService;

    /*
    Line数据展示
     */
    public RepEntity showLine(LineConfigInfo lineConfigInfo, String token, int dashId, String styleConfig){
        Assert.notNull(lineConfigInfo, "请求参数不能为空");
         /* 变量定义 */
        ChartsDataInfo chartsDataInfo = new ChartsDataInfo();
        String xColumn = lineConfigInfo.getxAxis().getColumnRename(),
               yColumn = lineConfigInfo.getyAxis().getColumnRename(),
               yType = lineConfigInfo.getyAxis().getShowDataType(),
               yAxisType = CalculationJudgeUtil.Judge(yType),
               xAxisType = lineConfigInfo.getxAxis().getShowDataType();
        List<String> groupBy = lineConfigInfo.getGroups(),
                     xAxisData = new ArrayList<String>();       //X轴自己用
        List<LineSeries> serieses = new ArrayList<LineSeries>();    //生成柱状图的系列
        List<Screen> filters = lineConfigInfo.getFilters();
        ScreenStr scr = new ScreenStr();
        String screen = "",                                 //正常筛选条件
               screenToColumn = "",                         //跟目标列相同的筛选条件
               screenToColumnS = "";                        //跟目标列相同的筛选条件
        TimeReture timeReture = new TimeReture();
        int id = lineConfigInfo.getId();
        int baseId = getChartsDataUtilService.getBaseId(id);
        ChartsColumnConfig chartsColumn = chartsConfigMapper.getChartsColumn(id);
        String tableName = chartsUtilService.getSqlStr(token, id, dashId);
        /* 参数校验 */
        if (StringUtils.isEmpty(chartsColumn)){
            return new RepEntity(RepCode.Null);
        }
        if (StringUtils.isEmpty(tableName)){
            return new RepEntity(RepCode.NoAuthority);
        }
        if (StringUtils.isEmpty(xColumn) || StringUtils.isEmpty(yColumn)){
            return new RepEntity(RepCode.nullAxis);
        }
        /* 取数逻辑 */
        try{
            if (!DynamicDataSourceContextHolder.isContainsDataSource(baseId)) {
                return new RepEntity(RepCode.DataSourceNull);
            } else {
                DynamicDataSourceContextHolder.setDataSourceType(baseId);
            }
            //条件语句处理
            if (!CollectionUtils.isEmpty(filters)) {
                scr = screenUtil.screensUtil(filters, xColumn, xAxisType);
                screen = scr.getRet();
                screenToColumn = scr.getWithColumnRet();
                if (!StringUtils.isEmpty(screenToColumn)){
                    screenToColumnS = screenToColumn.startsWith(" and ") ? (screenToColumn.substring(5) + " " + screen) : (screenToColumn+ " " + screen);
                } else {
                    screenToColumnS = screen.startsWith(" and ") ? screen.substring(5) : screen;
                }
            }else {
                screenToColumnS = " 1 = 1 ";
            }
            xColumn = TimeConverterUtil.convertToOracleDateStr(xColumn, xAxisType);         //X轴 -> 折线图X轴只能为日期类型
            String fieldName = yAxisType + "(" + yColumn + ") as value,nvl(" + xColumn + ",'空') as \"date\" ";
            String condition = screenToColumnS + " GROUP BY " + xColumn;
            String sort = xColumn, rule = "ASC";
            if (CollectionUtils.isEmpty(groupBy)) {
                List<LineSeriesMap> lineSeriesMapList = showChartsMapper.getLineValueWithoutGroup(fieldName, tableName, condition, sort, rule);
                xAxisData = lineSeriesMapList.stream().map(LineSeriesMap::getDate).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(xAxisData)) {
                    return new RepEntity(RepCode.Null);
                }
                if (xAxisData.size() > lineConfigInfo.getMaxCount()) {
                    chartsDataInfo.setTooMany(true);
                }
                serieses.add(new LineSeries(null, lineSeriesMapList));
            }else {
                fieldName = fieldName + ", nvl(" + groupBy.get(0) + ",'空') as groupName ";
                condition = screenToColumnS;
                String groupCondition = xColumn + "," + groupBy.get(0);
                List<LineSeriesGroupMap> lineSeriesGroupMapList = showChartsMapper.getLineValueWithGroup(fieldName, tableName, condition, groupCondition,sort, rule);
                Map<String, List<LineSeriesGroupMap>> lineSeriesGroupMap = CollectionUtils.groupBy(lineSeriesGroupMapList, LineSeriesGroupMap::getGroupName);
                Iterator<Map.Entry<String, List<LineSeriesGroupMap>>> it = lineSeriesGroupMap.entrySet().iterator();
                List<LineSeriesMap> lineSeriesMapList = null;
                while (it.hasNext()) {
                    Map.Entry<String, List<LineSeriesGroupMap>> entry = it.next();
                    lineSeriesMapList = new ArrayList<>();
                    copyProperties(entry.getValue(), lineSeriesMapList);
                    serieses.add(new LineSeries(entry.getKey(), lineSeriesMapList));
                }
            }
            chartsDataInfo.setStyleConfig(styleConfig);
            chartsDataInfo.setChartsColumnConfig(chartsColumn);
            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);
    }

    /**
     * LineSeriesGroupMap 转 LineSeriesMap
     * @param source
     * @param target
     */
    private void copyProperties(List<LineSeriesGroupMap> source, List<LineSeriesMap> target){
        if (!CollectionUtils.isEmpty(source)) {
            for (LineSeriesGroupMap lineSeriesGroupMap : source) {
                target.add(new LineSeriesMap(lineSeriesGroupMap.getDate(), lineSeriesGroupMap.getValue()));
            }
        }
    }


}
