package logic

import (
	"errors"
	"hongze/hongze_edb_lib/models"
	"hongze/hongze_edb_lib/utils"
	"strconv"
	"strings"
	"time"
)

// AddPredictEdbInfo 新增预测指标
func AddPredictEdbInfo(sourceEdbInfoId, classifyId int, edbName string, ruleList []models.RuleConfig, minValue, maxValue float64, sysUserId int, sysUserName string) (edbInfo *models.EdbInfo, err error, errMsg string) {
	var sourceEdbInfo *models.EdbInfo
	// 来源指标信息校验
	{
		sourceEdbInfo, err = models.GetEdbInfoById(sourceEdbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			errMsg = "新增失败"
			err = errors.New("获取来源指标失败,Err:" + err.Error())
			return
		}
		if sourceEdbInfo == nil {
			errMsg = "找不到该来源指标"
			err = errors.New(errMsg)
			return
		}
		//必须是普通的指标
		if sourceEdbInfo.EdbInfoType != 0 {
			errMsg = "来源指标异常,不是普通的指标"
			err = errors.New(errMsg)
			return
		}
		//if !utils.InArrayByStr([]string{"日度", "周度", "月度", "年度"}, sourceEdbInfo.Frequency) {
		//	errMsg = "预测指标只支持选择日度、周度、月度、年度的指标"
		//	err = errors.New(errMsg)
		//	return
		//}
	}

	var classifyInfo *models.EdbClassify
	// 来源分类信息校验
	{
		classifyInfo, err = models.GetEdbClassifyById(classifyId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			errMsg = "新增失败"
			err = errors.New("获取预测指标分类失败,Err:" + err.Error())
			return
		}
		if classifyInfo == nil {
			errMsg = "找不到该预测指标分类"
			err = errors.New(errMsg)
			return
		}
		//必须是预测指标分类
		if classifyInfo.ClassifyType != 1 {
			errMsg = "预测指标分类异常,不是预测指标分类"
			err = errors.New(errMsg)
			return
		}
	}

	edbName = strings.Trim(edbName, " ")

	edbCode := sourceEdbInfo.EdbCode + "_" + time.Now().Format(utils.FormatShortDateTimeUnSpace)

	//判断指标名称是否存在
	var condition string
	var pars []interface{}
	condition += " AND edb_info_type=? "
	pars = append(pars, 1)

	condition += " AND edb_name=? "
	pars = append(pars, edbName)

	count, err := models.GetEdbInfoCountByCondition(condition, pars)
	if err != nil {
		errMsg = "判断指标名称是否存在失败"
		err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
		return
	}
	if count > 0 {
		errMsg = "指标名称已存在,请重新填写"
		err = errors.New(errMsg)
		return
	}

	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
	edbInfo = &models.EdbInfo{
		//EdbInfoId:   0,
		EdbInfoType:      1,
		SourceName:       "预测指标",
		Source:           utils.DATA_SOURCE_PREDICT,
		EdbCode:          edbCode,
		EdbName:          edbName,
		EdbNameSource:    edbName,
		Frequency:        sourceEdbInfo.Frequency,
		Unit:             sourceEdbInfo.Unit,
		StartDate:        sourceEdbInfo.StartDate,
		ClassifyId:       classifyId,
		SysUserId:        sysUserId,
		SysUserRealName:  sysUserName,
		UniqueCode:       utils.MD5(utils.DATA_PREFIX + "_" + timestamp),
		CreateTime:       time.Now(),
		ModifyTime:       time.Now(),
		MinValue:         minValue,
		MaxValue:         maxValue,
		CalculateFormula: sourceEdbInfo.CalculateFormula,
		EdbType:          1,
		//Sort:             sourceEdbInfo.,
		LatestDate:    sourceEdbInfo.LatestDate,
		LatestValue:   sourceEdbInfo.LatestValue,
		MoveType:      sourceEdbInfo.MoveType,
		MoveFrequency: sourceEdbInfo.MoveFrequency,
		NoUpdate:      sourceEdbInfo.NoUpdate,
		ServerUrl:     "",
	}

	// 关联关系表
	calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0)
	fromEdbMap := make(map[int]int)

	// 源指标关联关系表
	calculateMappingItem := &models.EdbInfoCalculateMapping{
		//EdbInfoCalculateMappingId: 0,
		//EdbInfoId:                 0,
		Source:         edbInfo.Source,
		SourceName:     edbInfo.SourceName,
		EdbCode:        edbInfo.EdbCode,
		FromEdbInfoId:  sourceEdbInfo.EdbInfoId,
		FromEdbCode:    sourceEdbInfo.EdbCode,
		FromEdbName:    sourceEdbInfo.EdbName,
		FromSource:     sourceEdbInfo.Source,
		FromSourceName: sourceEdbInfo.SourceName,
		//FromTag:        "",
		Sort:       1,
		CreateTime: time.Now(),
		ModifyTime: time.Now(),
	}
	fromEdbMap[sourceEdbInfoId] = sourceEdbInfoId
	calculateMappingList = append(calculateMappingList, calculateMappingItem)

	// 动态环差 计算列表
	calculateRuleMap := make(map[int]models.CalculateRule, 0)

	// 预测指标配置
	predictEdbConfList := make([]*models.PredictEdbConf, 0)
	for ruleIndex, v := range ruleList {
		// 预测指标配置
		ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
		if tmpErr != nil {
			errMsg = "规则配置的截止日期异常,请重新填写"
			err = errors.New(errMsg)
			return
		}
		//1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,10:根据 给定终值后插值 规则获取预测数据,11:根据 季节性 规则获取预测数据,12:根据 移动平均同比 规则获取预测数据
		// 环比、环差、动态环差、季节性、移动平均同比不支持年度
		if sourceEdbInfo.Frequency == "年度" && utils.InArrayByInt([]int{5, 6, 11, 12}, v.RuleType) {
			errMsg = "环比、环差、动态环差、季节性、移动平均同比不支持年度指标"
			err = errors.New(errMsg)
			return
		}

		switch v.RuleType {
		case 8: //N期段线性外推值
			valInt, tmpErr := strconv.Atoi(v.Value)
			if tmpErr != nil {
				errMsg = "N期段线性外推值的N值异常"
				err = errors.New(errMsg)
				return
			}
			if valInt <= 1 {
				errMsg = "N期段线性外推值的N值必须大于1"
				err = errors.New(errMsg)
				return
			}
		case 9: //9:动态环差
			if v.Value == "" {
				errMsg = "请填写计算规则"
				err = errors.New(errMsg)
				return
			}
			formula := v.Value
			formula = strings.Replace(formula, "(", "(", -1)
			formula = strings.Replace(formula, ")", ")", -1)
			formula = strings.Replace(formula, ",", ",", -1)
			formula = strings.Replace(formula, "。", ".", -1)
			formula = strings.Replace(formula, "%", "*0.01", -1)
			v.Value = formula

			//检验公式
			var formulaStr string
			var edbInfoIdBytes []string
			for _, tmpEdbInfoId := range v.EdbInfoIdArr {
				formulaStr += tmpEdbInfoId.FromTag + ","
				edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
			}
			formulaMap := utils.CheckFormula(formula)
			for _, formula := range formulaMap {
				if !strings.Contains(formulaStr, formula) {
					errMsg = "公式错误,请重新填写"
					err = errors.New(errMsg)
					return
				}
			}

			//关联的指标信息
			edbInfoList := make([]*models.EdbInfo, 0)
			// 动态环差规则 关系表
			trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)

			for k, tmpEdbInfoId := range v.EdbInfoIdArr {
				fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
				if tmpErr != nil {
					err = tmpErr
					if err.Error() == utils.ErrNoRow() {
						errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
						err = errors.New(errMsg)
						return
					}
					errMsg = "获取指标失败:Err:" + err.Error()
					err = errors.New(errMsg)
					return
				}

				edbInfoList = append(edbInfoList, fromEdbInfo)

				//总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
				{
					if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
						fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
						calculateMappingItem := &models.EdbInfoCalculateMapping{
							EdbInfoCalculateMappingId: 0,
							EdbInfoId:                 0,
							Source:                    utils.DATA_SOURCE_CALCULATE,
							SourceName:                "指标运算",
							EdbCode:                   "",
							FromEdbInfoId:             fromEdbInfo.EdbInfoId,
							FromEdbCode:               fromEdbInfo.EdbCode,
							FromEdbName:               fromEdbInfo.EdbName,
							FromSource:                fromEdbInfo.Source,
							FromSourceName:            fromEdbInfo.SourceName,
							//FromTag:                   tmpEdbInfoId.FromTag,
							Sort:       k + 1,
							CreateTime: time.Now(),
							ModifyTime: time.Now(),
						}
						calculateMappingList = append(calculateMappingList, calculateMappingItem)
					}
				}
				// 动态环差规则 关系表
				tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
					//PredictEdbConfCalculateMappingId: 0,
					EdbInfoId:      0,
					ConfigId:       0,
					FromEdbInfoId:  fromEdbInfo.EdbInfoId,
					FromEdbCode:    fromEdbInfo.EdbCode,
					FromEdbName:    fromEdbInfo.EdbName,
					FromSource:     fromEdbInfo.Source,
					FromSourceName: fromEdbInfo.SourceName,
					FromTag:        tmpEdbInfoId.FromTag,
					Sort:           k + 1,
					CreateTime:     time.Now(),
					ModifyTime:     time.Now(),
				}
				trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
			}
			ok, _ := models.CheckFormula2(edbInfoList, formulaMap, formula, edbInfoIdBytes)
			if !ok {
				errMsg = "生成计算指标失败,请使用正确的计算公式"
				err = errors.New(errMsg)
				return
			}
			calculateRuleMap[ruleIndex] = models.CalculateRule{
				TrendsCalculateMappingList: trendsMappingList,
				EdbInfoList:                edbInfoList,
				EdbInfoIdBytes:             edbInfoIdBytes,
				Formula:                    formula,
				RuleType:                   v.RuleType,
				EndDate:                    v.EndDate,
				EdbInfoIdArr:               v.EdbInfoIdArr,
			}
		case 14: //14:根据 一元线性拟合 规则获取预测数据
			if v.Value == "" {
				errMsg = "请填写一元线性拟合规则"
				err = errors.New(errMsg)
				return
			}

			//关联的指标信息
			edbInfoList := make([]*models.EdbInfo, 0)
			// 动态环差规则 关系表
			trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)

			for k, tmpEdbInfoId := range v.EdbInfoIdArr {
				fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
				if tmpErr != nil {
					err = tmpErr
					if err.Error() == utils.ErrNoRow() {
						errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
						err = errors.New(errMsg)
						return
					}
					errMsg = "获取指标失败:Err:" + err.Error()
					err = errors.New(errMsg)
					return
				}

				edbInfoList = append(edbInfoList, fromEdbInfo)

				//总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
				{
					if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
						fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
						tmpCalculateMappingItem := &models.EdbInfoCalculateMapping{
							EdbInfoCalculateMappingId: 0,
							EdbInfoId:                 0,
							Source:                    utils.DATA_SOURCE_CALCULATE,
							SourceName:                "指标运算",
							EdbCode:                   "",
							FromEdbInfoId:             fromEdbInfo.EdbInfoId,
							FromEdbCode:               fromEdbInfo.EdbCode,
							FromEdbName:               fromEdbInfo.EdbName,
							FromSource:                fromEdbInfo.Source,
							FromSourceName:            fromEdbInfo.SourceName,
							//FromTag:                   tmpEdbInfoId.FromTag,
							Sort:       k + 1,
							CreateTime: time.Now(),
							ModifyTime: time.Now(),
						}
						calculateMappingList = append(calculateMappingList, tmpCalculateMappingItem)
					}
				}
				// 动态环差规则 关系表
				tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
					//PredictEdbConfCalculateMappingId: 0,
					EdbInfoId:      0,
					ConfigId:       0,
					FromEdbInfoId:  fromEdbInfo.EdbInfoId,
					FromEdbCode:    fromEdbInfo.EdbCode,
					FromEdbName:    fromEdbInfo.EdbName,
					FromSource:     fromEdbInfo.Source,
					FromSourceName: fromEdbInfo.SourceName,
					FromTag:        tmpEdbInfoId.FromTag,
					Sort:           k + 1,
					CreateTime:     time.Now(),
					ModifyTime:     time.Now(),
				}
				trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
			}

			calculateRuleMap[ruleIndex] = models.CalculateRule{
				TrendsCalculateMappingList: trendsMappingList,
				EdbInfoList:                edbInfoList,
				//EdbInfoIdBytes:             edbInfoIdBytes,
				//Formula:                    formula,
				RuleType:     v.RuleType,
				EndDate:      v.EndDate,
				EdbInfoIdArr: v.EdbInfoIdArr,
			}
		}

		tmpPredictEdbConf := &models.PredictEdbConf{
			PredictEdbInfoId: 0,
			SourceEdbInfoId:  sourceEdbInfoId,
			RuleType:         v.RuleType,
			//FixedValue:       v.Value,
			Value:      v.Value,
			EndDate:    ruleEndDate,
			ModifyTime: time.Now(),
			CreateTime: time.Now(),
		}

		edbInfo.EndDate = v.EndDate

		predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf)
	}
	err, errMsg = models.AddPredictEdb(edbInfo, calculateMappingList, predictEdbConfList, calculateRuleMap)

	return
}

// EditPredictEdbInfo 编辑预测指标
func EditPredictEdbInfo(edbInfoId, classifyId int, edbName string, ruleList []models.RuleConfig, minValue, maxValue float64) (edbInfo *models.EdbInfo, err error, errMsg string) {
	// 指标信息校验
	{
		edbInfo, err = models.GetEdbInfoById(edbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			errMsg = "修改失败"
			err = errors.New("获取预测指标失败,Err:" + err.Error())
			return
		}
		if edbInfo == nil {
			errMsg = "找不到该预测指标"
			err = errors.New(errMsg)
			return
		}
		//必须是普通的指标
		if edbInfo.EdbInfoType != 1 {
			errMsg = "指标异常,不是预测指标"
			err = errors.New(errMsg)
			return
		}
	}

	var predictEdbConf *models.PredictEdbConf
	// 指标配置信息校验
	{
		// 查找该预测指标配置
		predictEdbConfList, tmpErr := models.GetPredictEdbConfListById(edbInfo.EdbInfoId)
		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
			errMsg = "修改失败"
			err = errors.New("获取预测指标配置信息失败,Err:" + tmpErr.Error())
			return
		}
		if len(predictEdbConfList) == 0 {
			errMsg = "找不到该预测指标配置"
			err = errors.New(errMsg)
			return
		}
		predictEdbConf = predictEdbConfList[0]
	}

	//判断指标名称是否存在
	var condition string
	var pars []interface{}

	condition += " AND edb_info_id<>? "
	pars = append(pars, edbInfoId)

	condition += " AND edb_info_type=? "
	pars = append(pars, 1)

	condition += " AND edb_name=? "
	pars = append(pars, edbName)

	count, err := models.GetEdbInfoCountByCondition(condition, pars)
	if err != nil {
		errMsg = "判断指标名称是否存在失败"
		err = errors.New("判断指标名称是否存在失败,Err:" + err.Error())
		return
	}

	if count > 0 {
		errMsg = "指标名称已存在,请重新填写"
		err = errors.New(errMsg)
		return
	}

	edbInfo.EdbName = edbName
	edbInfo.EdbNameSource = edbName
	edbInfo.ClassifyId = classifyId
	edbInfo.MinValue = minValue
	edbInfo.MaxValue = maxValue
	edbInfo.ModifyTime = time.Now()
	updateEdbInfoCol := []string{"EdbName", "EdbNameSource", "ClassifyId", "EndDate", "MinValue", "MaxValue", "ModifyTime"}

	var sourceEdbInfo *models.EdbInfo
	// 来源指标信息校验
	{
		sourceEdbInfo, err = models.GetEdbInfoById(predictEdbConf.SourceEdbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			errMsg = "新增失败"
			err = errors.New("获取来源指标失败,Err:" + err.Error())
			return
		}
		if sourceEdbInfo == nil {
			errMsg = "找不到该来源指标"
			err = errors.New(errMsg)
			return
		}
		//必须是普通的指标
		if sourceEdbInfo.EdbInfoType != 0 {
			errMsg = "来源指标异常,不是普通的指标"
			err = errors.New(errMsg)
			return
		}
		//if !utils.InArrayByStr([]string{"日度", "周度", "月度", "年度"}, sourceEdbInfo.Frequency) {
		//	errMsg = "预测指标只支持选择日度、周度、月度、年度的指标"
		//	err = errors.New(errMsg)
		//	return
		//}
	}

	// 预测指标配置
	// 关联关系表
	calculateMappingList := make([]*models.EdbInfoCalculateMapping, 0)
	fromEdbMap := make(map[int]int)

	// 源指标关联关系表
	calculateMappingItem := &models.EdbInfoCalculateMapping{
		//EdbInfoCalculateMappingId: 0,
		EdbInfoId:      edbInfoId,
		Source:         edbInfo.Source,
		SourceName:     edbInfo.SourceName,
		EdbCode:        edbInfo.EdbCode,
		FromEdbInfoId:  sourceEdbInfo.EdbInfoId,
		FromEdbCode:    sourceEdbInfo.EdbCode,
		FromEdbName:    sourceEdbInfo.EdbName,
		FromSource:     sourceEdbInfo.Source,
		FromSourceName: sourceEdbInfo.SourceName,
		//FromTag:        "",
		Sort:       1,
		CreateTime: time.Now(),
		ModifyTime: time.Now(),
	}
	fromEdbMap[sourceEdbInfo.EdbInfoId] = sourceEdbInfo.EdbInfoId
	calculateMappingList = append(calculateMappingList, calculateMappingItem)

	// 动态环差 计算列表
	calculateRuleMap := make(map[int]models.CalculateRule, 0)

	// 预测指标配置
	predictEdbConfList := make([]*models.PredictEdbConf, 0)
	for ruleIndex, v := range ruleList {
		// 预测指标配置
		ruleEndDate, tmpErr := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
		if tmpErr != nil {
			errMsg = "规则配置的截止日期异常,请重新填写"
			err = errors.New(errMsg)
			return
		}
		//1:最新,2:固定值,3:同比,4:同差,5:环比,6:环差,7:N期移动均值,8:N期段线性外推值,9:动态环差,10:根据 给定终值后插值 规则获取预测数据,11:根据 季节性 规则获取预测数据,12:根据 移动平均同比 规则获取预测数据
		// 环比、环差、动态环差、季节性、移动平均同比不支持年度
		if sourceEdbInfo.Frequency == "年度" && utils.InArrayByInt([]int{5, 6, 11, 12}, v.RuleType) {
			errMsg = "环比、环差、动态环差、季节性、移动平均同比不支持年度指标"
			err = errors.New(errMsg)
			return
		}
		switch v.RuleType {
		case 8: //N期段线性外推值
			valInt, tmpErr := strconv.Atoi(v.Value)
			if tmpErr != nil {
				errMsg = "N期段线性外推值的N值异常"
				err = errors.New(errMsg)
				return
			}
			if valInt <= 1 {
				errMsg = "N期段线性外推值的N值必须大于1"
				err = errors.New(errMsg)
				return
			}
		case 9: //9:动态环差
			if v.Value == "" {
				errMsg = "请填写计算规则"
				err = errors.New(errMsg)
				return
			}
			formula := v.Value
			formula = strings.Replace(formula, "(", "(", -1)
			formula = strings.Replace(formula, ")", ")", -1)
			formula = strings.Replace(formula, ",", ",", -1)
			formula = strings.Replace(formula, "。", ".", -1)
			formula = strings.Replace(formula, "%", "*0.01", -1)
			v.Value = formula

			//检验公式
			var formulaStr string
			var edbInfoIdBytes []string
			for _, tmpEdbInfoId := range v.EdbInfoIdArr {
				formulaStr += tmpEdbInfoId.FromTag + ","
				edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
			}
			formulaMap := utils.CheckFormula(formula)
			for _, formula := range formulaMap {
				if !strings.Contains(formulaStr, formula) {
					errMsg = "公式错误,请重新填写"
					err = errors.New(errMsg)
					return
				}
			}

			//关联的指标信息
			edbInfoList := make([]*models.EdbInfo, 0)
			// 动态环差规则 关系表
			trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)

			for k, tmpEdbInfoId := range v.EdbInfoIdArr {
				fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
				if tmpErr != nil {
					err = tmpErr
					if err.Error() == utils.ErrNoRow() {
						errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
						err = errors.New(errMsg)
						return
					}
					errMsg = "获取指标失败:Err:" + err.Error()
					err = errors.New(errMsg)
					return
				}

				edbInfoList = append(edbInfoList, fromEdbInfo)

				//总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
				{
					if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
						fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
						calculateMappingItem := &models.EdbInfoCalculateMapping{
							EdbInfoCalculateMappingId: 0,
							EdbInfoId:                 edbInfoId,
							Source:                    utils.DATA_SOURCE_CALCULATE,
							SourceName:                "指标运算",
							EdbCode:                   "",
							FromEdbInfoId:             fromEdbInfo.EdbInfoId,
							FromEdbCode:               fromEdbInfo.EdbCode,
							FromEdbName:               fromEdbInfo.EdbName,
							FromSource:                fromEdbInfo.Source,
							FromSourceName:            fromEdbInfo.SourceName,
							//FromTag:                   tmpEdbInfoId.FromTag,
							Sort:       k + 1,
							CreateTime: time.Now(),
							ModifyTime: time.Now(),
						}
						calculateMappingList = append(calculateMappingList, calculateMappingItem)
					}
				}
				// 动态环差规则 关系表
				tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
					//PredictEdbConfCalculateMappingId: 0,
					EdbInfoId:      edbInfoId,
					ConfigId:       0,
					FromEdbInfoId:  fromEdbInfo.EdbInfoId,
					FromEdbCode:    fromEdbInfo.EdbCode,
					FromEdbName:    fromEdbInfo.EdbName,
					FromSource:     fromEdbInfo.Source,
					FromSourceName: fromEdbInfo.SourceName,
					FromTag:        tmpEdbInfoId.FromTag,
					Sort:           k + 1,
					CreateTime:     time.Now(),
					ModifyTime:     time.Now(),
				}
				trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
			}
			ok, _ := models.CheckFormula2(edbInfoList, formulaMap, formula, edbInfoIdBytes)
			if !ok {
				errMsg = "生成计算指标失败,请使用正确的计算公式"
				err = errors.New(errMsg)
				return
			}

			calculateRuleMap[ruleIndex] = models.CalculateRule{
				TrendsCalculateMappingList: trendsMappingList,
				EdbInfoList:                edbInfoList,
				EdbInfoIdBytes:             edbInfoIdBytes,
				Formula:                    formula,
				RuleType:                   v.RuleType,
				EndDate:                    v.EndDate,
				EdbInfoIdArr:               v.EdbInfoIdArr,
			}
		case 14: //14:根据 一元线性拟合 规则获取预测数据
			if v.Value == "" {
				errMsg = "请填写一元线性拟合规则"
				err = errors.New(errMsg)
				return
			}

			//关联的指标信息
			edbInfoList := make([]*models.EdbInfo, 0)
			// 动态环差规则 关系表
			trendsMappingList := make([]*models.PredictEdbConfCalculateMapping, 0)

			for k, tmpEdbInfoId := range v.EdbInfoIdArr {
				fromEdbInfo, tmpErr := models.GetEdbInfoById(tmpEdbInfoId.EdbInfoId)
				if tmpErr != nil {
					err = tmpErr
					if err.Error() == utils.ErrNoRow() {
						errMsg = "指标 " + strconv.Itoa(tmpEdbInfoId.EdbInfoId) + " 不存在"
						err = errors.New(errMsg)
						return
					}
					errMsg = "获取指标失败:Err:" + err.Error()
					err = errors.New(errMsg)
					return
				}

				edbInfoList = append(edbInfoList, fromEdbInfo)

				//总的 预测指标与所有相关联指标的关系表(不仅仅该条规则)
				{
					if _, ok := fromEdbMap[tmpEdbInfoId.EdbInfoId]; !ok {
						fromEdbMap[tmpEdbInfoId.EdbInfoId] = tmpEdbInfoId.EdbInfoId
						tmpCalculateMappingItem := &models.EdbInfoCalculateMapping{
							EdbInfoCalculateMappingId: 0,
							EdbInfoId:                 0,
							Source:                    utils.DATA_SOURCE_CALCULATE,
							SourceName:                "指标运算",
							EdbCode:                   "",
							FromEdbInfoId:             fromEdbInfo.EdbInfoId,
							FromEdbCode:               fromEdbInfo.EdbCode,
							FromEdbName:               fromEdbInfo.EdbName,
							FromSource:                fromEdbInfo.Source,
							FromSourceName:            fromEdbInfo.SourceName,
							//FromTag:                   tmpEdbInfoId.FromTag,
							Sort:       k + 1,
							CreateTime: time.Now(),
							ModifyTime: time.Now(),
						}
						calculateMappingList = append(calculateMappingList, tmpCalculateMappingItem)
					}
				}
				// 动态环差规则 关系表
				tmpPredictEdbConfCalculateMapping := &models.PredictEdbConfCalculateMapping{
					//PredictEdbConfCalculateMappingId: 0,
					EdbInfoId:      0,
					ConfigId:       0,
					FromEdbInfoId:  fromEdbInfo.EdbInfoId,
					FromEdbCode:    fromEdbInfo.EdbCode,
					FromEdbName:    fromEdbInfo.EdbName,
					FromSource:     fromEdbInfo.Source,
					FromSourceName: fromEdbInfo.SourceName,
					FromTag:        tmpEdbInfoId.FromTag,
					Sort:           k + 1,
					CreateTime:     time.Now(),
					ModifyTime:     time.Now(),
				}
				trendsMappingList = append(trendsMappingList, tmpPredictEdbConfCalculateMapping)
			}

			calculateRuleMap[ruleIndex] = models.CalculateRule{
				TrendsCalculateMappingList: trendsMappingList,
				EdbInfoList:                edbInfoList,
				//EdbInfoIdBytes:             edbInfoIdBytes,
				//Formula:                    formula,
				RuleType:     v.RuleType,
				EndDate:      v.EndDate,
				EdbInfoIdArr: v.EdbInfoIdArr,
			}
		}

		tmpPredictEdbConf := &models.PredictEdbConf{
			PredictEdbInfoId: edbInfoId,
			SourceEdbInfoId:  sourceEdbInfo.EdbInfoId,
			RuleType:         v.RuleType,
			//FixedValue:       v.Value,
			Value:      v.Value,
			EndDate:    ruleEndDate,
			ModifyTime: time.Now(),
			CreateTime: time.Now(),
		}

		edbInfo.EndDate = v.EndDate

		predictEdbConfList = append(predictEdbConfList, tmpPredictEdbConf)
	}

	err, errMsg = models.EditPredictEdb(edbInfo, updateEdbInfoCol, calculateMappingList, predictEdbConfList, calculateRuleMap)

	return
}

// RefreshPredictEdbInfo 更新基础预测指标规则中的动态数据
func RefreshPredictEdbInfo(edbInfoId int) (edbInfo *models.EdbInfo, err error, errMsg string) {
	// 指标信息校验
	{
		edbInfo, err = models.GetEdbInfoById(edbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			errMsg = "刷新失败"
			err = errors.New("获取预测指标失败,Err:" + err.Error())
			return
		}
		if edbInfo == nil {
			errMsg = "找不到该预测指标"
			err = nil
			return
		}
		//必须是普通的指标
		if edbInfo.EdbInfoType != 1 {
			errMsg = "指标异常,不是预测指标"
			return
		}
	}

	// 配置 与 指标的 关联关系表
	list, err := models.GetPredictEdbConfCalculateMappingListByEdbInfoId(edbInfoId)
	if err != nil {
		return
	}
	// 没有关联指标,不需要刷新
	if len(list) <= 0 {
		return
	}

	// 配置关联的指标信息
	predictEdbConfCalculateMappingListMap := make(map[int][]*models.PredictEdbConfCalculateMapping)
	configIdList := make([]int, 0)       //关联配置id
	edbInfoIdList := make([]int, 0)      //关联指标配置id
	edbInfoIdMap := make(map[int]int, 0) //关联指标配置map
	for _, v := range list {
		configList, ok := predictEdbConfCalculateMappingListMap[v.ConfigId]
		if !ok {
			configList = make([]*models.PredictEdbConfCalculateMapping, 0)
			configIdList = append(configIdList, v.ConfigId)
		}
		if _, ok := edbInfoIdMap[v.FromEdbInfoId]; !ok {
			edbInfoIdList = append(edbInfoIdList, v.FromEdbInfoId)
		}
		configList = append(configList, v)
		predictEdbConfCalculateMappingListMap[v.ConfigId] = configList
	}

	predictEdbConfList, err := models.GetPredictEdbConfListByConfigIdList(configIdList)
	if err != nil {
		errMsg = "刷新失败"
		err = errors.New("获取预测指标配置信息失败,Err:" + err.Error())
		return
	}
	if len(predictEdbConfList) == 0 {
		errMsg = "找不到该预测指标配置"
		err = nil
		return
	}

	// 指标信息
	edbInfoList, err := models.GetEdbInfoByIdList(edbInfoIdList)
	if err != nil {
		err = errors.New("获取关联指标失败,Err:" + err.Error())
		return
	}
	// 指标信息map
	edbInfoListMap := make(map[int]*models.EdbInfo)
	for _, v := range edbInfoList {
		edbInfoListMap[v.EdbInfoId] = v
	}

	predictEdbConfAndDataList := make([]*models.PredictEdbConfAndData, 0)
	// 刷新所有的规则
	for _, v := range predictEdbConfList {
		// 每次规则计算的时候,产生的临时数据
		resultDataList := make([]*models.EdbInfoSearchData, 0)

		switch v.RuleType {
		case 9: //动态环差值
			if v.Value == "" {
				errMsg = "请填写计算规则"
				return
			}
			formula := v.Value

			// 动态环差规则 关系表
			trendsMappingList := predictEdbConfCalculateMappingListMap[v.ConfigId]

			// 关联标签
			edbInfoIdArr := make([]models.EdbInfoFromTag, 0)

			//关联的指标信息
			edbInfoList := make([]*models.EdbInfo, 0)
			for _, trendsMapping := range trendsMappingList {
				tmpEdbInfo, ok := edbInfoListMap[trendsMapping.FromEdbInfoId]
				if ok {
					edbInfoList = append(edbInfoList, tmpEdbInfo)
				}

				// 关联标签
				edbInfoIdArr = append(edbInfoIdArr, models.EdbInfoFromTag{
					EdbInfoId: trendsMapping.FromEdbInfoId,
					FromTag:   trendsMapping.FromTag,
				})
			}

			//检验公式
			var formulaStr string
			var edbInfoIdBytes []string
			for _, tmpEdbInfoId := range edbInfoIdArr {
				formulaStr += tmpEdbInfoId.FromTag + ","
				edbInfoIdBytes = append(edbInfoIdBytes, tmpEdbInfoId.FromTag)
			}
			formulaMap := utils.CheckFormula(formula)
			for _, formula := range formulaMap {
				if !strings.Contains(formulaStr, formula) {
					errMsg = "公式错误,请重新填写"
					return
				}
			}

			ok, _ := models.CheckFormula2(edbInfoList, formulaMap, formula, edbInfoIdBytes)
			if !ok {
				errMsg = "生成计算指标失败,请使用正确的计算公式"
				return
			}

			rule := models.CalculateRule{
				EdbInfoId:                  v.PredictEdbInfoId,
				ConfigId:                   v.ConfigId,
				TrendsCalculateMappingList: trendsMappingList,
				EdbInfoList:                edbInfoList,
				EdbInfoIdBytes:             edbInfoIdBytes,
				Formula:                    formula,
				RuleType:                   v.RuleType,
				EndDate:                    v.EndDate.Format(utils.FormatDate),
				EdbInfoIdArr:               edbInfoIdArr,
			}
			resultDataList, err = models.RefreshCalculateByRuleBy9(rule)
			if err != nil {
				return
			}
		case 14: //14:根据 一元线性拟合 规则获取预测数据

			if v.Value == "" {
				errMsg = "一元线性拟合规则信息未配置"
				return
			}
			err, errMsg = models.RefreshCalculateByRuleByLineNh(*edbInfo, predictEdbConfAndDataList, *v)
			if err != nil {
				return
			}
		}

		// 规则配置(含数据)
		tmpPredictEdbConfAndData := &models.PredictEdbConfAndData{
			ConfigId:         0,
			PredictEdbInfoId: 0,
			SourceEdbInfoId:  v.SourceEdbInfoId,
			RuleType:         v.RuleType,
			FixedValue:       v.FixedValue,
			Value:            v.Value,
			EndDate:          v.EndDate,
			ModifyTime:       v.ModifyTime,
			CreateTime:       v.CreateTime,
			DataList:         resultDataList,
		}
		predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)

	}

	return
}