package data

import (
	"encoding/json"
	"errors"
	"eta/eta_chart_lib/models"
	"eta/eta_chart_lib/models/data_manage"
	"eta/eta_chart_lib/models/data_manage/excel"
	"eta/eta_chart_lib/utils"
	"fmt"
	"math"
	"sort"
	"strings"
	"time"
)

func GetBalanceExcelChartDetail(chartInfo *models.ChartInfo, mappingListTmp []*excel.ExcelChartEdb, dataListMap map[int][]*models.EdbDataList) (resp *models.ChartInfoDetailResp, err error, errMsg string) {
	chartInfoId := chartInfo.ChartInfoId
	resp = new(models.ChartInfoDetailResp)

	// 获取主题样式
	chartTheme, err := GetChartThemeConfig(chartInfo.ChartThemeId, 1, chartInfo.ChartType)
	if err != nil {
		errMsg = "获取失败"
		err = fmt.Errorf(" 获取主题信息失败 Err:%s", err.Error())
		return
	}
	chartInfo.ChartThemeStyle = chartTheme.Config
	chartInfo.ChartThemeId = chartTheme.ChartThemeId

	dateType := chartInfo.DateType
	fmt.Println("dateType:", dateType)

	chartType := chartInfo.ChartType
	startDate := chartInfo.StartDate
	endDate := chartInfo.EndDate
	seasonStartDate := chartInfo.SeasonStartDate
	seasonEndDate := chartInfo.SeasonEndDate
	startYear := chartInfo.StartYear

	calendar := chartInfo.Calendar

	if calendar == "" {
		calendar = "公历"
	}

	mappingList, err := TransferChartEdbToEdbMappingFormat(chartInfoId, chartType, mappingListTmp, dataListMap)
	if err != nil {
		return
	}
	if chartType == 2 {
		startDate = seasonStartDate
		endDate = seasonEndDate
		if dateType <= 0 {
			if startDate != "" {
				dateType = 5
			} else {
				dateType = utils.DateTypeNYears
			}
		}
	} else {
		if dateType <= 0 {
			dateType = 3
		}
	}
	yearMax := 0
	if dateType == utils.DateTypeNYears {
		for _, v := range mappingList {
			if v.LatestDate != "" {
				lastDateT, tErr := time.Parse(utils.FormatDate, v.LatestDate)
				if tErr != nil {
					errMsg = "获取失败"
					err = fmt.Errorf("获取图表日期信息失败,Err:" + tErr.Error())
					return
				}
				if lastDateT.Year() > yearMax {
					yearMax = lastDateT.Year()
				}
			}
		}
	}
	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, yearMax)

	if chartInfo.ChartType == 2 {
		chartInfo.StartDate = startDate
		chartInfo.EndDate = endDate
	}
	// 图表额外数据参数
	extraConfigStr := chartInfo.ExtraConfig
	// 柱方图的一些配置
	var barConfig data_manage.BarChartInfoReq
	if chartInfo != nil && chartInfo.ChartType == 7 {
		if chartInfo.BarConfig == `` {
			err = fmt.Errorf("柱方图未配置")
			errMsg = "柱方图未配置"
			return
		}
		err = json.Unmarshal([]byte(chartInfo.BarConfig), &barConfig)
		if err != nil {
			err = fmt.Errorf("柱方图配置异常 json.Unmarshal Err:%s", err.Error())
			errMsg = "柱方图配置异常"
			return
		}
		extraConfigStr = chartInfo.BarConfig
	}
	// 获取表格数据

	excelChartInfoDataShow := new(ExcelChartInfoDataShow)
	excelChartInfoDataShow.DataListMap = dataListMap

	// 获取图表中的指标数据
	edbList, xEdbIdValue, yDataList, dataResp, e, msg := GetChartEdbDataV2(chartInfoId, chartType, calendar, startDate, endDate, mappingList, extraConfigStr, chartInfo.SeasonExtraConfig, excelChartInfoDataShow)
	if e != nil {
		err = fmt.Errorf("获取图表,指标数据失败,Err:%s", e.Error())
		errMsg = msg
		return
	}

	for _, v := range edbList {
		// 指标别名
		if barConfig.EdbInfoIdList != nil && len(barConfig.EdbInfoIdList) > 0 {
			for _, reqEdb := range barConfig.EdbInfoIdList {
				if v.EdbInfoId == reqEdb.EdbInfoId {
					v.EdbAliasName = reqEdb.Name
				}
			}
		}
	}
	// 图表的指标来源
	sourceNameList, sourceNameEnList := GetEdbSourceByEdbInfoIdList(edbList)

	chartInfo.ChartSource = strings.Join(sourceNameList, ",")
	chartInfo.ChartSourceEn = strings.Join(sourceNameEnList, ",")

	resp.EdbInfoList = edbList
	resp.XEdbIdValue = xEdbIdValue
	resp.YDataList = yDataList
	resp.DataResp = dataResp

	resp.ChartInfo = chartInfo
	return
}

// GetBalanceExcelEdbDataMapList 获取指标最后的基础数据
func GetBalanceExcelEdbDataMapList(chartInfoId, chartType int, calendar, startDate, endDate string, mappingList []*models.ChartEdbInfoMapping, seasonExtraConfig string, dataListMap map[int][]*models.EdbDataList) (edbDataListMap map[int][]*models.EdbDataList, edbList []*models.ChartEdbInfoMapping, err error) {
	// 指标对应的所有数据
	edbDataListMap = make(map[int][]*models.EdbDataList)

	for _, v := range mappingList {
		//fmt.Println("v:", v.EdbInfoId)
		item := new(models.ChartEdbInfoMapping)
		item.EdbInfoId = v.EdbInfoId
		item.SourceName = v.SourceName
		item.Source = v.Source
		item.EdbCode = v.EdbCode
		item.EdbName = v.EdbName
		item.EdbNameEn = v.EdbNameEn
		item.Frequency = v.Frequency
		item.EdbType = v.EdbType
		item.FrequencyEn = GetFrequencyEn(v.Frequency)
		if v.Unit != `无` {
			item.Unit = v.Unit
		}
		item.UnitEn = v.UnitEn
		item.StartDate = v.StartDate
		item.EndDate = v.EndDate
		item.ModifyTime = v.ModifyTime
		item.EdbInfoCategoryType = v.EdbInfoCategoryType
		item.PredictChartColor = v.PredictChartColor
		if chartInfoId <= 0 {
			item.IsAxis = 1
			item.LeadValue = 0
			item.LeadUnit = ""
			item.ChartEdbMappingId = 0
			item.ChartInfoId = 0
			item.IsOrder = false
			item.EdbInfoType = 1
			item.ChartStyle = ""
			item.ChartColor = ""
			item.ChartWidth = 1
			item.MaxData = v.MaxValue
			item.MinData = v.MinValue
		} else {
			item.IsAxis = v.IsAxis
			item.EdbInfoType = v.EdbInfoType
			item.LeadValue = v.LeadValue
			item.LeadUnit = v.LeadUnit
			item.LeadUnitEn = GetLeadUnitEn(v.LeadUnit)
			item.ChartEdbMappingId = v.ChartEdbMappingId
			item.ChartInfoId = v.ChartInfoId
			item.ChartStyle = v.ChartStyle
			item.ChartColor = v.ChartColor
			item.ChartWidth = v.ChartWidth
			item.IsOrder = v.IsOrder
			item.MaxData = v.MaxData
			item.MinData = v.MinData
		}
		item.LatestValue = v.LatestValue
		item.LatestDate = v.LatestDate
		item.UniqueCode = v.UniqueCode
		item.MoveLatestDate = v.LatestDate
		item.EdbAliasName = v.EdbAliasName
		item.IsConvert = v.IsConvert
		item.ConvertType = v.ConvertType
		item.ConvertValue = v.ConvertValue
		item.ConvertUnit = v.ConvertUnit
		item.ConvertEnUnit = v.ConvertEnUnit

		var startDateReal string
		var diffSeconds int64
		if chartType == 2 { //季节性图
			startDateReal = startDate
		} else {
			if v.EdbInfoType == 0 && v.LeadUnit != "" && v.LeadValue > 0 { //领先指标
				var startTimeRealTemp time.Time
				startDateParse, _ := time.Parse(utils.FormatDate, startDate)
				switch v.LeadUnit {
				case "天":
					startTimeRealTemp = startDateParse.AddDate(0, 0, -v.LeadValue)
				case "月":
					startTimeRealTemp = startDateParse.AddDate(0, -v.LeadValue, 0)
				case "季":
					startTimeRealTemp = startDateParse.AddDate(0, -3*v.LeadValue, 0)
				case "周":
					startTimeRealTemp = startDateParse.AddDate(0, 0, -7*v.LeadValue)
				case "年":
					startTimeRealTemp = startDateParse.AddDate(-v.LeadValue, 0, 0)
				}
				if startTimeRealTemp.Before(startDateParse) {
					startDateReal = startTimeRealTemp.Format(utils.FormatDate)
					diffSeconds = (int64(startTimeRealTemp.UnixNano()) - int64(startDateParse.UnixNano())) / 1e6
				} else {
					startDateReal = startDate
					diffSeconds = 0
				}

				// 预测指标的开始日期也要偏移
				{
					day, tmpErr := utils.GetDaysBetween2Date(utils.FormatDate, startDate, startDateReal)
					if tmpErr != nil {
						err = tmpErr
						return
					}
					moveLatestDateTime, tmpErr := time.ParseInLocation(utils.FormatDate, item.MoveLatestDate, time.Local)
					if tmpErr != nil {
						err = tmpErr
						return
					}
					item.MoveLatestDate = moveLatestDateTime.AddDate(0, 0, day).Format(utils.FormatDate)
				}
			} else {
				startDateReal = startDate
			}
		}
		//fmt.Println("line 1011 chart:", v.Source, v.EdbInfoId, startDateReal, endDate)
		calendarPreYear := 0
		if calendar == "农历" {
			newStartDateReal, e := time.Parse(utils.FormatDate, startDateReal)
			if e != nil {
				err = fmt.Errorf("时间解析 time.Parse(%s, %s) error: %v", utils.FormatDate, startDateReal, e)
				return
			}
			calendarPreYear = newStartDateReal.Year() - 1
			newStartDateReal = newStartDateReal.AddDate(-1, 0, 0)
			startDateReal = newStartDateReal.Format(utils.FormatDate)
		}
		dataList := make([]*models.EdbDataList, 0)
		dataListTmp, ok := dataListMap[v.EdbInfoId]
		if ok {
			dataList = dataListTmp
			// 对dataList 根据dataTimestamp 进行排序
			sort.Slice(dataList, func(i, j int) bool {
				return dataList[i].DataTimestamp < dataList[j].DataTimestamp
			})
		} else {
			//err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.EdbInfoId))
			utils.FileLog.Info(fmt.Sprintf("获取失败,指标数据异常 %d", v.EdbInfoId))
		}
		if v.IsConvert == 1 {
			switch v.ConvertType {
			case 1:
				for i, data := range dataList {
					dataList[i].Value = data.Value * v.ConvertValue
				}
				//item.MaxData = item.MaxData * v.ConvertValue
				//item.MinData = item.MinData * v.ConvertValue
			case 2:
				for i, data := range dataList {
					dataList[i].Value = data.Value / v.ConvertValue
				}
				//item.MaxData = item.MaxData / v.ConvertValue
				//item.MinData = item.MinData / v.ConvertValue
			case 3:
				for i, data := range dataList {
					if data.Value <= 0 {
						err = errors.New("数据中含有负数或0,无法对数运算")
						return
					}
					dataList[i].Value = math.Log(data.Value) / math.Log(v.ConvertValue)
				}
				//item.MaxData = math.Log(item.MaxData) / math.Log(v.ConvertValue)
				//item.MinData = math.Log(item.MinData) / math.Log(v.ConvertValue)
			}
		}

		edbDataListMap[v.EdbInfoId] = dataList

		if diffSeconds != 0 && v.EdbInfoType == 0 {
			dataListLen := len(dataList)
			for i := 0; i < dataListLen; i++ {
				dataList[i].DataTimestamp = dataList[i].DataTimestamp - diffSeconds
			}
		}

		if chartType == 2 {
			latestDate, tmpErr := time.Parse(utils.FormatDate, v.LatestDate)
			if tmpErr != nil {
				//item.DataList = dataList
				item.IsNullData = true
				edbList = append(edbList, item)
				continue
			}

			if calendar == "农历" {
				if len(dataList) <= 0 {
					result := new(models.EdbDataResult)
					item.DataList = result
				} else {
					result, tmpErr := models.AddCalculateQuarterV6(dataList)
					if tmpErr != nil {
						err = errors.New("获取农历数据失败,Err:" + tmpErr.Error())
						return
					}
					quarterDataList, tErr := GetSeasonEdbInfoDataListByXDateNong(result, latestDate, seasonExtraConfig, calendarPreYear)
					if tErr != nil {
						err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
						return
					}
					item.DataList = quarterDataList
				}

			} else {
				quarterDataList, tErr := GetSeasonEdbInfoDataListByXDate(dataList, latestDate, seasonExtraConfig)
				if tErr != nil {
					err = errors.New("获取季节性图表数据失败,Err:" + tErr.Error())
					return
				}
				item.DataList = quarterDataList
			}

		} else if chartType == 7 || chartType == utils.CHART_TYPE_RADAR { //柱方图
			//item.DataList = dataList
		} else {
			item.DataList = dataList
		}
		edbList = append(edbList, item)
	}

	return
}
func getBalanceDataListStartDateAndValue(dataList []*models.EdbDataList) (startDate, endDate string, startVal, endVal, maxVal, minVal float64) {
	if len(dataList) == 0 {
		return
	}
	startDate = dataList[0].DataTime
	startVal = dataList[0].Value
	maxVal = dataList[0].Value
	minVal = dataList[0].Value
	endDate = dataList[len(dataList)-1].DataTime
	endVal = dataList[len(dataList)-1].Value
	for _, v := range dataList {
		if v.DataTime < startDate {
			startDate = v.DataTime
			startVal = v.Value
		}
		if v.DataTime > endDate {
			endDate = v.DataTime
			endVal = v.Value
		}
		if v.Value > maxVal {
			maxVal = v.Value
		}
		if v.Value < minVal {
			minVal = v.Value
		}
	}
	return
}

func TransferChartEdbToEdbMappingFormat(chartInfoId, chartType int, mappingListTmp []*excel.ExcelChartEdb, dataListMap map[int][]*models.EdbDataList) (mappingList []*models.ChartEdbInfoMapping, err error) {
	mappingList = make([]*models.ChartEdbInfoMapping, 0)
	//循环组装映射关系
	for _, v := range mappingListTmp {
		dataList := make([]*models.EdbDataList, 0)
		dataListTmp, ok := dataListMap[v.ExcelChartEdbId]
		if ok {
			dataList = dataListTmp
		} else {
			//err = errors.New(fmt.Sprint("获取失败,指标类型异常", v.ExcelChartEdbId))
			utils.FileLog.Info(fmt.Sprintf("获取失败,指标数据异常 %d", v.ExcelChartEdbId))
		}
		startDateStr, endDateStr, _, endVal, maxValue, minValue := getBalanceDataListStartDateAndValue(dataList)
		mapping := &models.ChartEdbInfoMapping{
			EdbInfoId:         v.ExcelChartEdbId,
			SourceName:        "平衡表",
			Source:            0,
			SubSource:         0,
			EdbCode:           v.EdbCode,
			EdbName:           v.EdbName,
			EdbAliasName:      v.EdbName,
			EdbNameEn:         v.EdbNameEn,
			EdbAliasNameEn:    "",
			EdbType:           0,
			Frequency:         "",
			FrequencyEn:       "",
			Unit:              v.Unit,
			UnitEn:            v.UnitEn,
			StartDate:         startDateStr,
			EndDate:           endDateStr,
			ModifyTime:        v.ModifyTime.Format(utils.FormatDateTime),
			ChartEdbMappingId: v.ExcelChartEdbId,
			ChartInfoId:       chartInfoId,
			MaxData:           v.MaxData,
			MinData:           v.MinData,
			IsOrder:           v.IsOrder,
			IsAxis:            v.IsAxis,
			EdbInfoType:       v.EdbInfoType,
			//EdbInfoCategoryType: 0,
			LeadValue:         v.LeadValue,
			LeadUnit:          v.LeadUnit,
			LeadUnitEn:        "",
			ChartStyle:        "",
			ChartColor:        "",
			PredictChartColor: "",
			ChartWidth:        v.ChartWidth,
			ChartType:         chartType,
			LatestDate:        endDateStr,
			LatestValue:       endVal,
			MoveLatestDate:    "",
			UniqueCode:        "",
			MinValue:          minValue,
			MaxValue:          maxValue,
			DataList:          nil,
			IsNullData:        false,
			MappingSource:     0,
			IsConvert:         0,
			ConvertType:       0,
			ConvertValue:      0,
			ConvertUnit:       "",
			ConvertEnUnit:     "",
		}
		mappingList = append(mappingList, mapping)
	}
	return
}