package data

import (
	"errors"
	"eta/eta_mobile/models/data_manage"
	"eta/eta_mobile/utils"
	"fmt"
	"github.com/shopspring/decimal"
	"time"
)

// GetEdbDataTbz 获取指标的同比值数据
func GetEdbDataTbz(edbInfo *data_manage.EdbInfo, tmpDataList []*data_manage.EdbDataList, startDateTime time.Time) (dataList []*data_manage.EdbDataList, minValue, maxValue float64, err error) {
	dataList = make([]*data_manage.EdbDataList, 0)

	// 数据处理
	var dateArr []string
	dataMap := make(map[string]*data_manage.EdbDataList)
	for _, v := range tmpDataList {
		dateArr = append(dateArr, v.DataTime)
		dataMap[v.DataTime] = v
	}
	for _, av := range dateArr {
		currentItem, ok := dataMap[av]
		// 如果找不到当前日期的数据,那么终止当前循环,进入下一循环
		if !ok {
			continue
		}
		tmpItem := *currentItem
		var isOk bool //是否计算出来结果

		//当前日期
		currentDate, tmpErr := time.ParseInLocation(utils.FormatDate, av, time.Local)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		// 如果存在开始日期,同时,当前日期早于开始日期,那么终止当前循环,进入下一循环
		if !startDateTime.IsZero() && currentDate.Before(startDateTime) {
			continue
		}
		//上一年的日期
		preDate := currentDate.AddDate(-1, 0, 0)
		preDateStr := preDate.Format(utils.FormatDate)
		if findItem, ok := dataMap[preDateStr]; ok { //上一年同期找到
			tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
			isOk = true
		} else {
			if edbInfo.Frequency == "月度" { //向上和向下，各找一个月
				for i := 0; i <= 35; i++ {
					nextDateDay := preDate.AddDate(0, 0, i)
					nextDateDayStr := nextDateDay.Format(utils.FormatDate)
					if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
						tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
						isOk = true
						break
					} else {
						preDateDay := preDate.AddDate(0, 0, -i)
						preDateDayStr := preDateDay.Format(utils.FormatDate)
						if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
							tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
							isOk = true
							break
						}
					}
				}
			} else if edbInfo.Frequency == "季度" || edbInfo.Frequency == "年度" {
				if findItem, ok := dataMap[preDateStr]; ok { //上一年同期->下一个月找到
					tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
					isOk = true
					break
				}
			} else {
				nextDateDay := preDate.AddDate(0, 0, 1)
				nextDateDayStr := nextDateDay.Format(utils.FormatDate)

				preDateDay := preDate.AddDate(0, 0, -1)
				preDateDayStr := preDateDay.Format(utils.FormatDate)

				for i := 0; i < 35; i++ {
					if i >= 1 {
						nextDateDay = nextDateDay.AddDate(0, 0, i)
						nextDateDayStr = nextDateDay.Format(utils.FormatDate)
					}
					if findItem, ok := dataMap[nextDateDayStr]; ok { //上一年同期->下一个月找到
						tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
						isOk = true
						break
					} else {
						if i >= 1 {
							preDateDay = preDate.AddDate(0, 0, -i)
							preDateDayStr = nextDateDay.Format(utils.FormatDate)
						}
						if findItem, ok := dataMap[preDateDayStr]; ok { //上一年同期->上一个月找到
							tmpItem.Value = TbzDiv(currentItem.Value, findItem.Value)
							isOk = true
							break
						}
					}
				}
			}
		}

		if isOk {
			if tmpItem.Value > maxValue {
				maxValue = tmpItem.Value
			}
			if tmpItem.Value < minValue {
				minValue = tmpItem.Value
			}
			dataList = append(dataList, &tmpItem)
		}
	}

	return
}

// GetChartEdbSeasonalData 获取指标的季节性数据
func GetChartEdbSeasonalData(calendar, startDate, endDate string, edbInfo *data_manage.EdbInfo) (resultData interface{}, err error) {
	var startDateReal string
	startDateReal = startDate
	calendarPreYear := 0
	if calendar == "农历" {
		newStartDateReal, tmpErr := time.Parse(utils.FormatDate, startDateReal)
		if tmpErr != nil {
			err = tmpErr
			fmt.Println("time.Parse:" + err.Error())
			return
		}
		calendarPreYear = newStartDateReal.Year() - 1
		newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
		startDateReal = newStartDateReal.Format(utils.FormatDate)
	}
	dataList := make([]*data_manage.EdbDataList, 0)

	switch edbInfo.EdbInfoType {
	case 0:
		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, startDateReal, endDate)
	case 1:
		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, startDateReal, endDate, false)
	default:
		err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))
	}
	if err != nil {
		return
	}

	latestDateStr := edbInfo.LatestDate //实际数据的截止日期
	latestDate, tmpErr := time.Parse(utils.FormatDate, edbInfo.LatestDate)
	if tmpErr != nil {
		err = errors.New(fmt.Sprint("获取最后实际数据的日期失败,Err:" + tmpErr.Error() + ";LatestDate:" + edbInfo.LatestDate))
		return
	}
	latestDateYear := latestDate.Year() //实际数据截止年份

	if calendar == "农历" {
		if len(dataList) <= 0 {
			resultData = new(data_manage.EdbDataResult)
		} else {
			result, tmpErr := data_manage.AddCalculateQuarterV4(dataList)
			if tmpErr != nil {
				err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
				return
			}

			// 处理季节图的截止日期
			for k, edbDataItems := range result.List {
				var cuttingDataTimestamp int64

				// 切割的日期时间字符串
				cuttingDataTimeStr := latestDate.AddDate(0, 0, edbDataItems.BetweenDay).Format(utils.FormatDate)
				//如果等于最后的实际日期，那么遍历找到该日期对应的时间戳，并将其赋值为 切割时间戳
				if edbDataItems.Year >= latestDateYear {
					for _, tmpData := range edbDataItems.Items {
						if tmpData.DataTime == cuttingDataTimeStr {
							cuttingDataTimestamp = tmpData.DataTimestamp
							break
						}
					}
				}
				edbDataItems.CuttingDataTimestamp = cuttingDataTimestamp
				result.List[k] = edbDataItems
			}

			if result.List[0].Year != calendarPreYear {
				itemList := make([]*data_manage.EdbDataList, 0)
				items := new(data_manage.EdbDataItems)
				//items.Year = calendarPreYear
				items.Items = itemList

				newResult := new(data_manage.EdbDataResult)
				newResult.List = append(newResult.List, items)
				newResult.List = append(newResult.List, result.List...)
				resultData = newResult
			} else {
				resultData = result
			}
		}

	} else {
		currentYear := time.Now().Year()

		quarterDataList := make([]*data_manage.QuarterData, 0)
		quarterMap := make(map[int][]*data_manage.EdbDataList)
		var quarterArr []int

		for _, v := range dataList {
			itemDate, tmpErr := time.Parse(utils.FormatDate, v.DataTime)
			if tmpErr != nil {
				err = errors.New("季度指标日期转换,Err:" + tmpErr.Error() + ";DataTime:" + v.DataTime)
				return
			}
			year := itemDate.Year()
			newItemDate := itemDate.AddDate(currentYear-year, 0, 0)
			timestamp := newItemDate.UnixNano() / 1e6
			v.DataTimestamp = timestamp
			if findVal, ok := quarterMap[year]; !ok {
				quarterArr = append(quarterArr, year)
				findVal = append(findVal, v)
				quarterMap[year] = findVal
			} else {
				findVal = append(findVal, v)
				quarterMap[year] = findVal
			}
		}
		for _, v := range quarterArr {
			itemList := quarterMap[v]
			quarterItem := new(data_manage.QuarterData)
			quarterItem.Year = v
			quarterItem.DataList = itemList

			//如果等于最后的实际日期，那么将切割时间戳记录
			if v == latestDateYear {
				var cuttingDataTimestamp int64
				for _, tmpData := range itemList {
					if tmpData.DataTime == latestDateStr {
						cuttingDataTimestamp = tmpData.DataTimestamp
						break
					}
				}
				quarterItem.CuttingDataTimestamp = cuttingDataTimestamp
			} else if v > latestDateYear {
				//如果大于最后的实际日期，那么第一个点就是切割的时间戳
				if len(itemList) > 0 {
					quarterItem.CuttingDataTimestamp = itemList[0].DataTimestamp - 100
				}
			}
			quarterDataList = append(quarterDataList, quarterItem)
		}
		resultData = quarterDataList
	}
	return
}

// TbzDiv 同比值计算
func TbzDiv(a, b float64) float64 {
	var valFloat float64
	if b != 0 {
		af := decimal.NewFromFloat(a)
		bf := decimal.NewFromFloat(b)
		val, _ := af.Div(bf).Float64()
		val = val - 1
		valFloat, _ = decimal.NewFromFloat(val).RoundCeil(4).Float64()
	} else {
		valFloat = 0
	}
	return valFloat
}

// GetDateData 获取指标的单个日期的值
func GetDateData(edbInfo *data_manage.EdbInfo, startDate, endDate string) (item *data_manage.EdbDataList, err error) {
	var dataList []*data_manage.EdbDataList
	switch edbInfo.EdbInfoType {
	case 0:
		dataList, err = data_manage.GetEdbDataList(edbInfo.Source, edbInfo.EdbInfoId, startDate, endDate)
	case 1:
		_, dataList, _, _, err, _ = GetPredictDataListByPredictEdbInfoId(edbInfo.EdbInfoId, startDate, endDate, false)
	default:
		err = errors.New(fmt.Sprint("获取失败,指标类型异常", edbInfo.EdbInfoType))

	}
	if err != nil {
		return
	}

	if len(dataList) <= 0 {
		return
	}

	item = dataList[0]

	return
}
