package correlation

import (
	"encoding/json"
	"errors"
	"fmt"
	"github.com/shopspring/decimal"
	"eta/eta_mobile/models/data_manage"
	"eta/eta_mobile/models/system"
	"eta/eta_mobile/services/alarm_msg"
	"eta/eta_mobile/services/data"
	"eta/eta_mobile/utils"
	"math"
	"sort"
	"strconv"
	"strings"
	"time"
)

// HandleDataByLinearRegression 线性方程插值法补全数据
func HandleDataByLinearRegression(originList []*data_manage.EdbDataList, handleDataMap map[string]float64) (newList []*data_manage.EdbDataList, err error) {
	if len(originList) < 2 {
		return
	}

	var startEdbInfoData *data_manage.EdbDataList
	for _, v := range originList {
		handleDataMap[v.DataTime] = v.Value

		// 第一个数据就给过滤了,给后面的试用
		if startEdbInfoData == nil {
			startEdbInfoData = v
			newList = append(newList, &data_manage.EdbDataList{
				DataTime: v.DataTime,
				Value:    v.Value,
			})
			continue
		}

		// 获取两条数据之间相差的天数
		startDataTime, _ := time.ParseInLocation(utils.FormatDate, startEdbInfoData.DataTime, time.Local)
		currDataTime, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
		betweenHour := int(currDataTime.Sub(startDataTime).Hours())
		betweenDay := betweenHour / 24

		// 如果相差一天,那么过滤
		if betweenDay <= 1 {
			startEdbInfoData = v
			newList = append(newList, &data_manage.EdbDataList{
				DataTime: v.DataTime,
				Value:    v.Value,
			})
			continue
		}

		// 生成线性方程式
		var a, b float64
		{
			coordinateData := make([]utils.Coordinate, 0)
			tmpCoordinate1 := utils.Coordinate{
				X: 1,
				Y: startEdbInfoData.Value,
			}
			coordinateData = append(coordinateData, tmpCoordinate1)
			tmpCoordinate2 := utils.Coordinate{
				X: float64(betweenDay) + 1,
				Y: v.Value,
			}
			coordinateData = append(coordinateData, tmpCoordinate2)

			a, b = utils.GetLinearResult(coordinateData)
			if math.IsNaN(a) || math.IsNaN(b) {
				err = fmt.Errorf("线性方程公式生成失败")
				return
			}
		}

		// 生成对应的值
		{
			for i := 1; i < betweenDay; i++ {
				tmpDataTime := startDataTime.AddDate(0, 0, i)
				aDecimal := decimal.NewFromFloat(a)
				xDecimal := decimal.NewFromInt(int64(i) + 1)
				bDecimal := decimal.NewFromFloat(b)

				val, _ := aDecimal.Mul(xDecimal).Add(bDecimal).Round(4).Float64()
				handleDataMap[tmpDataTime.Format(utils.FormatDate)] = val
				newList = append(newList, &data_manage.EdbDataList{
					DataTime: tmpDataTime.Format(utils.FormatDate),
					Value:    val,
				})
			}
		}

		// 最后将自己赋值
		newList = append(newList, &data_manage.EdbDataList{
			EdbDataId: v.EdbDataId,
			DataTime:  v.DataTime,
			Value:     v.Value,
		})

		startEdbInfoData = v
	}
	return
}

// MoveDataDaysToNewDataList 平移指标数据生成新的数据序列
func MoveDataDaysToNewDataList(dataList []*data_manage.EdbDataList, moveDay int) (newDataList []data_manage.EdbDataList, dateDataMap map[string]float64) {
	dateMap := make(map[time.Time]float64)
	var minDate, maxDate time.Time
	dateDataMap = make(map[string]float64)

	for _, v := range dataList {
		currDate, _ := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
		if minDate.IsZero() || currDate.Before(minDate) {
			minDate = currDate
		}
		if maxDate.IsZero() || currDate.After(maxDate) {
			maxDate = currDate
		}
		dateMap[currDate] = v.Value
	}

	// 处理领先、滞后数据
	newDateMap := make(map[time.Time]float64)
	for currDate, value := range dateMap {
		newDate := currDate.AddDate(0, 0, moveDay)
		newDateMap[newDate] = value
	}
	minDate = minDate.AddDate(0, 0, moveDay)
	maxDate = maxDate.AddDate(0, 0, moveDay)

	// 获取日期相差日
	dayNum := utils.GetTimeSubDay(minDate, maxDate)

	for i := 0; i <= dayNum; i++ {
		currDate := minDate.AddDate(0, 0, i)
		tmpValue, ok := newDateMap[currDate]
		if !ok {
			//找不到数据,那么就用前面的数据吧
			if len(newDataList)-1 < 0 {
				tmpValue = 0
			} else {
				tmpValue = newDataList[len(newDataList)-1].Value
			}
		}
		tmpData := data_manage.EdbDataList{
			DataTime: currDate.Format(utils.FormatDate),
			Value:    tmpValue,
		}
		dateDataMap[tmpData.DataTime] = tmpData.Value
		newDataList = append(newDataList, tmpData)
	}
	return
}

// GetChartEdbInfoFormat 相关性图表-获取指标信息
func GetChartEdbInfoFormat(chartInfoId int, edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping) (edbList []*data_manage.ChartEdbInfoMapping, err error) {
	edbList = make([]*data_manage.ChartEdbInfoMapping, 0)
	if edbInfoMappingA == nil || edbInfoMappingB == nil {
		err = fmt.Errorf("指标信息有误")
		return
	}

	edbInfoMappingA.FrequencyEn = data.GetFrequencyEn(edbInfoMappingA.Frequency)
	if edbInfoMappingA.Unit == `无` {
		edbInfoMappingA.Unit = ``
	}
	if edbInfoMappingB.Unit == `无` {
		edbInfoMappingB.Unit = ``
	}
	if chartInfoId <= 0 {
		edbInfoMappingA.IsAxis = 1
		edbInfoMappingA.LeadValue = 0
		edbInfoMappingA.LeadUnit = ""
		edbInfoMappingA.ChartEdbMappingId = 0
		edbInfoMappingA.ChartInfoId = 0
		edbInfoMappingA.IsOrder = false
		edbInfoMappingA.EdbInfoType = 1
		edbInfoMappingA.ChartStyle = ""
		edbInfoMappingA.ChartColor = ""
		edbInfoMappingA.ChartWidth = 0

		edbInfoMappingB.IsAxis = 1
		edbInfoMappingB.LeadValue = 0
		edbInfoMappingB.LeadUnit = ""
		edbInfoMappingB.ChartEdbMappingId = 0
		edbInfoMappingB.ChartInfoId = 0
		edbInfoMappingB.IsOrder = false
		edbInfoMappingB.EdbInfoType = 1
		edbInfoMappingB.ChartStyle = ""
		edbInfoMappingB.ChartColor = ""
		edbInfoMappingB.ChartWidth = 0
	} else {
		edbInfoMappingA.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingA.LeadUnit)
		edbInfoMappingB.LeadUnitEn = data.GetLeadUnitEn(edbInfoMappingB.LeadUnit)
	}
	edbList = append(edbList, edbInfoMappingA, edbInfoMappingB)
	return
}

// GetChartAndCorrelationInfo 获取图表信息和相关信息信息
func GetChartAndCorrelationInfo(chartInfoId int) (chartInfo *data_manage.ChartInfo, correlationInfo *data_manage.ChartInfoCorrelation, tips string, err error) {
	item, e := data_manage.GetChartInfoById(chartInfoId)
	if e != nil {
		if e.Error() == utils.ErrNoRow() {
			tips = "图表已被删除, 请刷新页面"
			err = fmt.Errorf("图表已被删除, 请刷新页面")
			return
		}
		err = fmt.Errorf("获取图表信息失败, Err: %s", e.Error())
		return
	}
	if item.Source != utils.CHART_SOURCE_CORRELATION {
		tips = "该图不是相关性图表"
		err = fmt.Errorf("该图不是相关性图表")
		return
	}
	chartInfo = item
	correlationInfo = new(data_manage.ChartInfoCorrelation)
	if e = correlationInfo.GetItemById(chartInfo.ChartInfoId); e != nil {
		err = fmt.Errorf("获取图表相关性信息失败, Err: %s", e.Error())
		return
	}
	return
}

// GetChartDataByEdbInfo 相关性图表-根据指标信息获取x轴和y轴
func GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit, startDate, endDate string) (xEdbIdValue []int, yDataList []data_manage.YData, err error) {
	xData := make([]int, 0)
	yData := make([]float64, 0)
	if leadValue == 0 {
		xData = append(xData, 0)
	}
	if leadValue > 0 {
		leadMin := 0 - leadValue
		xLen := 2*leadValue + 1
		for i := 0; i < xLen; i++ {
			n := leadMin + i
			xData = append(xData, n)
		}
	}

	// 计算窗口,不包含第一天
	startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
	startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)

	//// 2023-03-02 时间序列始终以指标B为基准, 始终是A进行平移
	//baseEdbInfo := edbInfoMappingB
	//changeEdbInfo := edbInfoMappingA
	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
	baseEdbInfo := edbInfoMappingA
	changeEdbInfo := edbInfoMappingB

	// 获取时间基准指标在时间区间内的值
	aDataList := make([]*data_manage.EdbDataList, 0)
	switch baseEdbInfo.EdbInfoCategoryType {
	case 0:
		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
	case 1:
		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, false)
	default:
		err = errors.New("指标base类型异常")
		return
	}

	// 获取变频指标所有日期的值, 插值法完善数据
	bDataList := make([]*data_manage.EdbDataList, 0)
	switch changeEdbInfo.EdbInfoCategoryType {
	case 0:
		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
	case 1:
		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
	default:
		err = errors.New("指标change类型异常")
		return
	}
	//changeDataMap := make(map[string]float64)
	//newChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
	//if e != nil {
	//	err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
	//	return
	//}

	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
	baseDataList := make([]*data_manage.EdbDataList, 0)
	baseDataMap := make(map[string]float64)
	changeDataList := make([]*data_manage.EdbDataList, 0)
	changeDataMap := make(map[string]float64)

	// 先把低频指标升频为高频
	{
		frequencyIntMap := map[string]int{
			"日度": 1,
			"周度": 2,
			"旬度": 3,
			"月度": 4,
			"季度": 5,
			"年度": 6,
		}

		// 如果A指标是高频,那么就需要对B指标进行升频
		if frequencyIntMap[edbInfoMappingA.Frequency] < frequencyIntMap[edbInfoMappingB.Frequency] {
			tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
			if e != nil {
				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
				return
			}
			changeDataList = tmpNewChangeDataList
			baseDataList = aDataList
			for _, v := range baseDataList {
				baseDataMap[v.DataTime] = v.Value
			}

		} else if frequencyIntMap[edbInfoMappingA.Frequency] > frequencyIntMap[edbInfoMappingB.Frequency] {
			// 如果B指标是高频,那么就需要对A指标进行升频
			tmpNewChangeDataList, e := HandleDataByLinearRegression(aDataList, baseDataMap)
			if e != nil {
				err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
				return
			}
			baseDataList = tmpNewChangeDataList

			changeDataList = bDataList
			for _, v := range changeDataList {
				changeDataMap[v.DataTime] = v.Value
			}
		} else {
			baseDataList = aDataList
			for _, v := range baseDataList {
				baseDataMap[v.DataTime] = v.Value
			}
			changeDataList = bDataList
			for _, v := range changeDataList {
				changeDataMap[v.DataTime] = v.Value
			}
		}

	}

	// 计算不领先也不滞后时的相关系数
	baseCalculateData := make([]float64, 0)
	baseDataTimeArr := make([]string, 0)
	for i := range baseDataList {
		baseDataTimeArr = append(baseDataTimeArr, baseDataList[i].DataTime)
		baseCalculateData = append(baseCalculateData, baseDataList[i].Value)
	}

	zeroBaseData := make([]float64, 0)
	zeroCalculateData := make([]float64, 0)
	for i := range baseDataTimeArr {
		tmpBaseVal, ok1 := baseDataMap[baseDataTimeArr[i]]
		tmpCalculateVal, ok2 := changeDataMap[baseDataTimeArr[i]]
		if ok1 && ok2 {
			zeroBaseData = append(zeroBaseData, tmpBaseVal)
			zeroCalculateData = append(zeroCalculateData, tmpCalculateVal)
		}
	}
	if len(zeroBaseData) != len(zeroCalculateData) {
		err = fmt.Errorf("相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(zeroCalculateData))
		return
	}
	zeroRatio := utils.CalculateCorrelationByIntArr(zeroBaseData, zeroCalculateData)
	if leadValue == 0 {
		yData = append(yData, zeroRatio)
	}

	// 计算领先/滞后N期
	if leadValue > 0 {
		// 平移变频指标领先/滞后的日期(单位天)
		moveUnitDays := utils.FrequencyDaysMap[leadUnit]

		for i := range xData {
			if xData[i] == 0 {
				yData = append(yData, zeroRatio)
				continue
			}
			xCalculateData := make([]float64, 0)
			yCalculateData := make([]float64, 0)

			// 平移指定天数
			mDays := int(moveUnitDays) * xData[i]
			_, dMap := MoveDataDaysToNewDataList(changeDataList, mDays)

			// 取出对应的基准日期的值
			for i2 := range baseDataTimeArr {
				if yVal, ok := dMap[baseDataTimeArr[i2]]; ok {
					xCalculateData = append(xCalculateData, baseCalculateData[i2])
					yCalculateData = append(yCalculateData, yVal)
				}
			}
			if len(yCalculateData) <= 0 {
				//err = fmt.Errorf("领先滞后相关系数两组序列元素数不一致, %d-%d", len(baseCalculateData), len(yCalculateData))
				//return
				// 领先滞后后,没有可以计算的数据了
				continue
			}

			// 公式计算出领先/滞后频度对应点的相关性系数
			ratio := utils.CalculateCorrelationByIntArr(xCalculateData, yCalculateData)
			yData = append(yData, ratio)
		}
	}

	xEdbIdValue = xData
	yDataList = make([]data_manage.YData, 0)
	yDate := "0000-00-00"
	yDataList = append(yDataList, data_manage.YData{
		Date:  yDate,
		Value: yData,
	})
	return
}

// RollingCorrelationChartDataResp 滚动相关性图表数据
type RollingCorrelationChartDataResp struct {
	MaxData             float64
	MinData             float64
	LatestDate          string `description:"真实数据的最后日期"`
	EdbInfoCategoryType int
	ChartColor          string
	ChartStyle          string
	PredictChartColor   string
	ChartType           int
	ChartWidth          int
	EdbName             string
	EdbNameEn           string
	Unit                string
	UnitEn              string
	IsAxis              int
	DataList            []data_manage.EdbDataList
}

// GetRollingCorrelationChartDataByEdbInfo 滚动相关性计算
func GetRollingCorrelationChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB *data_manage.ChartEdbInfoMapping, leadValue int, leadUnit string, calculateValue int, calculateUnit string, startDate, endDate, chartName, chartNameEn string) (dataResp RollingCorrelationChartDataResp, err error) {
	dataResp = RollingCorrelationChartDataResp{
		DataList:          make([]data_manage.EdbDataList, 0),
		MaxData:           0,
		MinData:           0,
		ChartColor:        "#00f",
		ChartStyle:        `spline`,
		PredictChartColor: `#00f`,
		ChartType:         0,
		ChartWidth:        3,
		EdbName:           chartName,
		EdbNameEn:         chartNameEn,
		IsAxis:            1,
	}
	dataList := make([]data_manage.EdbDataList, 0)

	// 计算窗口,不包含第一天
	startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
	startDate = startDateTime.AddDate(0, 0, 1).Format(utils.FormatDate)

	baseEdbInfo := edbInfoMappingA
	changeEdbInfo := edbInfoMappingB

	// 获取时间基准指标在时间区间内的值
	aDataList := make([]*data_manage.EdbDataList, 0)
	switch baseEdbInfo.EdbInfoCategoryType {
	case 0:
		aDataList, err = data_manage.GetEdbDataList(baseEdbInfo.Source, baseEdbInfo.EdbInfoId, startDate, endDate)
	case 1:
		_, aDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(baseEdbInfo.EdbInfoId, startDate, endDate, true)
	default:
		err = errors.New("指标base类型异常")
		return
	}

	// 获取变频指标所有日期的值, 插值法完善数据
	bDataList := make([]*data_manage.EdbDataList, 0)
	switch changeEdbInfo.EdbInfoCategoryType {
	case 0:
		bDataList, err = data_manage.GetEdbDataList(changeEdbInfo.Source, changeEdbInfo.EdbInfoId, "", "")
	case 1:
		_, bDataList, _, _, err, _ = data.GetPredictDataListByPredictEdbInfoId(changeEdbInfo.EdbInfoId, "", "", false)
	default:
		err = errors.New("指标change类型异常")
		return
	}

	// 数据平移变频指标领先/滞后的日期(单位天)
	// 2023-03-17 时间序列始终以指标A为基准, 始终是B进行平移
	//baseDataList := make([]*data_manage.EdbDataList, 0)
	baseDataMap := make(map[string]float64)
	changeDataList := make([]*data_manage.EdbDataList, 0)
	changeDataMap := make(map[string]float64)

	// A指标不管三七二十一,先变个频再说
	{
		_, e := HandleDataByLinearRegression(aDataList, baseDataMap)
		if e != nil {
			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
			return
		}
		//baseDataList = tmpNewChangeDataList
	}
	// B指标不管三七二十一,先变个频再说
	{
		tmpNewChangeDataList, e := HandleDataByLinearRegression(bDataList, changeDataMap)
		if e != nil {
			err = fmt.Errorf("获取变频指标插值法Map失败, Err: %s", e.Error())
			return
		}
		changeDataList = tmpNewChangeDataList

		// 平移下日期
		moveUnitDays := utils.FrequencyDaysMap[leadUnit]
		_, changeDataMap = MoveDataDaysToNewDataList(changeDataList, leadValue*moveUnitDays)
	}

	// 计算计算时,需要多少个日期内数据
	calculateDay := utils.FrequencyDaysMap[calculateUnit] * calculateValue

	// 计算 每个日期的相关性值
	{
		startDateTime, _ := time.ParseInLocation(utils.FormatDate, startDate, time.Local)
		if endDate == `` {
			endDate = baseEdbInfo.EndDate
		}
		endDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
		endDateTime = endDateTime.AddDate(0, 0, -(calculateDay - 1))

		// 是否开始第一条数据
		var isStart, isNotFirst bool
		for currDay := startDateTime; !currDay.After(endDateTime); currDay = currDay.AddDate(0, 0, 1) {
			yCalculateData := make([]float64, 0)
			baseCalculateData := make([]float64, 0)

			// 取出对应的基准日期的值
			for i := 0; i < calculateDay; i++ {
				iDay := currDay.AddDate(0, 0, i).Format(utils.FormatDate)

				tmpBaseValue, ok1 := baseDataMap[iDay]
				tmpChangeValue, ok2 := changeDataMap[iDay]
				if ok1 && ok2 {
					baseCalculateData = append(baseCalculateData, tmpBaseValue)
					yCalculateData = append(yCalculateData, tmpChangeValue)
				} else {
					continue
				}
			}

			// 公式计算出领先/滞后频度对应点的相关性系数
			var ratio float64
			if len(baseCalculateData) > 0 {
				ratio = utils.CalculateCorrelationByIntArr(baseCalculateData, yCalculateData)
			} else {
				// 没有数据的话,那就不返回
				continue
			}

			// 过滤前面都是0的数据
			{
				if ratio != 0 {
					isStart = true
				}

				if !isStart {
					continue
				}
			}

			dataTime := currDay.AddDate(0, 0, calculateDay-1)
			dataList = append(dataList, data_manage.EdbDataList{
				//EdbDataId:     0,
				EdbInfoId:     0,
				DataTime:      dataTime.Format(utils.FormatDate),
				DataTimestamp: dataTime.UnixNano() / 1e6,
				Value:         ratio,
			})

			if !isNotFirst {
				dataResp.MinData = ratio
				dataResp.MaxData = ratio
				isNotFirst = true
			}
			if dataResp.MinData > ratio {
				dataResp.MinData = ratio
			}
			if dataResp.MaxData < ratio {
				dataResp.MaxData = ratio
			}
		}
		dataResp.DataList = dataList
	}

	return
}

// ChartInfoRefresh 图表刷新
func ChartInfoRefresh(chartInfoId int) (err error) {
	var errMsg string
	defer func() {
		if err != nil {
			go alarm_msg.SendAlarmMsg("CorrelationChartInfoRefresh: "+errMsg, 3)
		}
	}()
	correlationChart := new(data_manage.ChartInfoCorrelation)
	if err = correlationChart.GetItemById(chartInfoId); err != nil {
		errMsg = "获取相关性图表失败, Err: " + err.Error()
		return
	}

	// 批量刷新ETA指标
	err = data.EdbInfoRefreshAllFromBaseV3([]int{correlationChart.EdbInfoIdFirst, correlationChart.EdbInfoIdSecond}, false)
	if err != nil {
		return
	}

	// 重新生成数据并更新
	edbInfoMappingA, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdFirst)
	if err != nil {
		errMsg = "获取相关性图表, A指标mapping信息失败, Err:" + err.Error()
		return
	}
	edbInfoMappingB, err := data_manage.GetChartEdbMappingByEdbInfoId(correlationChart.EdbInfoIdSecond)
	if err != nil {
		errMsg = "获取相关性图表, B指标mapping信息失败, Err:" + err.Error()
		return
	}
	periodData, correlationData, err := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, correlationChart.LeadValue, correlationChart.LeadUnit, correlationChart.StartDate.Format(utils.FormatDate), correlationChart.EndDate.Format(utils.FormatDate))
	if err != nil {
		errMsg = "获取相关性图表, 图表计算值失败, Err:" + err.Error()
		return
	}
	periodDataByte, err := json.Marshal(periodData)
	if err != nil {
		errMsg = "相关性图表, X轴信息有误, Err:" + err.Error()
		return
	}
	correlationDataByte, err := json.Marshal(correlationData[0].Value)
	if err != nil {
		errMsg = "相关性图表, Y轴信息有误, Err:" + err.Error()
		return
	}
	correlationChart.PeriodData = string(periodDataByte)
	correlationChart.CorrelationData = string(correlationDataByte)
	correlationChart.ModifyTime = time.Now().Local()
	correlationUpdateCols := []string{"PeriodData", "CorrelationData", "ModifyTime"}
	if err = correlationChart.Update(correlationUpdateCols); err != nil {
		errMsg = "更新相关性图表失败, Err:" + err.Error()
		return
	}
	return
}

// AddChartInfo 添加图表
func AddChartInfo(req data_manage.AddChartInfoReq, source int, sysUser *system.Admin) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
	isSendEmail = true

	req.ChartName = strings.Trim(req.ChartName, " ")
	if req.ChartName == "" {
		errMsg = "请填写图表名称!"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	if req.ChartClassifyId <= 0 {
		errMsg = "分类参数错误!"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	// 相关性图表配置
	if req.CorrelationChartInfo.LeadValue == 0 {
		errMsg = "请输入领先期数"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	if req.CorrelationChartInfo.LeadUnit == "" {
		errMsg = "请填写领先单位"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	//if req.CorrelationChartInfo.StartDate == "" || req.CorrelationChartInfo.EndDate == "" {
	//	errMsg = "请填写开始结束日期"
	//	err = errors.New(errMsg)
	//	isSendEmail = false
	//	return
	//}
	//startDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.StartDate)
	//if e != nil {
	//	errMsg = "开始日期格式有误"
	//	err = errors.New(errMsg)
	//	isSendEmail = false
	//	return
	//}
	//endDate, e := time.Parse(utils.FormatDate, req.CorrelationChartInfo.EndDate)
	//if e != nil {
	//	errMsg = "结束日期格式有误"
	//	err = errors.New(errMsg)
	//	isSendEmail = false
	//	return
	//}
	if len(req.CorrelationChartInfo.EdbInfoIdList) != 2 {
		errMsg = "请选择AB指标"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	chartClassify, err := data_manage.GetChartClassifyById(req.ChartClassifyId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "分类不存在"
			err = errors.New(errMsg)
			isSendEmail = false
			return
		}
		errMsg = "获取分类信息失败"
		err = errors.New("获取分类信息失败,Err:" + err.Error())
		return
	}
	if chartClassify == nil {
		errMsg = "分类不存在"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	var edbInfoIdArr []int
	for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
		edbInfoId := v.EdbInfoId
		edbInfo, tmpErr := data_manage.GetEdbInfoById(edbInfoId)
		if tmpErr != nil {
			if tmpErr.Error() == utils.ErrNoRow() {
				errMsg = "指标不存在!"
				err = errors.New("指标不存在,edbInfoId:" + strconv.Itoa(edbInfoId))
				return
			} else {
				errMsg = "获取指标信息失败!"
				err = errors.New("获取图表的指标信息失败,Err:" + tmpErr.Error())
				return
			}
		}

		if edbInfo == nil {
			errMsg = "指标已被删除,请重新选择!"
			err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
			return
		} else {
			if edbInfo.EdbInfoId <= 0 {
				errMsg = "指标已被删除,请重新选择!"
				err = errors.New("指标不存在,ChartInfoId:" + strconv.Itoa(edbInfoId))
				return
			}
		}

		edbInfoIdArr = append(edbInfoIdArr, edbInfoId)
		edbInfo.EdbNameSource = edbInfo.EdbName
	}

	sort.Ints(edbInfoIdArr)
	var edbInfoIdArrStr []string
	for _, v := range edbInfoIdArr {
		edbInfoIdArrStr = append(edbInfoIdArrStr, strconv.Itoa(v))
	}
	edbInfoIdStr := strings.Join(edbInfoIdArrStr, ",")
	var chartInfoId int
	// 判断图表是否存在
	var condition string
	var pars []interface{}
	condition += " AND chart_name=? AND source = ? "
	pars = append(pars, req.ChartName, source)
	count, err := data_manage.GetChartInfoCountByCondition(condition, pars)
	if err != nil {
		errMsg = "判断图表名称是否存在失败"
		err = errors.New("判断图表名称是否存在失败,Err:" + err.Error())
		return
	}

	if count > 0 {
		errMsg = "图表已存在,请重新填写"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}

	disableVal := data.CheckIsDisableChart(edbInfoIdArr)

	chartInfo = new(data_manage.ChartInfo)
	chartInfo.ChartName = req.ChartName
	chartInfo.EdbInfoIds = edbInfoIdStr
	chartInfo.ChartClassifyId = req.ChartClassifyId
	chartInfo.SysUserId = sysUser.AdminId
	chartInfo.SysUserRealName = sysUser.RealName
	chartInfo.CreateTime = time.Now()
	chartInfo.ModifyTime = time.Now()
	chartInfo.IsSetName = 0
	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
	chartInfo.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp)
	chartInfo.ChartType = 9 // 相关性图
	chartInfo.Calendar = "公历"
	chartInfo.DateType = 6
	chartInfo.StartDate = req.StartDate
	chartInfo.EndDate = req.EndDate
	chartInfo.SeasonStartDate = req.SeasonStartDate
	chartInfo.SeasonEndDate = req.SeasonEndDate
	chartInfo.LeftMin = req.LeftMin
	chartInfo.LeftMax = req.LeftMax
	chartInfo.RightMin = req.RightMin
	chartInfo.RightMax = req.RightMax
	chartInfo.Disabled = disableVal
	chartInfo.Source = source

	// 指标信息
	mapList := make([]*data_manage.ChartEdbMapping, 0)
	for _, v := range req.CorrelationChartInfo.EdbInfoIdList {
		mapItem := new(data_manage.ChartEdbMapping)
		mapItem.EdbInfoId = v.EdbInfoId
		mapItem.CreateTime = time.Now()
		mapItem.ModifyTime = time.Now()
		timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
		mapItem.UniqueCode = utils.MD5(utils.CHART_PREFIX + "_" + timestamp + "_" + strconv.Itoa(v.EdbInfoId))
		mapItem.IsOrder = true
		mapItem.IsAxis = 1
		mapItem.EdbInfoType = 1
		mapItem.Source = utils.CHART_SOURCE_CORRELATION
		mapList = append(mapList, mapItem)
	}

	// 相关性图表扩展信息
	correlationChart := new(data_manage.ChartInfoCorrelation)
	correlationChart.LeadValue = req.CorrelationChartInfo.LeadValue
	correlationChart.LeadUnit = req.CorrelationChartInfo.LeadUnit
	correlationChart.CalculateValue = req.CorrelationChartInfo.CalculateValue
	correlationChart.CalculateUnit = req.CorrelationChartInfo.CalculateUnit
	correlationChart.BaseCalculateValue = req.CorrelationChartInfo.BaseCalculateValue
	correlationChart.BaseCalculateUnit = req.CorrelationChartInfo.BaseCalculateUnit
	correlationChart.EdbInfoIdFirst = req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId
	correlationChart.EdbInfoIdSecond = req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId
	correlationChart.CreateTime = time.Now().Local()
	correlationChart.ModifyTime = time.Now().Local()
	//// 生成图表x轴y轴数据
	//edbInfoMappingA, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[0].EdbInfoId)
	//if e != nil {
	//	errMsg = "获取失败"
	//	err = errors.New("获取相关性图表, A指标mapping信息失败, Err:" + e.Error())
	//	return
	//}
	//edbInfoMappingB, e := data_manage.GetChartEdbMappingByEdbInfoId(req.CorrelationChartInfo.EdbInfoIdList[1].EdbInfoId)
	//if e != nil {
	//	errMsg = "获取失败"
	//	err = errors.New("获取相关性图表, B指标mapping信息失败, Err:" + e.Error())
	//	return
	//}
	//periodData, correlationData, e := GetChartDataByEdbInfo(edbInfoMappingA, edbInfoMappingB, req.CorrelationChartInfo.LeadValue, req.CorrelationChartInfo.LeadUnit, req.CorrelationChartInfo.StartDate, req.CorrelationChartInfo.EndDate)
	//if e != nil {
	//	errMsg = "获取失败"
	//	err = errors.New("获取相关性图表, 图表计算值失败, Err:" + e.Error())
	//	return
	//}
	//periodDataByte, e := json.Marshal(periodData)
	//if e != nil {
	//	errMsg = "获取失败"
	//	err = errors.New("相关性图表, X轴信息有误, Err:" + e.Error())
	//	return
	//}
	//correlationDataByte, e := json.Marshal(correlationData[0].Value)
	//if e != nil {
	//	errMsg = "获取失败"
	//	err = errors.New("相关性图表, Y轴信息有误, Err:" + e.Error())
	//	return
	//}
	//correlationChart.PeriodData = string(periodDataByte)
	//correlationChart.CorrelationData = string(correlationDataByte)

	// 新增图表和指标mapping
	chartInfoId, e := data_manage.CreateCorrelationChartAndEdb(chartInfo, mapList, correlationChart)
	if e != nil {
		errMsg = "操作失败"
		err = errors.New("新增相关性图表失败, Err: " + e.Error())
		return
	}

	//添加es数据
	go data.EsAddOrEditChartInfo(chartInfoId)

	return
}

// CopyChartInfo 复制图表
func CopyChartInfo(configId, classifyId int, chartName string, correlationChartInfoReq data_manage.CorrelationChartInfoReq, sysUser *system.Admin) (chartInfo *data_manage.ChartInfo, err error, errMsg string, isSendEmail bool) {
	configSource := 2
	isSendEmail = true
	// 获取相关性图的配置
	multipleGraphConfigChartMapping, err := data_manage.GetMultipleGraphConfigChartMappingByIdAndSource(configId, configSource)
	if err != nil {
		return
	}
	multipleGraphConfig, err := data_manage.GetMultipleGraphConfigById(configId)
	if err != nil {
		return
	}
	multipleGraphConfig.MultipleGraphConfigId = 0
	err = data_manage.AddMultipleGraphConfig(multipleGraphConfig)
	if err != nil {
		return
	}

	// 添加图
	addChartReq := data_manage.AddChartInfoReq{
		ChartClassifyId:      classifyId,
		ChartName:            chartName,
		ChartType:            utils.CHART_TYPE_CURVE,
		Calendar:             "公历",
		CorrelationChartInfo: correlationChartInfoReq,
	}
	chartSource := utils.CHART_SOURCE_CORRELATION // 默认是相关性图
	chartInfo, err, errMsg, isSendEmail = AddChartInfo(addChartReq, chartSource, sysUser)
	if err != nil {
		return
	}

	// 添加关系
	multipleGraphConfigChartMapping = &data_manage.MultipleGraphConfigChartMapping{
		//Id:                    0,
		MultipleGraphConfigId: multipleGraphConfig.MultipleGraphConfigId,
		ChartInfoId:           chartInfo.ChartInfoId,
		Source:                configSource,
		ModifyTime:            time.Now(),
		CreateTime:            time.Now(),
	}
	err = data_manage.AddMultipleGraphConfigChartMapping(multipleGraphConfigChartMapping)
	if err != nil {
		return
	}

	//添加es数据
	go data.EsAddOrEditChartInfo(chartInfo.ChartInfoId)

	return
}