package data

import (
	"eta/eta_mobile/models/data_manage"
	"fmt"
)

// 查询两个指标是否存在循环引用关系
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
}

// 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
}
