package data

import (
	"eta/eta_api/models/data_manage"
	excelModel "eta/eta_api/models/data_manage/excel"
	"eta/eta_api/models/fe_calendar"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/services/sandbox"
	"eta/eta_api/utils"
	"fmt"
	"strings"
	"time"
)

// SaveChartEdbInfoRelation 添加/编辑图表指标引用关联记录
func SaveChartEdbInfoRelation(edbInfoIds []int, chartInfo *data_manage.ChartInfo) (err error) {
	//更新指标刷新状态为启用
	err = saveEdbInfoRelation(edbInfoIds, chartInfo.ChartInfoId, utils.EDB_RELATION_CHART, chartInfo.Source, false)
	return
}

// saveEdbInfoRelation 添加/编辑图表指标引用关联记录
func saveEdbInfoRelation(edbInfoIds []int, objectId, objectType, objectSubType int, needPredict bool) (err error) {
	// 实现添加引用记录的逻辑
	if len(edbInfoIds) == 0 {
		return
	}
	defer func() {
		if err != nil {
			tips := "实现添加引用记录的逻辑-添加/编辑图表指标引用关联记录失败, ErrMsg:\n" + err.Error()
			utils.FileLog.Info(tips)
			go alarm_msg.SendAlarmMsg(tips, 3)
		}
	}()
	refreshIds := make([]int, 0)
	indexCodeList := make([]string, 0)
	// 查询指标信息
	edbInfoListTmp, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
	if e != nil {
		err = fmt.Errorf("查询指标信息失败,%s", e.Error())
		return
	}
	// 过滤预测指标
	edbInfoList := make([]*data_manage.EdbInfo, 0)
	for _, v := range edbInfoListTmp {
		if v.EdbInfoType == 0 || (v.EdbType == 1 && v.EdbInfoType == 1 && needPredict) {
			edbInfoList = append(edbInfoList, v)
		}
	}
	// 查询计算指标信息,并且建立关联关系
	// 查询间接引用的指标信息
	calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList, needPredict)
	if e != nil {
		err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
		return
	}
	// 只统计上海钢联和wind来源的指标
	for _, edbInfo := range edbInfoList {
		/*if edbInfo.Source != utils.DATA_SOURCE_WIND && edbInfo.Source != utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			continue
		}*/
		refreshIds = append(refreshIds, edbInfo.EdbInfoId)
		if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			indexCodeList = append(indexCodeList, edbInfo.EdbCode)
		}
	}
	// 循转组装引用
	// 查询已有的引用关系
	existList, e := data_manage.GetEdbInfoRelationByReferObjectId(objectId, objectType)
	if e != nil {
		err = fmt.Errorf("查询已有的引用关系失败,%s", e.Error())
		return
	}
	deleteMap := make(map[int]bool)
	relationMap := make(map[int]bool)
	for _, exist := range existList {
		deleteMap[exist.EdbInfoId] = true
		relationMap[exist.EdbInfoId] = true
	}
	// 新增不存在的引用关系
	// 删除不再需要的引用关系
	nowTime := time.Now()
	addList := make([]*data_manage.EdbInfoRelation, 0)
	deleteEdbInfoIds := make([]int, 0)
	for _, edbInfo := range edbInfoList {
		/*if edbInfo.Source != utils.DATA_SOURCE_WIND && edbInfo.Source != utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			continue
		}*/
		if _, ok := relationMap[edbInfo.EdbInfoId]; ok {
			delete(deleteMap, edbInfo.EdbInfoId)
		} else {
			tmp := &data_manage.EdbInfoRelation{
				ReferObjectId:      objectId,
				ReferObjectType:    objectType,
				ReferObjectSubType: objectSubType,
				EdbInfoId:          edbInfo.EdbInfoId,
				EdbName:            edbInfo.EdbName,
				Source:             edbInfo.Source,
				EdbCode:            edbInfo.EdbCode,
				CreateTime:         nowTime,
				ModifyTime:         nowTime,
				RelationTime:       nowTime,
			}
			tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
			addList = append(addList, tmp)
			if (edbInfo.EdbType == 2 && edbInfo.EdbInfoType == 0) || (edbInfo.EdbType == 1 && edbInfo.EdbInfoType == 1 && needPredict) {
				childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
				if !ok1 {
					continue
				}
				for _, childEdbMappingId := range childEdbMappingIds {
					childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
					if !ok2 {
						continue
					}

					if childEdbMapping.FromSource == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
						indexCodeList = append(indexCodeList, childEdbMapping.FromEdbCode)
					}
					tmp1 := &data_manage.EdbInfoRelation{
						ReferObjectId:      objectId,
						ReferObjectType:    objectType,
						ReferObjectSubType: objectSubType,
						EdbInfoId:          childEdbMapping.FromEdbInfoId,
						EdbName:            childEdbMapping.FromEdbName,
						Source:             childEdbMapping.FromSource,
						EdbCode:            childEdbMapping.FromEdbCode,
						CreateTime:         nowTime,
						ModifyTime:         nowTime,
						RelationTime:       nowTime,
						RelationType:       1,
						RootEdbInfoId:      edbInfo.EdbInfoId,
						ChildEdbInfoId:     childEdbMapping.EdbInfoId,
						RelationCode:       tmp.RelationCode,
					}
					addList = append(addList, tmp1)
					refreshIds = append(refreshIds, childEdbMapping.FromEdbInfoId)
					// todo 防止重复
				}
			}

		}
	}

	// 删除不再需要的引用关系
	for deleteId, _ := range deleteMap {
		deleteEdbInfoIds = append(deleteEdbInfoIds, deleteId)
	}
	//更新指标刷新状态为启用
	err = data_manage.AddOrUpdateEdbInfoRelation(objectId, objectType, addList, deleteEdbInfoIds, refreshIds, indexCodeList)
	if err != nil {
		err = fmt.Errorf("删除不再需要的引用关系失败,%s", err.Error())
		return
	}
	return
}

// SaveSandBoxEdbInfoRelation 添加/编辑 eta逻辑图指标引用
func SaveSandBoxEdbInfoRelation(sandBoxId int, sandBoxContent string) (err error) {
	edbInfoIds, err := sandbox.GetSandBoxEdbIdsByContent(sandBoxContent)
	if err != nil {
		return
	}
	if len(edbInfoIds) == 0 {
		return
	}
	//更新指标刷新状态为启用
	err = saveEdbInfoRelation(edbInfoIds, sandBoxId, utils.EDB_RELATION_SANDBOX, 0, false)
	return
}

// SaveCalendarEdbInfoRelation 添加/编辑 事件日历指标引用
func SaveCalendarEdbInfoRelation(chartPermissionId int, matterDate string, editMatters, removeMatters []*fe_calendar.FeCalendarMatter) (err error) {
	defer func() {
		if err != nil {
			err = fmt.Errorf("添加/编辑 事件日历指标引用失败,%s", err.Error())
			go alarm_msg.SendAlarmMsg(err.Error(), 3)
		}
	}()
	//整理相关的事件ID
	matterIds := make([]int, 0)
	updateMatterMap := make(map[int]*fe_calendar.FeCalendarMatter)
	deleteMatterMap := make(map[int]struct{})
	for _, matter := range removeMatters {
		deleteMatterMap[matter.FeCalendarMatterId] = struct{}{}
		matterIds = append(matterIds, matter.FeCalendarMatterId)
	}
	for _, matter := range editMatters {
		updateMatterMap[matter.FeCalendarMatterId] = matter
		matterIds = append(matterIds, matter.FeCalendarMatterId)
	}

	//删除ID,先删除
	deleteObjectIds := make([]int, 0)
	if len(matterIds) > 0 {
		relationList, e := data_manage.GetEdbInfoRelationAllByReferObjectIds(matterIds, utils.EDB_RELATION_CALENDAR)
		if e != nil {
			err = fmt.Errorf("查询事件日历指标引用失败,%s", e.Error())
			return
		}
		for _, relation := range relationList {
			if _, ok := deleteMatterMap[relation.ReferObjectId]; ok {
				deleteObjectIds = append(deleteObjectIds, relation.ReferObjectId)
			}
			if newMatter, ok := updateMatterMap[relation.ReferObjectId]; ok {
				if relation.EdbInfoId != newMatter.EdbInfoId {
					deleteObjectIds = append(deleteObjectIds, relation.ReferObjectId)
				}
			}
		}
	}
	if len(deleteObjectIds) > 0 {
		err = data_manage.DeleteEdbRelationByObjectIds(deleteObjectIds, utils.EDB_RELATION_CALENDAR)
		if err != nil {
			err = fmt.Errorf("删除事件日历指标引用失败,%s", err.Error())
			return
		}
	}

	// 获取已有事项
	matterOb := new(fe_calendar.FeCalendarMatter)
	cond := fmt.Sprintf(` AND %s = ? AND %s = ?`, fe_calendar.FeCalendarMatterCols.ChartPermissionId, fe_calendar.FeCalendarMatterCols.MatterDate)
	pars := make([]interface{}, 0)
	pars = append(pars, chartPermissionId, matterDate)
	order := fmt.Sprintf(`%s ASC`, fe_calendar.FeCalendarMatterCols.Sort)
	matters, e := matterOb.GetItemsByCondition(cond, pars, []string{}, order)
	if e != nil {
		err = fmt.Errorf("查询事件日历事项失败,%s", e.Error())
		return
	}
	// 循环查询matters
	edbInfoIds := make([]int, 0)
	refreshIds := make([]int, 0)
	indexCodeList := make([]string, 0)

	newMatterIds := make([]int, 0)
	for _, matter := range matters {
		newMatterIds = append(newMatterIds, matter.FeCalendarMatterId)
		edbInfoIds = append(edbInfoIds, matter.EdbInfoId)
	}

	// 查询指标信息
	edbInfoListTmp, e := data_manage.GetEdbInfoByIdList(edbInfoIds)
	if e != nil {
		err = fmt.Errorf("查询指标信息失败,%s", e.Error())
		return
	}
	// 过滤预测指标
	edbInfoList := make([]*data_manage.EdbInfo, 0)
	for _, v := range edbInfoListTmp {
		if v.EdbInfoType == 0 {
			edbInfoList = append(edbInfoList, v)
		}
	}
	// 查询计算指标信息,并且建立关联关系
	// 查询间接引用的指标信息
	calculateEdbMappingListMap, calculateEdbMappingIdsMap, e := GetEdbListByEdbInfoId(edbInfoList, false)
	if e != nil {
		err = fmt.Errorf("查询计算指标信息失败,%s", e.Error())
		return
	}
	addEdbInfoIdMap := make(map[int]*data_manage.EdbInfo)
	for _, edbInfo := range edbInfoList {
		/*if edbInfo.Source != utils.DATA_SOURCE_WIND && edbInfo.Source != utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			continue
		}*/
		refreshIds = append(refreshIds, edbInfo.EdbInfoId)
		addEdbInfoIdMap[edbInfo.EdbInfoId] = edbInfo
		if edbInfo.Source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			indexCodeList = append(indexCodeList, edbInfo.EdbCode)
		}
	}

	relationMap := make(map[int]struct{})
	if len(newMatterIds) > 0 {
		//查询已有的matters
		relationList, e := data_manage.GetEdbInfoRelationByReferObjectIds(newMatterIds, utils.EDB_RELATION_CALENDAR)
		if e != nil {
			err = fmt.Errorf("查询事件日历指标引用失败,%s", e.Error())
			return
		}
		for _, relation := range relationList {
			relationMap[relation.ReferObjectId] = struct{}{}
		}
	}
	addList := make([]*data_manage.EdbInfoRelation, 0)
	nowTime := time.Now()
	for _, matter := range matters {
		_, ok1 := relationMap[matter.FeCalendarMatterId]
		edbInfo, ok2 := addEdbInfoIdMap[matter.EdbInfoId]
		if !ok1 && ok2 {
			tmp := &data_manage.EdbInfoRelation{
				ReferObjectId:      matter.FeCalendarMatterId,
				ReferObjectType:    utils.EDB_RELATION_CALENDAR,
				ReferObjectSubType: 0,
				EdbInfoId:          edbInfo.EdbInfoId,
				EdbName:            edbInfo.EdbName,
				Source:             edbInfo.Source,
				EdbCode:            edbInfo.EdbCode,
				CreateTime:         nowTime,
				ModifyTime:         nowTime,
				RelationTime:       matter.CreateTime,
			}
			tmp.RelationCode = fmt.Sprintf("%d_%d_%d_%d", tmp.EdbInfoId, tmp.ReferObjectId, tmp.ReferObjectType, tmp.ReferObjectSubType)
			addList = append(addList, tmp)
			//添加指标间接引用
			if edbInfo.EdbType == 2 && edbInfo.EdbInfoType == 0 {
				childEdbMappingIds, ok1 := calculateEdbMappingIdsMap[edbInfo.EdbInfoId]
				if !ok1 {
					continue
				}
				for _, childEdbMappingId := range childEdbMappingIds {
					childEdbMapping, ok2 := calculateEdbMappingListMap[childEdbMappingId]
					if !ok2 {
						continue
					}
					if childEdbMapping.FromSource == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
						indexCodeList = append(indexCodeList, childEdbMapping.FromEdbCode)
					}
					tmp1 := &data_manage.EdbInfoRelation{
						ReferObjectId:      matter.FeCalendarMatterId,
						ReferObjectType:    utils.EDB_RELATION_CALENDAR,
						ReferObjectSubType: 0,
						EdbInfoId:          childEdbMapping.FromEdbInfoId,
						EdbName:            childEdbMapping.FromEdbName,
						Source:             childEdbMapping.FromSource,
						EdbCode:            childEdbMapping.FromEdbCode,
						CreateTime:         nowTime,
						ModifyTime:         nowTime,
						RelationTime:       nowTime,
						RelationType:       1,
						RootEdbInfoId:      edbInfo.EdbInfoId,
						ChildEdbInfoId:     childEdbMapping.EdbInfoId,
						RelationCode:       tmp.RelationCode,
					}
					addList = append(addList, tmp1)
					refreshIds = append(refreshIds, childEdbMapping.FromEdbInfoId)
					// todo 防止重复
				}
			}
		}
	}
	//更新指标刷新状态为启用
	err = data_manage.AddOrUpdateEdbInfoRelationMulti(addList, refreshIds, indexCodeList)
	if err != nil {
		err = fmt.Errorf("添加指标引用,%s", err.Error())
		return
	}
	return
}

// GetEdbRelationList 获取指标引用列表
func GetEdbRelationList(source, edbType int, classifyId, sysUserId, frequency, keyword, status string, startSize, pageSize int, sortParam, sortType string) (total int, list []*data_manage.BaseRelationEdbInfo, err error) {
	var pars []interface{}
	var condition string

	list = make([]*data_manage.BaseRelationEdbInfo, 0)

	isStop := -1
	switch status {
	case `暂停`:
		isStop = 1
	case `启用`:
		isStop = 0
	case `供应商停用`:
		isStop = 3
	}

	// 关联表语句
	var addFieldStr, joinTableStr string

	switch source {
	case 0: // 计算指标,不校验source
	default:
		condition += ` AND e.source = ? `
		pars = append(pars, source)
	}

	if edbType == 2 { //计算指标
		condition += ` AND e.edb_type = ? AND e.edb_info_type = 0`
		pars = append(pars, edbType)
	}
	switch isStop {
	case -1:
		// 供应商停用
		if source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			joinTableStr = ` LEFT JOIN base_from_mysteel_chemical_index z ON e.edb_code = z.index_code `
			addFieldStr = ` ,z.is_supplier_stop `
		}
	case 0, 1:
		condition += " AND e.no_update = ? "
		pars = append(pars, isStop)

		// 供应商停用
		if source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			condition += " AND z.is_supplier_stop = ? "
			pars = append(pars, 0)
			joinTableStr = ` LEFT JOIN base_from_mysteel_chemical_index z ON e.edb_code = z.index_code `
			addFieldStr = ` ,z.is_supplier_stop `
		}
	case 3:
		// 供应商停用
		if source == utils.DATA_SOURCE_MYSTEEL_CHEMICAL {
			condition += " AND z.is_supplier_stop = ? "
			pars = append(pars, 1)
			joinTableStr = ` LEFT JOIN base_from_mysteel_chemical_index z ON e.edb_code = z.index_code `
			addFieldStr = ` ,z.is_supplier_stop `
		}
	}

	if classifyId != `` {
		classifyIdSlice := strings.Split(classifyId, ",")
		condition += ` AND e.classify_id IN (` + utils.GetOrmInReplace(len(classifyIdSlice)) + `)`
		pars = append(pars, classifyIdSlice)
	}
	if sysUserId != `` {
		sysUserIdSlice := strings.Split(sysUserId, ",")
		condition += ` AND e.sys_user_id IN (` + utils.GetOrmInReplace(len(sysUserIdSlice)) + `)`
		pars = append(pars, sysUserIdSlice)
	}
	if frequency != `` {
		frequencySlice := strings.Split(frequency, ",")
		condition += ` AND e.frequency IN (` + utils.GetOrmInReplace(len(frequencySlice)) + `)`
		pars = append(pars, frequencySlice)
	}
	if keyword != `` {
		keywordSlice := strings.Split(keyword, " ")
		if len(keywordSlice) > 0 {
			tmpConditionSlice := make([]string, 0)
			tmpConditionSlice = append(tmpConditionSlice, ` e.edb_name like ? or e.edb_code like ? `)
			pars = utils.GetLikeKeywordPars(pars, keyword, 2)

			for _, v := range keywordSlice {
				if v == ` ` || v == `` {
					continue
				}
				tmpConditionSlice = append(tmpConditionSlice, ` e.edb_name like ? or e.edb_code like ? `)
				pars = utils.GetLikeKeywordPars(pars, v, 2)
			}
			condition += ` AND (` + strings.Join(tmpConditionSlice, " or ") + `)`

		} else {
			condition += ` AND (e.edb_name like ? or e.edb_code like ? )`
			pars = utils.GetLikeKeywordPars(pars, keyword, 2)
		}
	}

	sortStr := ``
	if sortParam != `` {
		sortStr = fmt.Sprintf("%s %s,e.edb_info_id desc ", sortParam, sortType)
	}

	total, list, err = data_manage.GetEdbInfoRelationList(condition, pars, addFieldStr, joinTableStr, sortStr, startSize, pageSize)

	return
}

// 查找当前计算指标的所有溯源指标
func GetEdbListByEdbInfoId(edbInfoList []*data_manage.EdbInfo, needPredict bool) (edbMappingListMap map[int]*data_manage.EdbInfoCalculateMapping, edbInfoMappingRootIdsMap map[int][]int, err error) {
	if len(edbInfoList) == 0 {
		return
	}
	edbInfoIds := make([]int, 0)
	for _, v := range edbInfoList {
		if (v.EdbType == 2 && v.EdbInfoType == 0) || (v.EdbType == 1 && v.EdbInfoType == 1 && needPredict) { //普通计算指标,或者是基础预测指标
			edbInfoIds = append(edbInfoIds, v.EdbInfoId)
		}
	}
	if len(edbInfoIds) == 0 {
		return
	}
	//查询指标信息
	allEdbMappingMap := make(map[int][]*data_manage.EdbInfoCalculateMappingInfo, 0)
	allMappingList, e := data_manage.GetEdbInfoCalculateMappingListByEdbInfoIds(edbInfoIds)
	if e != nil {
		err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoIds err: %s", e.Error())
		return
	}
	for _, v := range allMappingList {
		if _, ok := allEdbMappingMap[v.EdbInfoId]; !ok {
			allEdbMappingMap[v.EdbInfoId] = make([]*data_manage.EdbInfoCalculateMappingInfo, 0)
		}
		allEdbMappingMap[v.EdbInfoId] = append(allEdbMappingMap[v.EdbInfoId], v)
	}
	//查询指标映射
	//查询所有指标数据
	//查询这个指标相关的mapping信息放到数组里,
	//将得到的指标ID信息放到数组里
	hasFindMap := make(map[int]struct{})
	edbInfoIdMap := make(map[int]struct{})
	edbMappingList := make([]*data_manage.EdbInfoCalculateMapping, 0)
	edbInfoMappingRootIdsMap = make(map[int][]int, 0)
	edbMappingMap := make(map[int]struct{})
	for _, edbInfo := range edbInfoList {
		if (edbInfo.EdbType == 2 && edbInfo.EdbInfoType == 0) || (edbInfo.EdbType == 1 && edbInfo.EdbInfoType == 1 && needPredict) {
			edbInfoId := edbInfo.EdbInfoId
			edbMappingList, err = getCalculateEdbInfoByEdbInfoId(allEdbMappingMap, edbInfoId, hasFindMap, edbInfoIdMap, edbMappingList, edbMappingMap, edbInfoMappingRootIdsMap, edbInfoId)
			if err != nil {
				err = fmt.Errorf(" GetCalculateEdbInfoByEdbInfoId err: %s", err.Error())
				return
			}
		}
	}
	if len(edbMappingList) == 0 {
		return
	}
	// 查询指标信息
	// 指标信息map
	edbInfoIdList := make([]int, 0)
	for k, _ := range edbInfoIdMap {
		edbInfoIdList = append(edbInfoIdList, k)
	}
	edbMappingListMap = make(map[int]*data_manage.EdbInfoCalculateMapping)

	if len(edbMappingList) > 0 {
		for _, v := range edbMappingList {
			edbMappingListMap[v.EdbInfoCalculateMappingId] = v
		}
	}
	return
}

// getCalculateEdbInfoByEdbInfoId 计算指标追溯
func getCalculateEdbInfoByEdbInfoId(allEdbMappingMap map[int][]*data_manage.EdbInfoCalculateMappingInfo, edbInfoId int, hasFindMap map[int]struct{}, edbInfoIdMap map[int]struct{}, edbMappingList []*data_manage.EdbInfoCalculateMapping, edbMappingMap map[int]struct{}, edbInfoMappingRootIdsMap map[int][]int, rootEdbInfoId int) (newEdbMappingList []*data_manage.EdbInfoCalculateMapping, err error) {
	newEdbMappingList = edbMappingList
	_, ok := hasFindMap[edbInfoId]
	if ok {
		return
	}

	if _, ok1 := edbInfoIdMap[edbInfoId]; !ok1 {
		edbInfoIdMap[edbInfoId] = struct{}{}
	}
	edbInfoMappingList := make([]*data_manage.EdbInfoCalculateMappingInfo, 0)
	edbInfoMappingList, ok = allEdbMappingMap[edbInfoId]
	if !ok {
		edbInfoMappingList, err = data_manage.GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoId)
		if err != nil {
			err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoId err: %s", err.Error())
			return
		}
	}
	hasFindMap[edbInfoId] = struct{}{}
	if len(edbInfoMappingList) > 0 {
		fromEdbInfoIdList := make([]int, 0)
		edbInfoMappingIdList := make([]int, 0)
		for _, v := range edbInfoMappingList {
			fromEdbInfoIdList = append(fromEdbInfoIdList, v.FromEdbInfoId)
			edbInfoMappingIdList = append(edbInfoMappingIdList, v.EdbInfoCalculateMappingId)
			if _, ok1 := edbInfoIdMap[v.FromEdbInfoId]; !ok1 {
				edbInfoIdMap[v.FromEdbInfoId] = struct{}{}
			}
			if _, ok2 := edbMappingMap[v.EdbInfoCalculateMappingId]; !ok2 {
				edbMappingMap[v.EdbInfoCalculateMappingId] = struct{}{}
				tmp := &data_manage.EdbInfoCalculateMapping{
					EdbInfoCalculateMappingId: v.EdbInfoCalculateMappingId,
					EdbInfoId:                 v.EdbInfoId,
					Source:                    v.Source,
					SourceName:                v.SourceName,
					EdbCode:                   v.EdbCode,
					FromEdbInfoId:             v.FromEdbInfoId,
					FromEdbCode:               v.FromEdbCode,
					FromEdbName:               v.FromEdbName,
					FromSource:                v.FromSource,
					FromSourceName:            v.FromSourceName,
					FromTag:                   v.FromTag,
					Sort:                      v.Sort,
					CreateTime:                v.CreateTime,
					ModifyTime:                v.ModifyTime,
				}
				newEdbMappingList = append(newEdbMappingList, tmp)

			}

			if edbInfoId != v.FromEdbInfoId && (v.FromEdbType == 2 || v.FromEdbInfoType == 1) {
				// 查过了就不查了
				if _, ok2 := hasFindMap[v.FromEdbInfoId]; !ok2 {
					newEdbMappingList, err = getCalculateEdbInfoByEdbInfoId(allEdbMappingMap, v.FromEdbInfoId, hasFindMap, edbInfoIdMap, newEdbMappingList, edbMappingMap, edbInfoMappingRootIdsMap, rootEdbInfoId)
					if err != nil {
						err = fmt.Errorf("traceEdbInfoByEdbInfoId err: %s", err.Error())
						return
					}
				}
			}
			hasFindMap[v.FromEdbInfoId] = struct{}{}
		}
		edbInfoMappingRootIdsMap[rootEdbInfoId] = append(edbInfoMappingRootIdsMap[rootEdbInfoId], edbInfoMappingIdList...)
	}

	return
}

// SaveExcelEdbInfoRelation 添加/编辑表格时同步修改指标引用关联记录
func SaveExcelEdbInfoRelation(excelInfoId, source int, addChildExcel bool) (err error) {
	defer func() {
		if err != nil {
			err = fmt.Errorf("添加/编辑表格时同步修改指标引用关联记录失败,%s", err.Error())
			go alarm_msg.SendAlarmMsg(err.Error(), 3)
		}
	}()
	//查询和指标相关的时间序列表格和混合表格
	if !utils.InArrayByInt([]int{utils.TIME_TABLE, utils.MIXED_TABLE, utils.BALANCE_TABLE}, source) {
		return
	}
	if addChildExcel && source == utils.BALANCE_TABLE {
		//查询excel信息,
		excelInfoList, e := excelModel.GetChildExcelInfoByParentId(excelInfoId)
		if e != nil {
			err = fmt.Errorf("查询excel信息失败,错误:%s", e.Error())
			return
		}

		//查询
		if len(excelInfoList) > 0 {
			//汇总表格ID
			excelIds := make([]int, 0)
			for _, v := range excelInfoList {
				if v.BalanceType == 0 {
					excelIds = append(excelIds, v.ExcelInfoId)
				}
			}
			mappingList, e := excelModel.GetAllExcelEdbMappingByExcelInfoIds(excelIds)
			if e != nil {
				err = fmt.Errorf("查询和指标相关的表格失败,错误:%s", e.Error())
				return
			}
			//整理map
			mappingMap := make(map[int][]int)
			for _, v := range mappingList {
				mappingMap[v.ExcelInfoId] = append(mappingMap[v.ExcelInfoId], v.EdbInfoId)
			}

			// 添加指标引用
			for _, v := range excelInfoList {
				edbInfoIds, ok := mappingMap[v.ExcelInfoId]
				if !ok {
					continue
				}
				err = saveEdbInfoRelation(edbInfoIds, v.ExcelInfoId, utils.EDB_RELATION_TABLE, source, false)
			}
			//更新
		}
	}
	mappingList, err := excelModel.GetAllExcelEdbMappingByExcelInfoId(excelInfoId)
	if err != nil {
		err = fmt.Errorf("查询和指标相关的表格失败,错误:%s", err.Error())
		return
	}
	//查询指标ID
	edbInfoIds := make([]int, 0)
	for _, v := range mappingList {
		edbInfoIds = append(edbInfoIds, v.EdbInfoId)
	}
	//查询指标引用关联记录
	//更新指标刷新状态为启用
	if len(edbInfoIds) == 0 {
		return
	}
	err = saveEdbInfoRelation(edbInfoIds, excelInfoId, utils.EDB_RELATION_TABLE, source, false)
	return
}

// SavePredictEdbInfoRelation 添加/编辑预测指标引用关联记录
func SavePredictEdbInfoRelation(edbInfoIds []int, edbInfoId int) (err error) {
	//更新指标刷新状态为启用
	err = saveEdbInfoRelation(edbInfoIds, edbInfoId, utils.EDB_RELATION_PREDICT_EDB, 1, true)
	return
}

// GetCalculateEdbByFromEdbInfo 找到依赖于该基础指标的所有计算指标
func GetCalculateEdbByFromEdbInfo(edbInfoIds []int, calculateEdbIds []int, hasFind map[int]struct{}) (newCalculateEdbIds []int, err error) {
	if len(edbInfoIds) == 0 {
		return
	}
	newCalculateEdbIds = calculateEdbIds
	newEdbInfoIds := make([]int, 0)
	for _, v := range edbInfoIds {
		if _, ok := hasFind[v]; ok {
			continue
		}
		newEdbInfoIds = append(newEdbInfoIds, v)
	}
	if len(newEdbInfoIds) == 0 {
		return
	}
	var condition string
	var pars []interface{}
	// 关联指标
	condition += ` AND b.from_edb_info_id in (` + utils.GetOrmInReplace(len(newEdbInfoIds)) + `)`
	pars = append(pars, newEdbInfoIds)

	//获取关联图表列表
	list, err := data_manage.GetRelationEdbInfoListMappingByCondition(condition, pars)
	if err != nil && err.Error() != utils.ErrNoRow() {
		err = fmt.Errorf("获取关联指标信息失败,Err:%s", err.Error())
		return
	}
	calculateEdbIdsTmp := make([]int, 0)
	for _, mapping := range list {
		if mapping.EdbType == 2 && mapping.EdbInfoType == 0 { // 如果指标库里的计算指标,则加入,否则继续找
			newCalculateEdbIds = append(newCalculateEdbIds, mapping.EdbInfoId)
			calculateEdbIdsTmp = append(calculateEdbIdsTmp, mapping.EdbInfoId)
		}
	}
	for _, v := range newEdbInfoIds {
		hasFind[v] = struct{}{}
	}
	if len(calculateEdbIdsTmp) > 0 {
		newCalculateEdbIds, err = GetCalculateEdbByFromEdbInfo(calculateEdbIdsTmp, newCalculateEdbIds, hasFind)
		if err != nil {
			return
		}
	}

	return
}

// 查询两个指标是否存在循环引用关系
func CheckTwoEdbInfoRelation(edbInfoA, edbInfoB *data_manage.EdbInfo) (hasRelation bool, err error) {
	//查询指标信息
	allEdbMappingMap := make(map[int][]*data_manage.EdbInfoCalculateMappingInfo, 0)
	allMappingList, e := data_manage.GetEdbInfoCalculateMappingListByEdbInfoId(edbInfoA.EdbInfoId)
	if e != nil {
		err = fmt.Errorf("GetEdbInfoCalculateMappingListByEdbInfoIds err: %s", e.Error())
		return
	}
	for _, v := range allMappingList {
		if v.EdbInfoId == edbInfoB.EdbInfoId {
			hasRelation = true
			return
		}
		if _, ok := allEdbMappingMap[v.EdbInfoId]; !ok {
			allEdbMappingMap[v.EdbInfoId] = make([]*data_manage.EdbInfoCalculateMappingInfo, 0)
		}
		allEdbMappingMap[v.EdbInfoId] = append(allEdbMappingMap[v.EdbInfoId], v)
	}
	//查询指标映射
	//查询所有指标数据
	//查询这个指标相关的mapping信息放到数组里,
	//将得到的指标ID信息放到数组里
	hasFindMap := make(map[int]struct{})
	edbInfoIdMap := make(map[int]struct{})
	edbMappingList := make([]*data_manage.EdbInfoCalculateMapping, 0)
	edbInfoMappingRootIdsMap := make(map[int][]int, 0)
	edbMappingMap := make(map[int]struct{})

	if edbInfoA.EdbType == 2 {
		edbInfoId := edbInfoA.EdbInfoId
		edbMappingList, err = getCalculateEdbInfoByEdbInfoId(allEdbMappingMap, edbInfoId, hasFindMap, edbInfoIdMap, edbMappingList, edbMappingMap, edbInfoMappingRootIdsMap, edbInfoId)
		if err != nil {
			err = fmt.Errorf(" GetCalculateEdbInfoByEdbInfoId err: %s", err.Error())
			return
		}
		// 判断其中是否包含指标B
		if _, ok := edbInfoIdMap[edbInfoB.EdbInfoId]; ok { // 如果包含,则说明存在循环引用关系
			hasRelation = true
			return
		}
	}

	return
}