package future_good

import (
	"errors"
	"eta/eta_api/models/data_manage"
	future_good2 "eta/eta_api/models/data_manage/future_good"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/services/data"
	"eta/eta_api/utils"
	"fmt"
	"github.com/shopspring/decimal"
	"sort"
	"strconv"
	"time"
)

// GetChartEdbData 获取图表的指标数据
func GetChartEdbData(chartInfoId int, startDate, endDate string, baseEdbInfoMapping *data_manage.ChartEdbInfoMapping, edbInfoMappingList []*data_manage.ChartEdbInfoMapping, futureGoodEdbInfoMapping *data_manage.ChartEdbInfoMapping, barChartInfoConf data_manage.FutureGoodBarChartInfoReq, needData bool) (barConfigEdbInfoIdList []data_manage.BarChartInfoEdbItemReq, edbList []*data_manage.ChartEdbInfoMapping, xEdbIdValue []int, xDataList []data_manage.XData, yDataList []data_manage.YData, err error) {
	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
	barChartInfoDateList := barChartInfoConf.DateList
	if futureGoodEdbInfoMapping == nil {
		err = errors.New("商品指标未选取")
		return
	}
	if len(edbInfoMappingList) == 0 {
		err = errors.New("ETA指标未选取")
		return
	}

	// 指标对应的所有数据
	edbDataListMap := make(map[int][]*data_manage.EdbDataList)

	// todo item
	//item := new(data_manage.ChartEdbInfoMapping)

	if futureGoodEdbInfoMapping.Unit == `无` {
		futureGoodEdbInfoMapping.Unit = ``
	}

	if chartInfoId <= 0 {
		for k, edbInfoMapping := range edbInfoMappingList {
			edbInfoMapping.FrequencyEn = data.GetFrequencyEn(edbInfoMapping.Frequency)
			if edbInfoMapping.Unit == `无` {
				edbInfoMapping.Unit = ``
			}
			edbInfoMapping.IsAxis = 1
			edbInfoMapping.LeadValue = 0
			edbInfoMapping.LeadUnit = ""
			edbInfoMapping.ChartEdbMappingId = 0
			edbInfoMapping.ChartInfoId = 0
			edbInfoMapping.IsOrder = false
			edbInfoMapping.EdbInfoType = 1
			edbInfoMapping.ChartStyle = ""
			edbInfoMapping.ChartColor = ""
			edbInfoMapping.ChartWidth = 0
			edbInfoMappingList[k] = edbInfoMapping
		}
		futureGoodEdbInfoMapping.IsAxis = 1
		futureGoodEdbInfoMapping.LeadValue = 0
		futureGoodEdbInfoMapping.LeadUnit = ""
		futureGoodEdbInfoMapping.ChartEdbMappingId = 0
		futureGoodEdbInfoMapping.ChartInfoId = 0
		futureGoodEdbInfoMapping.IsOrder = false
		futureGoodEdbInfoMapping.EdbInfoType = 1
		futureGoodEdbInfoMapping.ChartStyle = ""
		futureGoodEdbInfoMapping.ChartColor = ""
		futureGoodEdbInfoMapping.ChartWidth = 0
	} else {
		for k, edbInfoMapping := range edbInfoMappingList {
			edbInfoMapping.FrequencyEn = data.GetFrequencyEn(edbInfoMapping.Frequency)
			if edbInfoMapping.Unit == `无` {
				edbInfoMapping.Unit = ``
			}
			edbInfoMapping.LeadUnitEn = data.GetLeadUnitEn(edbInfoMapping.LeadUnit)
			edbInfoMappingList[k] = edbInfoMapping
		}
		futureGoodEdbInfoMapping.LeadUnitEn = data.GetLeadUnitEn(futureGoodEdbInfoMapping.LeadUnit)
	}

	//查询横轴配置项
	xDataItemMap := make(map[int]data_manage.XData)
	for k, v := range barChartInfoConf.XDataList {
		xDataItemMap[k] = v
	}

	// 普通的指标数据
	{
		edbList = edbInfoMappingList

		for k, edbInfoMapping := range edbInfoMappingList {
			tmp := data_manage.BarChartInfoEdbItemReq{
				EdbInfoId: edbInfoMapping.EdbInfoId,
				Name:      edbInfoMapping.EdbName,
				NameEn:    edbInfoMapping.EdbNameEn,
				Source:    edbInfoMapping.Source,
			}
			// 如果有配置，则用配置中的指标名称替换
			xItem, ok := xDataItemMap[k]
			if ok && xItem.Name != "" {
				tmp.Name = xItem.Name
				tmp.NameEn = xItem.NameEn
				tmp.IsHide = xItem.IsHide
			}
			barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, tmp)
		}
	}

	// 获取主力合约和最新日期
	var zlFutureGoodEdbInfo *future_good2.FutureGoodEdbInfo
	var latestDate string // 最新日期是这个
	var regionType string // 交易所来源：“国内”，“海外”
	var futureGoodEdbType int
	{
		// 寻找主力合约
		zlFutureGoodEdbInfo, err = future_good2.GetFutureGoodEdbInfo(futureGoodEdbInfoMapping.EdbInfoId)
		if err != nil {
			return
		}
		regionType = zlFutureGoodEdbInfo.RegionType
		futureGoodEdbType = zlFutureGoodEdbInfo.FutureGoodEdbType

		// 如果当前合约配置的 "画图时，日期来源的指标id" 并不是自己的话，那么就去查找对应配置的合约
		if zlFutureGoodEdbInfo.DateSourceId != zlFutureGoodEdbInfo.FutureGoodEdbInfoId {
			sourceDateFutureGoodEdbInfo, tmpErr := future_good2.GetFutureGoodEdbInfo(zlFutureGoodEdbInfo.DateSourceId)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			latestDate = sourceDateFutureGoodEdbInfo.EndDate // 最新日期是这个
		} else {
			latestDate = zlFutureGoodEdbInfo.EndDate // 最新日期是这个
		}
		if latestDate == `0000-00-00` {
			err = errors.New("日期异常")
			return
		}
	}

	// 获取期货指标以及期货数据
	tmpFutureGoodEdbInfoList, err := future_good2.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
	if err != nil {
		return
	}

	latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)
	_, futureGoodEdbInfoList, err := getFutureGoodEdbInfoList(latestDateTime, tmpFutureGoodEdbInfoList, barChartInfoDateList)
	if err != nil {
		return
	}

	futureGoodMappingList := make([]*data_manage.ChartEdbInfoMapping, 0)
	for k, v := range futureGoodEdbInfoList {
		newMappingInfo := &data_manage.ChartEdbInfoMapping{
			EdbInfoId:           v.FutureGoodEdbInfoId,
			SourceName:          v.Exchange,
			Source:              0,
			EdbCode:             v.FutureGoodEdbCode,
			EdbName:             v.FutureGoodEdbName,
			EdbAliasName:        v.FutureGoodEdbName,
			EdbNameEn:           v.FutureGoodEdbNameEn,
			EdbType:             baseEdbInfoMapping.EdbType, //todo baseEdbInfoMapping
			Frequency:           baseEdbInfoMapping.Frequency,
			FrequencyEn:         baseEdbInfoMapping.FrequencyEn,
			Unit:                baseEdbInfoMapping.Unit,
			UnitEn:              baseEdbInfoMapping.UnitEn,
			StartDate:           v.StartDate,
			EndDate:             v.EndDate,
			ModifyTime:          v.ModifyTime.Format(utils.FormatDateTime),
			ChartEdbMappingId:   v.FutureGoodEdbInfoId,
			ChartInfoId:         baseEdbInfoMapping.ChartInfoId,
			MaxData:             v.MaxValue,
			MinData:             v.MinValue,
			IsOrder:             baseEdbInfoMapping.IsOrder,
			IsAxis:              baseEdbInfoMapping.IsAxis,
			EdbInfoType:         baseEdbInfoMapping.EdbInfoType,
			EdbInfoCategoryType: baseEdbInfoMapping.EdbInfoCategoryType,
			LeadValue:           baseEdbInfoMapping.LeadValue,
			LeadUnit:            baseEdbInfoMapping.LeadUnit,
			LeadUnitEn:          baseEdbInfoMapping.LeadUnitEn,
			ChartStyle:          baseEdbInfoMapping.ChartStyle,
			ChartColor:          baseEdbInfoMapping.ChartColor,
			PredictChartColor:   baseEdbInfoMapping.PredictChartColor,
			ChartWidth:          baseEdbInfoMapping.ChartWidth,
			ChartType:           baseEdbInfoMapping.ChartType,
			LatestDate:          v.LatestDate.Format(utils.FormatDateTime),
			LatestValue:         v.LatestValue,
			UniqueCode:          futureGoodEdbInfoMapping.UniqueCode + strconv.Itoa(k),
			MinValue:            v.MinValue,
			MaxValue:            v.MaxValue,
			DataList:            nil,
			IsNullData:          false,
		}
		futureGoodMappingList = append(futureGoodMappingList, newMappingInfo)

		tmp := data_manage.BarChartInfoEdbItemReq{
			EdbInfoId: newMappingInfo.EdbInfoId,
			Name:      fmt.Sprint("M+", v.Month),
			NameEn:    fmt.Sprint("M+", v.Month),
			Source:    newMappingInfo.Source,
		}
		// 判断如果有配置，需要替换为配置内容
		xItem, ok := xDataItemMap[k]
		if ok && xItem.Name != "" {
			tmp.Name = xItem.Name
			tmp.NameEn = xItem.NameEn
			tmp.IsHide = xItem.IsHide
		}
		barConfigEdbInfoIdList = append(barConfigEdbInfoIdList, tmp)

	}

	if regionType == `海外` {
		zlFutureGoodEdbMapping := &data_manage.ChartEdbInfoMapping{
			EdbInfoId:           zlFutureGoodEdbInfo.FutureGoodEdbInfoId,
			SourceName:          zlFutureGoodEdbInfo.Exchange,
			Source:              0,
			EdbCode:             zlFutureGoodEdbInfo.FutureGoodEdbCode,
			EdbName:             zlFutureGoodEdbInfo.FutureGoodEdbName,
			EdbAliasName:        zlFutureGoodEdbInfo.FutureGoodEdbName,
			EdbNameEn:           zlFutureGoodEdbInfo.FutureGoodEdbNameEn,
			EdbType:             baseEdbInfoMapping.EdbType,
			Frequency:           baseEdbInfoMapping.Frequency,
			FrequencyEn:         baseEdbInfoMapping.FrequencyEn,
			Unit:                baseEdbInfoMapping.Unit,
			UnitEn:              baseEdbInfoMapping.UnitEn,
			StartDate:           zlFutureGoodEdbInfo.StartDate,
			EndDate:             zlFutureGoodEdbInfo.EndDate,
			ModifyTime:          zlFutureGoodEdbInfo.ModifyTime.Format(utils.FormatDateTime),
			ChartEdbMappingId:   zlFutureGoodEdbInfo.FutureGoodEdbInfoId,
			ChartInfoId:         baseEdbInfoMapping.ChartInfoId,
			MaxData:             zlFutureGoodEdbInfo.MaxValue,
			MinData:             zlFutureGoodEdbInfo.MinValue,
			IsOrder:             baseEdbInfoMapping.IsOrder,
			IsAxis:              baseEdbInfoMapping.IsAxis,
			EdbInfoType:         baseEdbInfoMapping.EdbInfoType,
			EdbInfoCategoryType: baseEdbInfoMapping.EdbInfoCategoryType,
			LeadValue:           baseEdbInfoMapping.LeadValue,
			LeadUnit:            baseEdbInfoMapping.LeadUnit,
			LeadUnitEn:          baseEdbInfoMapping.LeadUnitEn,
			ChartStyle:          baseEdbInfoMapping.ChartStyle,
			ChartColor:          baseEdbInfoMapping.ChartColor,
			PredictChartColor:   baseEdbInfoMapping.PredictChartColor,
			ChartWidth:          baseEdbInfoMapping.ChartWidth,
			ChartType:           baseEdbInfoMapping.ChartType,
			LatestDate:          zlFutureGoodEdbInfo.LatestDate.Format(utils.FormatDateTime),
			LatestValue:         zlFutureGoodEdbInfo.LatestValue,
			UniqueCode:          futureGoodEdbInfoMapping.UniqueCode + strconv.Itoa(0),
			MinValue:            zlFutureGoodEdbInfo.MinValue,
			MaxValue:            zlFutureGoodEdbInfo.MaxValue,
			DataList:            nil,
			IsNullData:          false,
		}
		edbList = append(edbList, zlFutureGoodEdbMapping)
		edbList = append(edbList, futureGoodMappingList...)
	} else {
		edbList = append(edbList, futureGoodMappingList...)
	}

	if !needData {
		return
	}

	// 获取数据

	// 现货数据
	for _, edbInfoMapping := range edbInfoMappingList {
		dataList := make([]*data_manage.EdbDataList, 0)
		dataList, err = data_manage.GetEdbDataList(edbInfoMapping.Source, edbInfoMapping.SubSource, edbInfoMapping.EdbInfoId, startDate, endDate)
		if err != nil {
			return
		}
		edbDataListMap[edbInfoMapping.EdbInfoId] = dataList
		// todo item
		//item.DataList = dataList
	}
	futureEdbInfoIds := make([]int, 0)
	for _, v := range futureGoodMappingList {
		futureEdbInfoIds = append(futureEdbInfoIds, v.EdbInfoId)
	}
	tmpDataListMap := make(map[int][]*future_good2.FutureGoodEdbData)
	if len(futureEdbInfoIds) > 0 {
		// 期货数据
		tmpDataList, tmpErr := future_good2.GetFutureGoodEdbDataListByIdsAndDate(futureEdbInfoIds, startDate, endDate)
		if tmpErr != nil {
			err = tmpErr
			return
		}

		for _, v := range tmpDataList {
			if _, ok := tmpDataListMap[v.FutureGoodEdbInfoId]; !ok {
				tmpDataListMap[v.FutureGoodEdbInfoId] = make([]*future_good2.FutureGoodEdbData, 0)
			}
			tmpDataListMap[v.FutureGoodEdbInfoId] = append(tmpDataListMap[v.FutureGoodEdbInfoId], v)
		}
	}

	for _, v := range futureGoodMappingList {
		dataList := make([]*data_manage.EdbDataList, 0)
		tmpDataList, ok := tmpDataListMap[v.EdbInfoId]
		if !ok {
			err = fmt.Errorf("期货数据不存在 FutureGoodEdbInfoId: %d", v.EdbInfoId)
			return
		}
		for _, tmpData := range tmpDataList {
			dataList = append(dataList, &data_manage.EdbDataList{
				EdbDataId:     tmpData.FutureGoodEdbDataId,
				EdbInfoId:     tmpData.FutureGoodEdbInfoId,
				DataTime:      tmpData.DataTime.Format(utils.FormatDate),
				DataTimestamp: tmpData.DataTimestamp,
				Value:         tmpData.Close,
			})
		}
		edbDataListMap[v.EdbInfoId] = dataList
		v.DataList = dataList
	}

	xEdbIdValue, yDataList, err = BarChartData(baseEdbInfoMapping, edbInfoMappingList, futureGoodEdbInfoList, edbDataListMap, barChartInfoDateList, regionType, baseEdbInfoMapping.EndDate)

	if len(barChartInfoConf.XDataList) > 0 {
		xDataList = barChartInfoConf.XDataList
	} else {
		for _, v := range edbInfoMappingList {
			xDataList = append(xDataList, data_manage.XData{
				Name:   v.EdbName,
				NameEn: v.EdbNameEn,
				IsHide: 0,
			})
		}
	}

	//yDataList =make([]data_manage.YData,0)
	//data_manage.YData{
	//	Date:           "",
	//	Color:          "",
	//	Name:           "",
	//	NameEn:         "",
	//	Value:          nil,
	//	NoDataEdbList:  nil,
	//	XEdbInfoIdList: nil,
	//}
	futureGoodEdbInfoIndexMap := make(map[int]int)
	for index, v := range futureGoodEdbInfoList {
		futureGoodEdbInfoIndexMap[v.FutureGoodEdbInfoId] = index
	}
	nMap := make(map[int]int)
	maxIndex := 0 // 最大x轴的下标
	for k, tmpYData := range yDataList {
		yDataMap := tmpYData.EdbValMap
		edbInfoIdList := make([]int, 0)
		noDataEdbInfoIdList := make([]int, 0)
		valueList := make([]float64, 0)
		noDataEdbIdMap := make(map[int]int)

		// 所有的N值
		for _, n := range tmpYData.M {
			nMap[n] = n
		}

		// 基础指标
		for _, tmp := range edbInfoMappingList {
			edbInfoIdList = append(edbInfoIdList, tmp.EdbInfoId)
			tmpVal, ok := yDataMap[tmp.EdbInfoId]
			valueList = append(valueList, tmpVal)
			if !ok || tmpVal == 0 {
				noDataEdbInfoIdList = append(noDataEdbInfoIdList, tmp.EdbInfoId)
				noDataEdbIdMap[tmp.EdbInfoId] = tmp.EdbInfoId
			}
		}

		for _, futureGoodEdbInfo := range futureGoodEdbInfoList {
			tmpEdbInfId := futureGoodEdbInfo.FutureGoodEdbInfoId
			edbInfoIdList = append(edbInfoIdList, tmpEdbInfId)
			tmpVal, ok := yDataMap[tmpEdbInfId]
			valueList = append(valueList, tmpVal)
			if !ok || tmpVal == 0 {
				noDataEdbInfoIdList = append(noDataEdbInfoIdList, tmpEdbInfId)
				noDataEdbIdMap[tmpEdbInfId] = tmpEdbInfId
			}
		}
		//tmpYData.Value = valueList
		tmpYData.NoDataEdbList = noDataEdbInfoIdList
		yDataList[k] = tmpYData

		lenEdbId := len(edbInfoIdList)
		tmpMaxIndex := lenEdbId - 1 // 当前数据的最大x轴的下标

		for i := lenEdbId - 1; i >= 0; i-- {
			// 如果没有在无数据的指标列表中找到，那么就找到了最大x轴的下标
			if _, ok := noDataEdbIdMap[edbInfoIdList[i]]; !ok {
				// 如果最大x轴的下标 小于 当前下标，那么就重新赋值
				if maxIndex < i-1 {
					maxIndex = i - 1
				}
				break
			}

			tmpMaxIndex = i - 1
		}

		// 如果最大x轴的下标 小于 当前下标，那么就重新赋值
		if maxIndex < tmpMaxIndex {
			maxIndex = tmpMaxIndex
		}
	}

	//xEdbIdValue = xEdbIdValue[0:maxIndex]

	// 找出所有的N值，并进行正序排列
	nList := make([]int, 0)
	for _, n := range nMap {
		nList = append(nList, n)
	}
	sort.Slice(nList, func(i, j int) bool {
		return nList[i] < nList[j]
	})

	for k, v := range yDataList {
		if len(v.XEdbInfoIdList) >= maxIndex+1 {
			yDataList[k].XEdbInfoIdList = v.XEdbInfoIdList[0 : maxIndex+1]
		}
		if len(v.Value) >= maxIndex+1 {
			yDataList[k].Value = v.Value[0 : maxIndex+1]
		}
	}
	baseEdbLen := len(edbInfoMappingList)
	tmpXDataList, newYDataList, err := handleResultData(regionType, futureGoodEdbType, baseEdbLen, yDataList, futureGoodEdbInfoList, maxIndex)
	if err != nil {
		return
	}
	if len(barChartInfoConf.XDataList) == 0 {
		xDataList = append(xDataList, tmpXDataList...)
	}

	yDataList = newYDataList

	return
}

// BarChartData 获取数据
func BarChartData(baseEdbInfoMapping *data_manage.ChartEdbInfoMapping, edbInfoMappingList []*data_manage.ChartEdbInfoMapping, futureGoodMappingList []*future_good2.FutureGoodEdbInfo, edbDataListMap map[int][]*data_manage.EdbDataList, barChartInfoDateList []data_manage.BarChartInfoDateReq, regionType, latestDate string) (edbIdList []int, yDataList []data_manage.YData, err error) {
	// 指标数据数组（10086:{"2022-12-02":100.01,"2022-12-01":102.3}）
	// 现货指标数据map
	baseEdbDataMap := make(map[int]map[string]float64)
	edbInfoMappingMap := make(map[int]struct{})
	for _, v := range edbInfoMappingList {
		edbInfoMappingMap[v.EdbInfoId] = struct{}{}
	}
	for edbInfoId, edbDataList := range edbDataListMap {
		if _, ok1 := edbInfoMappingMap[edbInfoId]; ok1 {
			edbDateData := make(map[string]float64)
			for _, edbData := range edbDataList {
				edbDateData[edbData.DataTime] = edbData.Value
			}
			baseEdbDataMap[edbInfoId] = edbDateData
		}
	}

	// 期货指标数据map
	futureGoodEdbDataMap := make(map[int]map[string]float64)
	for edbInfoId, edbDataList := range edbDataListMap {
		if _, ok := edbInfoMappingMap[edbInfoId]; ok {
			continue
		}
		edbDateData := make(map[string]float64)
		for _, edbData := range edbDataList {
			edbDateData[edbData.DataTime] = edbData.Value
		}
		futureGoodEdbDataMap[edbInfoId] = edbDateData
	}

	// edbIdList 指标展示顺序；x轴的指标顺序
	edbIdList = make([]int, 0)
	for _, v := range edbInfoMappingList {
		edbIdList = append(edbIdList, v.EdbInfoId)
	}

	for _, v := range futureGoodMappingList {
		edbIdList = append(edbIdList, v.FutureGoodEdbInfoId)
	}

	latestDateTime, _ := time.ParseInLocation(utils.FormatDate, latestDate, time.Local)

	yDataList = make([]data_manage.YData, 0) //y轴的数据列表

	for _, barChartInfoDate := range barChartInfoDateList {
		yDataMap := make(map[int]float64)
		var maxDate time.Time

		var findDateTime time.Time
		switch barChartInfoDate.Type {
		case 1: //最新值
			findDateTime = latestDateTime
		case 2: //近期几天
			findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
		case 3: // 固定日期
			//寻找固定日期的数据
			tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			findDateTime = tmpFindDateTime
		default:
			err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
			return
		}
		if findDateTime.IsZero() {
			err = errors.New("错误的日期")
			return
		}

		findDataList := make([]float64, 0)  // 当前日期的数据值
		noDataIdList := make([]int, 0)      // 没有数据的指标id
		noDataIdMap := make(map[int]int, 0) // 没有数据的指标map
		xEdbInfoIdList := make([]int, 0)    // 当前数据的指标id列表

		// 先找到基准日期
		var realDateTime time.Time
		realDateTime, findDataValue, isFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[baseEdbInfoMapping.EdbInfoId], baseEdbDataMap[baseEdbInfoMapping.EdbInfoId], futureGoodEdbDataMap)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		// 处理其余现货指标
		for _, v := range edbInfoMappingList {
			if v.EdbInfoId == baseEdbInfoMapping.EdbInfoId {
				findDataList = append(findDataList, findDataValue)
				yDataMap[baseEdbInfoMapping.EdbInfoId] = findDataValue
				if isFind {
					maxDate = realDateTime
				} else {
					noDataIdList = append(noDataIdList, baseEdbInfoMapping.EdbInfoId)
					noDataIdMap[baseEdbInfoMapping.EdbInfoId] = baseEdbInfoMapping.EdbInfoId
				}
				xEdbInfoIdList = append(xEdbInfoIdList, v.EdbInfoId)
				continue
			}
			tmpRealDateTime, findDataValueTmp, isFindTmp, e := GetNeedDateData(realDateTime, edbDataListMap[v.EdbInfoId], baseEdbDataMap[v.EdbInfoId], futureGoodEdbDataMap)
			if e != nil {
				err = e
				return
			}
			findDataList = append(findDataList, findDataValueTmp)
			yDataMap[v.EdbInfoId] = findDataValueTmp
			if isFindTmp {
				// todo 是否需要变更 maxDate
				if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
					maxDate = tmpRealDateTime
				}
			} else {
				noDataIdList = append(noDataIdList, v.EdbInfoId)
				noDataIdMap[v.EdbInfoId] = v.EdbInfoId
			}
			xEdbInfoIdList = append(xEdbInfoIdList, v.EdbInfoId)
		}
		//currMonth := findDateTime.Month() // 当前月份
		//currYear := findDateTime.Year()   // 当前年份

		// 用实际日期的月份作为基准，往前推12个月（2024-5-13 16:26:43修改）
		currMonth := realDateTime.Month() // 当前月份
		currYear := realDateTime.Year()   // 当前年份

		mList := make([]int, 0) // 间隔月份
		indexList := make([]int, 0)
		if regionType == `国内` {
			for i := currMonth + 1; i <= 12; i++ {
				indexList = append(indexList, int(i))
				mList = append(mList, int(i-currMonth))
			}
			for i := 1; i < int(currMonth); i++ {
				indexList = append(indexList, i)
				mList = append(mList, 12+i-int(currMonth))
			}
		} else {
			for i, v := range futureGoodMappingList {
				if v.FutureGoodEdbType == 2 {
					if i == 0 {
						continue
					}
					indexList = append(indexList, i)
					mList = append(mList, v.Month)
				} else {
					if v.Year > currYear || (v.Year == currYear && v.Month > int(currMonth)) {
						indexList = append(indexList, i)
						mList = append(mList, (v.Year-currYear)*12+v.Month-int(currMonth))
					}
				}
			}
		}

		for _, i := range indexList {
			futureGoodMapping := futureGoodMappingList[i] // 当前的期货指标
			//tmpRealDateTime, tmpFindDataValue, tmpIsFind, tmpErr := GetNeedDateData(findDateTime, edbDataListMap[futureGoodMapping.FutureGoodEdbInfoId], edbDataMap[futureGoodMapping.FutureGoodEdbInfoId])
			//if tmpErr != nil {
			//	err = tmpErr
			//	return
			//}
			//tmpRealDateTime := findDateTime	// 按照配置找到的日期
			tmpRealDateTime := realDateTime // 实际现货的日期
			tmpFindDataValue, tmpIsFind := futureGoodEdbDataMap[futureGoodMapping.FutureGoodEdbInfoId][tmpRealDateTime.Format(utils.FormatDate)]
			yDataMap[futureGoodMapping.FutureGoodEdbInfoId] = tmpFindDataValue

			findDataList = append(findDataList, tmpFindDataValue)
			if tmpIsFind {
				if maxDate.IsZero() || maxDate.Before(tmpRealDateTime) {
					maxDate = tmpRealDateTime
				}
			} else {
				noDataIdList = append(noDataIdList, futureGoodMapping.FutureGoodEdbInfoId)
				noDataIdMap[futureGoodMapping.FutureGoodEdbInfoId] = futureGoodMapping.FutureGoodEdbInfoId
			}
			// 当前期货合约的指标
			xEdbInfoIdList = append(xEdbInfoIdList, futureGoodMapping.FutureGoodEdbInfoId)
		}

		yName := barChartInfoDate.Name
		yNameEn := barChartInfoDate.Name
		if yName == `` {
			if barChartInfoDate.Type == 2 {
				yName = strconv.Itoa(barChartInfoDate.Value) + "天前"
				if barChartInfoDate.Value == 1 {
					yNameEn = strconv.Itoa(barChartInfoDate.Value) + "day ago"
				} else {
					yNameEn = strconv.Itoa(barChartInfoDate.Value) + " days ago"
				}
			} else {
				yName = maxDate.Format(utils.FormatDate)
				yNameEn = maxDate.Format(utils.FormatDate)
			}
		}
		yDate := "0000-00-00"
		if !maxDate.IsZero() {
			yDate = maxDate.Format(utils.FormatDate)
		}

		// 数据处理,将没有数据的下标,赋值平均值
		{
			hasDataIndexList := make([]int, 0)
			for dataK, edbInfoId := range xEdbInfoIdList {
				if _, ok := noDataIdMap[edbInfoId]; !ok { // 如果是没有数据的指标id
					hasDataIndexList = append(hasDataIndexList, dataK)
				}
			}
			lenHasDataIndex := len(hasDataIndexList)
			if lenHasDataIndex > 0 {
				for lenHasDataI := 1; lenHasDataI < lenHasDataIndex; lenHasDataI++ {
					perK := hasDataIndexList[lenHasDataI-1] //上一个有数据的指标下标
					currK := hasDataIndexList[lenHasDataI]  //当前有数据的指标下标
					preVal := findDataList[perK]            //上一个有数据的坐标的值
					currVal := findDataList[currK]          //当前有数据的指标的值

					// 环差值
					hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(currK - perK)))
					var tmpI int64
					// 将两个中间的数据做平均值补全
					for hcI := perK + 1; hcI < currK; hcI++ {
						tmpI++
						findDataList[hcI], _ = decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(tmpI))).RoundCeil(4).Float64()
					}
				}
			}
		}

		yDataList = append(yDataList, data_manage.YData{
			Date:           yDate,
			ConfigDate:     realDateTime,
			Value:          findDataList,
			NoDataEdbList:  noDataIdList,
			XEdbInfoIdList: xEdbInfoIdList,
			Color:          barChartInfoDate.Color,
			Name:           yName,
			NameEn:         yNameEn,
			EdbValMap:      yDataMap,
			M:              mList,
		})
	}

	return
}

// handleResultData 处理成最终的结果数据
func handleResultData(regionType string, futureGoodEdbType, baseEdbLen int, yDataList []data_manage.YData, futureGoodEdbInfoList []*future_good2.FutureGoodEdbInfo, maxIndex int) (xDataList []data_manage.XData, newYDataList []data_manage.YData, err error) {
	xDataList = make([]data_manage.XData, 0)
	newYDataList = yDataList
	if regionType == `国内` {
		for i := 1; i < 12; i++ {
			if i > maxIndex {
				break
			}
			// todo x轴 内容调整
			xDataList = append(xDataList, data_manage.XData{
				Name:   fmt.Sprint("M+", i),
				NameEn: fmt.Sprint("M+", i),
			})
		}
		return
	}

	futureGoodEdbInfoMap := make(map[int]*future_good2.FutureGoodEdbInfo)
	for _, v := range futureGoodEdbInfoList {
		futureGoodEdbInfoMap[v.FutureGoodEdbInfoId] = v
	}

	if futureGoodEdbType == 2 { // 	FutureGoodEdbType   int       `description:"指标类型,1:年月是固定的合约；2：只有M+N期的合约，未固定年月"`
		nList := []int{3, 15, 27}
		for _, i := range nList {
			xDataList = append(xDataList, data_manage.XData{
				Name:   fmt.Sprint("M+", i),
				NameEn: fmt.Sprint("M+", i),
			})
		}

		for yIndex, yData := range yDataList {
			newYDataList[yIndex].XEdbInfoIdList = []int{}
			newYDataList[yIndex].Value = []float64{}
			tmpNList := nList

			//当前的主力合约
			newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, yData.XEdbInfoIdList[0:baseEdbLen]...)
			newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[0:baseEdbLen]...)

			xEdbInfoIdList := yData.XEdbInfoIdList[baseEdbLen:]
			valIndex := baseEdbLen
			needNum := 0
			for _, n := range tmpNList {
				if len(xEdbInfoIdList) > 0 {
					edbInfoId := xEdbInfoIdList[0]
					futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId]
					if !ok {
						err = errors.New("找不到指标")
						return
					}
					// 当前距离最早的日期相差的N数
					if futureGoodEdbInfo.Month == n {
						if needNum > 0 {
							currVal := yData.Value[valIndex]
							preVal := yData.Value[valIndex-1]
							hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1)))

							for tmpNum := 0; tmpNum < needNum; tmpNum++ {
								newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)

								// 赋值平均值
								tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64()
								newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
							}
						}

						newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, edbInfoId)
						newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
						valIndex++
						needNum = 0
						if len(xEdbInfoIdList) > 0 {
							xEdbInfoIdList = xEdbInfoIdList[1:]
						}
					} else {
						needNum++
					}
				}
			}
		}

		maxI := 0
		for _, yData := range newYDataList {
			lenEdb := len(yData.XEdbInfoIdList)
			for i := 0; i < lenEdb; i++ {
				if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) {
					if maxI < i {
						maxI = i
					}
				}
			}
		}

		xDataList = xDataList[0:maxI]
		for yIndex, yData := range newYDataList {
			if len(yData.XEdbInfoIdList) > maxI+1 {
				newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
			}
			if len(yData.Value) > maxI+1 {
				newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
			}
		}
		return
	}

	nMap := make(map[int]int)

	for _, v := range yDataList {
		findDateTime := v.ConfigDate
		currMonth := findDateTime.Month() // 当前月份
		currYear := findDateTime.Year()   // 当前年份
		//v.XEdbInfoIdList
		for edbInfoIndex, edbInfoId := range v.XEdbInfoIdList {
			// 现货指标不处理
			if edbInfoIndex <= baseEdbLen-1 {
				continue
			}

			futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId]
			if !ok {
				err = errors.New("找不到指标")
				return
			}
			n := (futureGoodEdbInfo.Year-currYear)*12 + futureGoodEdbInfo.Month - int(currMonth)
			nMap[n] = n
		}

	}

	// 找出所有的N值，并进行正序排列
	nList := make([]int, 0)
	for _, n := range nMap {
		nList = append(nList, n)
	}
	sort.Slice(nList, func(i, j int) bool {
		return nList[i] < nList[j]
	})

	//prevMonth := 1

	for _, n := range nList {
		xDataList = append(xDataList, data_manage.XData{
			Name:   fmt.Sprint("M+", n),
			NameEn: fmt.Sprint("M+", n),
		})
	}

	for yIndex, yData := range yDataList {
		newYDataList[yIndex].XEdbInfoIdList = []int{}
		newYDataList[yIndex].Value = []float64{}
		tmpNList := nList

		//当前的主力合约
		newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, yData.XEdbInfoIdList[0:baseEdbLen]...)
		newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[0:baseEdbLen]...)

		xEdbInfoIdList := yData.XEdbInfoIdList[baseEdbLen:]
		currDataTime := yData.ConfigDate
		valIndex := baseEdbLen
		needNum := 0
		for _, n := range tmpNList {
			if len(xEdbInfoIdList) > 0 {
				edbInfoId := xEdbInfoIdList[0]
				futureGoodEdbInfo, ok := futureGoodEdbInfoMap[edbInfoId]
				if !ok {
					err = errors.New("找不到指标")
					return
				}
				// 当前距离最早的日期相差的N数
				divMonth := (futureGoodEdbInfo.Year-currDataTime.Year())*12 + (futureGoodEdbInfo.Month - int(currDataTime.Month()))
				if divMonth == n {
					if needNum > 0 {
						currVal := yData.Value[valIndex]
						preVal := yData.Value[valIndex-1]
						hcValDeci := decimal.NewFromFloat(currVal).Sub(decimal.NewFromFloat(preVal)).Div(decimal.NewFromInt(int64(needNum + 1)))

						for tmpNum := 0; tmpNum < needNum; tmpNum++ {
							newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, 0)

							// 赋值平均值
							tmpVal, _ := decimal.NewFromFloat(preVal).Add(hcValDeci.Mul(decimal.NewFromInt(int64(tmpNum + 1)))).RoundCeil(4).Float64()
							newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, tmpVal)
						}
					}

					newYDataList[yIndex].XEdbInfoIdList = append(newYDataList[yIndex].XEdbInfoIdList, edbInfoId)
					newYDataList[yIndex].Value = append(newYDataList[yIndex].Value, yData.Value[valIndex])
					valIndex++
					needNum = 0
					if len(xEdbInfoIdList) > 0 {
						xEdbInfoIdList = xEdbInfoIdList[1:]
					}
				} else {
					needNum++
				}
			}
		}
	}

	maxI := 0
	for _, yData := range newYDataList {
		lenEdb := len(yData.XEdbInfoIdList)
		for i := 0; i < lenEdb; i++ {
			if yData.XEdbInfoIdList[i] != 0 && !utils.InArrayByInt(yData.NoDataEdbList, yData.XEdbInfoIdList[i]) {
				if maxI < i {
					maxI = i
				}
			}
		}
	}

	xDataList = xDataList[0:maxI]
	for yIndex, yData := range newYDataList {
		if len(yData.XEdbInfoIdList) > maxI+1 {
			newYDataList[yIndex].XEdbInfoIdList = yData.XEdbInfoIdList[0 : maxI+1]
		}
		if len(yData.Value) > maxI+1 {
			newYDataList[yIndex].Value = yData.Value[0 : maxI+1]
		}
	}
	return
}

// getFutureGoodEdbInfoList 获取适用的指标列表
func getFutureGoodEdbInfoList(latestDateTime time.Time, tmpFutureGoodEdbInfoList []*future_good2.FutureGoodEdbInfo, barChartInfoDateList []data_manage.BarChartInfoDateReq) (earliestDateTime time.Time, futureGoodEdbInfoList []*future_good2.FutureGoodEdbInfo, err error) {
	maxM := 36 //最大36期合约
	futureGoodEdbInfoList = make([]*future_good2.FutureGoodEdbInfo, 0)
	earliestDateTime = latestDateTime // 数据的最早日期，目的是为了找出最早的合约
	for _, barChartInfoDate := range barChartInfoDateList {
		var findDateTime time.Time
		switch barChartInfoDate.Type {
		case 1: //最新值
			findDateTime = latestDateTime
		case 2: //近期几天
			findDateTime = latestDateTime.AddDate(0, 0, -barChartInfoDate.Value)
		case 3: // 固定日期
			//寻找固定日期的数据
			tmpFindDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, barChartInfoDate.Date, time.Local)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			findDateTime = tmpFindDateTime
		default:
			err = errors.New(fmt.Sprint("日期类型异常,Type:", barChartInfoDate.Type))
			return
		}
		if findDateTime.IsZero() {
			err = errors.New("错误的日期")
			return
		}
		if findDateTime.Before(earliestDateTime) {
			earliestDateTime = findDateTime
		}
	}

	for _, v := range tmpFutureGoodEdbInfoList {
		if v.RegionType == `国内` {
			futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
			continue
		}
		//海外的连续日期,目前
		if v.FutureGoodEdbType == 2 {
			if v.Month <= maxM {
				//addMonth := int(earliestDateTime.Month()) + v.Month
				//v.Year = earliestDateTime.Year() + addMonth/12
				//realMonth := addMonth % 12
				//if realMonth == 0 {
				//	realMonth = 12
				//}
				//v.Month = realMonth
				futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
			}
			continue
		}

		if v.Year < earliestDateTime.Year() {
			continue
		}
		// 小于等于当前年，那么就肯定是ok的
		if v.Year <= earliestDateTime.Year() {
			futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
			continue
		}
		// 如果（当前年-最新日期的年份） * 12个月 + (当前月-最新日期的月份) 小于总月份
		if (v.Year-earliestDateTime.Year())*12+(v.Month-int(earliestDateTime.Month())) <= maxM {
			futureGoodEdbInfoList = append(futureGoodEdbInfoList, v)
			continue
		}

	}

	return
}

// GetNeedDateData 获取合约内需要的日期数据
func GetNeedDateData(needDateTime time.Time, dataList []*data_manage.EdbDataList, edbDataMap map[string]float64, allEdbDataMap map[int]map[string]float64) (findDateTime time.Time, findDataValue float64, isFind bool, err error) {
	//dataList := edbDataListMap[edbInfoId] //指标的所有数据值
	if len(dataList) <= 0 {
		// 没有数据的指标id
		return
	}

	//最早的日期
	minDateTime, err := time.ParseInLocation(utils.FormatDate, dataList[0].DataTime, time.Local)
	if err != nil {
		return
	}

	// 该日期存在数据的期货指标的最小数量，目前是现货和期货各1个，总共2个
	maxCount := 1

	for tmpDateTime := needDateTime; tmpDateTime.After(minDateTime) || tmpDateTime.Equal(minDateTime); tmpDateTime = tmpDateTime.AddDate(0, 0, -1) {
		tmpDate := tmpDateTime.Format(utils.FormatDate)
		tmpValue, ok := edbDataMap[tmpDate]
		if !ok {
			continue
		}

		// 该日期存在数据的指标数量
		count := 0

		for _, currEdbDataMap := range allEdbDataMap {
			_, tmpIsFind := currEdbDataMap[tmpDate]
			if tmpIsFind {
				count++
				if count >= maxCount {
					continue
				}
			}
		}

		// 该日期存在数据的期货指标数量小于2个，那么要继续往前找
		if count < maxCount {
			continue
		}

		//如果能找到数据，那么就返回
		// 数据为0,也直接返回,做无值处理
		if tmpValue == 0 {
			return
		}
		findDateTime, _ = time.ParseInLocation(utils.FormatDate, tmpDate, time.Local)
		findDataValue = tmpValue
		isFind = true
		return
	}

	return
}

// FutureGoodChartInfoRefresh
// @author Roc
// @datetime 2023-2-2 18:44:46
// @description 商品价格曲线图表刷新
func FutureGoodChartInfoRefresh(chartInfoId int) (err error) {
	var errMsg string
	defer func() {
		if err != nil {
			go alarm_msg.SendAlarmMsg("ChartInfoRefresh:"+errMsg, 3)
			fmt.Println("ChartInfoRefresh Err:" + errMsg)
		}
	}()

	edbInfoMappingList, err := data_manage.GetEtaEdbChartEdbMappingList(chartInfoId)
	if err != nil {
		errMsg = "获取需要刷新的ETA指标失败:Err:" + err.Error()
		return
	}
	edbInfoIds := make([]int, 0)
	for _, edbInfoMapping := range edbInfoMappingList {
		edbInfoIds = append(edbInfoIds, edbInfoMapping.EdbInfoId)
	}
	// 获取期货指标
	futureGoodEdbInfoMapping, err := data_manage.GetFutureGoodEdbChartEdbMapping(chartInfoId)
	if err != nil {
		errMsg = "获取需要刷新的商品期货指标失败:Err:" + err.Error()
		return
	}

	// 获取期货指标以及期货数据
	futureGoodEdbInfoList, err := future_good2.GetFutureGoodEdbInfoListByParentId(futureGoodEdbInfoMapping.EdbInfoId)
	if err != nil {
		return
	}

	// 批量刷新ETA指标
	err, _ = data.EdbInfoRefreshAllFromBaseV3(edbInfoIds, false, true, false)
	if err != nil {
		return
	}

	// 批量刷新期货指标
	err = FutureGoodEdbInfoRefreshAllFromBase(futureGoodEdbInfoList, false)
	if err != nil {
		return
	}

	return
}
