package com.ozs.rpm.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ozs.rpm.dto.KpiListColumnDTO;
import com.ozs.rpm.dto.ReportDTO;
import com.ozs.rpm.dto.ReportKPIDTO;
import com.ozs.rpm.dto.ReportSqlDTO;
import com.ozs.rpm.dto.kpim.ComputedTypeInfoDTO;
import com.ozs.rpm.dto.kpim.DefinedTypeInfoDTO;
import com.ozs.rpm.dto.kpim.KpiConfigDTO;
import com.ozs.rpm.dto.kpim.RelColumnConfigDTO;
import com.ozs.rpm.dto.kpim.RuleConfigDTO;
import com.ozs.rpm.dto.save.RpmInfoReportChartDTO;
import com.ozs.rpm.dto.util.ChartParameterDTO;
import com.ozs.rpm.mapper.ReportMapper;
import com.ozs.rpm.service.ReportDataService;
import com.ozs.rpm.util.KpimApi;
import com.ozs.rpm.util.MdmApi;
import com.ozs.rpm.util.R;
import com.ozs.rpm.util.S;
import com.ozs.rpm.util.StringUtil;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class ReportDataServiceImpl implements ReportDataService {

	@Autowired
	private KpimApi kpimApi;
	@Autowired
	private MdmApi mdmApi;
	@Autowired
	private ReportMapper reportMapper;

	/**
	 * 报表中，如果有group by，则kpi中， 数值型（除率值）求和， 率值求平均值， 只保留group by的字段
	 */
	@Override
	public R<String> saveReportSql(String reportId) {
		// 三个图表的结果集
		List<ReportSqlDTO> resultList = new ArrayList<>();
		// 封装的报表类型参数集
		ChartParameterDTO chartParameter = new ChartParameterDTO();
		// 根据报表ID查询报表对应KPI数组
		List<ReportKPIDTO> reportKPIList = new ArrayList<>();
		// 分组id数组
		List<String> idsGroupBy = new ArrayList<>();
		List<String> idsOperableGroup = new ArrayList<>();

		try {
			reportKPIList = reportMapper.listReportKPI(reportId);
			idsGroupBy = reportMapper.listReportIdByGroupSort(reportId);
			idsOperableGroup = reportMapper.listReportIdByOperableGroup(reportId);
			// 去重合并
			idsGroupBy.removeAll(idsOperableGroup);
			idsGroupBy.addAll(idsOperableGroup);
		} catch (Exception e) {
			e.printStackTrace();
			return new R<>(S.ERROR, "报表没有kpi");
		}
		// KPIID-所有集合
		List<String> ids = new ArrayList<String>();
		// KPIID-分组查询集合
		for (int i = 0; i < reportKPIList.size(); i++) {
			// KPIID-所有集合
			ids.add(reportKPIList.get(i).getKpiId());
			// KPIID-分组查询集合
			// if (reportKPIList.get(i).getIfQueryGroupBy() != null &&
			// reportKPIList.get(i).getIfQueryGroupBy() == 1) {
			// idsGroupBy.add(reportKPIList.get(i).getKpiId());
			// }
		}
		if (ids.size() == 0) {
			return new R<>("-1", "报表没有KPI");
		}
		// 报表对应的图表KPI信息
		List<RpmInfoReportChartDTO> chartInfoList = new ArrayList<>();
		try {
			// 查询该报表有哪些图表KPI信息
			chartInfoList = reportMapper.getReportChartType(reportId);
		} catch (Exception e) {
			e.printStackTrace();
			return new R<>(S.ERROR);
		}
		// 图表类型
		Set<Integer> reportTypeSet = new HashSet<>();
		// 目前有两种图：柱折混合，饼
		// 柱折混合只有一个X
		RpmInfoReportChartDTO bolX = null;
		// 柱折混合的Y集合
		List<RpmInfoReportChartDTO> bolYList = new ArrayList<>();
		// 饼图集合
		List<RpmInfoReportChartDTO> pieList = new ArrayList<>();
		for (RpmInfoReportChartDTO chartInfo : chartInfoList) {
			// 累计图表类型
			reportTypeSet.add(chartInfo.getChartTypeId());
			// 查询柱折的X
			if (chartInfo.getChartTypeId() == 1) { // 柱折混合图
				if (chartInfo.getAxis() == 1) { // x轴
					bolX = chartInfo;
				}
				bolYList.add(chartInfo); // x和y轴
			} else if (chartInfo.getChartTypeId() == 2) { // 饼图
				pieList.add(chartInfo);
			}
			// 饼图的
		}
		List<Integer> reportTypes = new ArrayList<>(reportTypeSet);
		// 默认加个统计图
		reportTypes.add(0, 0);
		// 2 3 4-保存为拼接sql查询条件：图表-柱折xy，饼图kpi
		// 所有相关字段集合
		Set<String> columnIdSets = new HashSet<>();
		List<String> columnIds = null;
		// 报表所有KPI详细信息
		List<KpiConfigDTO> kpiConfigList = kpimApi.listKpiConfigByKpiIds(ids);
		if (kpiConfigList == null) {
			return new R<>(S.ERROR);
		}
		for (int i = 0; i < kpiConfigList.size(); i++) {
			// kpi详细信息
			KpiConfigDTO kpi = kpiConfigList.get(i);
			/**
			 * 计算类型
			 */
			if (kpi.getType() == 2) {
				// 获取计算类型相关内容
				ComputedTypeInfoDTO computedTypeInfo = kpi.getComputedTypeInfo();
				// KPI字段之间关系
				List<RelColumnConfigDTO> relColumnList = computedTypeInfo.getRelOptions();
				if (relColumnList != null) {
					for (int j = 0; j < relColumnList.size(); j++) {
						// 添加相关表和字段
						columnIdSets.add(relColumnList.get(j).getColumnId());
						columnIdSets.add(relColumnList.get(j).getRelColumnId());
					}
				}
				// KPI计算公式，按数据加载，如(a /b)
				List<RuleConfigDTO> ruleConfigList = computedTypeInfo.getRuleOptions();
				if (ruleConfigList != null) {
					String isConstant = "";
					for (int j = 0; j < ruleConfigList.size(); j++) {
						if (ruleConfigList.get(j) != null) {
							isConstant = ruleConfigList.get(j).getIsConstant();
						}
						if (StringUtil.isNotEmpty(isConstant) && isConstant.equals("false")) { // 字段
							// 添加相关表和字段
							columnIdSets.add(ruleConfigList.get(j).getColumnId());
						}
					}
				}
			} else if (kpi.getType() == 4) {
				/**
				 * 函数类型
				 */
				List<DefinedTypeInfoDTO> functionKpiColumns = kpi.getFunctionKpiColumns();
				for (DefinedTypeInfoDTO c : functionKpiColumns) {
					columnIdSets.add(c.getColumnId());
				}
			} else {
				/**
				 * 定义或输入
				 */
				DefinedTypeInfoDTO definedTypeInfo = kpi.getDefinedTypeInfo();
				// 添加相关表和字段
				columnIdSets.add(definedTypeInfo.getColumnId());
			}
		}
		/**
		 * 涉及到的字段
		 */
		columnIds = new ArrayList<>(columnIdSets);
		/**
		 * KPI和字段的统一映射map
		 */
		Map<String, String> columnMap = new HashMap<>();
		List<KpiListColumnDTO> columnlist = mdmApi.listColumnByIds(columnIds);
		log.info("字段映射查询数量结果：{}", columnlist.size());
		for (int i = 0; i < columnlist.size(); i++) {
			columnMap.put(columnlist.get(i).getId(),
					columnlist.get(i).getTableName() + "." + columnlist.get(i).getColumnName());
			columnMap.put(columnlist.get(i).getTableId(), columnlist.get(i).getTableName());
		}
		// 定义sql条件
		ReportSqlDTO reportSqlDTO = null;
		// 最终sql
		String resultSqlStr = "";
		for (Integer reportType : reportTypes) {
			chartParameter = new ChartParameterDTO();
			// 1-保存为拼接sql查询条件：图表信息
			chartParameter.setChartInfoList(chartInfoList);
			// 6 保存为拼接sql查询条件：KPI字段的映射
			chartParameter.setColumnMap(columnMap);
			/**
			 * 循环类型，拼接table报表
			 */
			switch (reportType) {
			case 0:
				// 表格
				chartParameter.setReportType(reportType);
				chartParameter.setIdsGroupBy(idsGroupBy);
				// 汇总展示kpi
				List<String> totalKpis = reportMapper.listTotalKpis(reportId, 1);
				ReportDTO report = reportMapper.getReportById(reportId);
				if (totalKpis != null && totalKpis.size() != 0) {
					List<KpiConfigDTO> totalKpiConfigList = kpimApi.listKpiConfigByKpiIds(totalKpis);
					chartParameter.setTotalKpiConfigList(totalKpiConfigList);
				}
				// 汇总展示为1 下方，则展示所有数字字段信息
				if (report.getTotalShowType() != null && report.getTotalShowType() == 1) {
					chartParameter.setTotalKpiConfigList(kpiConfigList);
				}
				chartParameter.setKpiConfigList(kpiConfigList);
				reportSqlDTO = ReportDataServiceImplUtil.getReportSqlList(chartParameter);
				if (resultSqlStr.equals("-1")) {
					return new R<>(S.ERROR, "sql不允许跨库");
				}
				// 保存sql存储对象
				reportSqlDTO.setChartType(reportType);
				reportSqlDTO.setReportId(reportId);
				resultList.add(reportSqlDTO);
				break;

			case 1:
				// 柱折
				if (bolX == null) {
					return new R<>(S.ERROR, "未检测到X轴");
				}
				if (bolYList.size() == 0) {
					return new R<>(S.ERROR, "未检测到Y轴");
				}
				// 拆分出Y轴kpi配置信息
				List<KpiConfigDTO> yList = new ArrayList<>();
				for (KpiConfigDTO kpiConfig : kpiConfigList) {
					for (RpmInfoReportChartDTO bolY : bolYList) {
						if (kpiConfig.getId().equals(bolY.getKpiId())) {
							yList.add(kpiConfig);
						}
					}
				}
				// 以X轴group by
				List<String> xList = new ArrayList<>();
				xList.add(bolX.getKpiId());
				chartParameter.setReportType(reportType);
				chartParameter.setIdsGroupBy(xList);
				chartParameter.setKpiConfigList(yList);
				reportSqlDTO = ReportDataServiceImplUtil.getReportSqlList(chartParameter);
				if (resultSqlStr.equals("-1")) {
					return new R<>(S.ERROR, "sql不允许跨库");
				}
				// 保存sql存储对象
				reportSqlDTO.setChartType(reportType);
				reportSqlDTO.setReportId(reportId);
				resultList.add(reportSqlDTO);
				break;

			case 2:
				// 饼图
				if (pieList.size() == 0) {
					return new R<>(S.ERROR, "未检测到饼图数据");
				}
				// 拆分出饼图kpi配置信息
				List<KpiConfigDTO> pList = new ArrayList<>();
				for (KpiConfigDTO kpiConfig : kpiConfigList) {
					for (RpmInfoReportChartDTO pie : pieList) {
						if (kpiConfig.getId().equals(pie.getKpiId())) {
							pList.add(kpiConfig);
						}
					}
				}
				chartParameter.setReportType(reportType);
				chartParameter.setKpiConfigList(pList);
				reportSqlDTO = ReportDataServiceImplUtil.getReportSqlList(chartParameter);
				if (resultSqlStr.equals("-1")) {
					return new R<>(S.ERROR, "sql不允许跨库");
				}
				// 保存sql存储对象
				reportSqlDTO.setChartType(reportType);
				reportSqlDTO.setReportId(reportId);
				resultList.add(reportSqlDTO);
				break;

			default:
				break;
			}
		}

		/**
		 * 汇总结果集，入库
		 */
		int result = 0;
		try {
			result = reportMapper.saveReportSql(resultList);
		} catch (Exception e) {
			e.printStackTrace();
			return new R<>(S.ERROR);
		}

		if (result == 0) {
			return new R<>(S.ERROR, "sql插入失败");
		} else {
			return new R<>();
		}

	}

	@Override
	public R<String> saveChartSql(String id) {
		// TODO Auto-generated method stub
		return null;
	}
}
