package models

import (
	"eta/eta_index_lib/utils"
	"fmt"
	"github.com/shopspring/decimal"
	"time"
)

// EdbTradeAnalysis 持仓分析指标
type EdbTradeAnalysis struct{}

// GetSource 获取来源编码id
func (obj EdbTradeAnalysis) GetSource() int {
	return utils.DATA_SOURCE_TRADE_ANALYSIS
}

// GetSourceName 获取来源名称
func (obj EdbTradeAnalysis) GetSourceName() string {
	return utils.DATA_SOURCE_NAME_TRADE_ANALYSIS
}

// GetEdbType 获取指标类型
func (obj EdbTradeAnalysis) GetEdbType() int {
	return utils.DEFAULT_EDB_TYPE
}

func (obj EdbTradeAnalysis) Refresh(edbInfo *EdbInfo, convertData []*EdbDataList) (err error) {
	if edbInfo == nil {
		err = fmt.Errorf("指标信息有误, EdbInfo: %v", edbInfo)
		return
	}

	// 真实数据的最大日期, 插入规则配置的日期
	var realDataMaxDate, edbDataInsertConfigDate time.Time
	var edbDataInsertConfig *EdbDataInsertConfig
	var isFindConfigDateRealData bool
	{
		conf, e := GetEdbDataInsertConfigByEdbId(edbInfo.EdbInfoId)
		if e != nil && e.Error() != utils.ErrNoRow() {
			err = fmt.Errorf("GetEdbDataInsertConfigByEdbId err: %v", e)
			return
		}
		edbDataInsertConfig = conf
		if edbDataInsertConfig != nil {
			edbDataInsertConfigDate = edbDataInsertConfig.Date
		}
	}

	// 获取已有数据
	dataOb := new(EdbDataTradeAnalysis)
	dataExists := make(map[string]*EdbDataTradeAnalysis)
	searchExistMap := make(map[string]*EdbInfoSearchData)
	{
		cond := fmt.Sprintf(" AND %s = ?", dataOb.Cols().EdbInfoId)
		pars := make([]interface{}, 0)
		pars = append(pars, edbInfo.EdbInfoId)
		//if queryDate != "" {
		//	cond += fmt.Sprintf(" AND %s >= ?", dataOb.Cols().DataTime)
		//	pars = append(pars, queryDate)
		//}
		list, e := dataOb.GetItemsByCondition(cond, pars, []string{}, "")
		if e != nil {
			err = fmt.Errorf("获取指标数据失败, %v", e)
			return
		}
		for _, v := range list {
			dataExists[v.DataTime.Format(utils.FormatDate)] = v
			searchExistMap[v.DataTime.Format(utils.FormatDate)] = &EdbInfoSearchData{
				EdbDataId:     v.EdbDataId,
				EdbInfoId:     v.EdbInfoId,
				DataTime:      v.DataTime.Format(utils.FormatDate),
				Value:         v.Value,
				EdbCode:       v.EdbCode,
				DataTimestamp: v.DataTimestamp,
			}
		}
	}

	// 比对数据
	insertExist := make(map[string]bool)
	insertData := make([]*EdbDataTradeAnalysis, 0)
	updateData := make([]*EdbDataTradeAnalysis, 0)
	for _, v := range convertData {
		dataDate, e := time.ParseInLocation(utils.FormatDate, v.DataTime, time.Local)
		if e != nil {
			utils.FileLog.Info(fmt.Sprintf("持仓分析-数据日期转换失败, EdbCode: %s, DataDate: %s", edbInfo.EdbCode, v.DataTime))
			continue
		}
		strDate := v.DataTime

		// 手动插入数据的判断
		if realDataMaxDate.IsZero() || dataDate.After(realDataMaxDate) {
			realDataMaxDate = dataDate
		}
		if edbDataInsertConfigDate.IsZero() || dataDate.Equal(edbDataInsertConfigDate) {
			isFindConfigDateRealData = true
		}

		// 入库值
		saveVal := decimal.NewFromFloat(v.Value).Round(4).String()
		d, e := decimal.NewFromString(saveVal)
		if e != nil {
			utils.FileLog.Info(fmt.Sprintf("EdbDataTradeAnalysis NewFromString err: %v", e))
			continue
		}
		saveFloat, _ := d.Float64()

		// 更新
		exists := dataExists[strDate]
		if exists != nil {
			existVal := decimal.NewFromFloat(exists.Value).Round(4).String()
			if saveVal != existVal {
				exists.Value = saveFloat
				updateData = append(updateData, exists)
			}
			continue
		}

		// 新增
		if insertExist[strDate] {
			continue
		}
		insertExist[strDate] = true

		timestamp := dataDate.UnixNano() / 1e6
		insertData = append(insertData, &EdbDataTradeAnalysis{
			EdbInfoId:     edbInfo.EdbInfoId,
			EdbCode:       edbInfo.EdbCode,
			DataTime:      dataDate,
			Value:         saveFloat,
			CreateTime:    time.Now(),
			ModifyTime:    time.Now(),
			DataTimestamp: timestamp,
		})
	}

	// 批量新增/更新
	if len(insertData) > 0 {
		if e := dataOb.CreateMulti(insertData); e != nil {
			err = fmt.Errorf("批量新增指标数据失败, %v", e)
			return
		}
	}
	if len(updateData) > 0 {
		if e := dataOb.MultiUpdateValue(updateData); e != nil {
			err = fmt.Errorf("批量更新指标数据失败, %v", e)
			return
		}
	}

	// 处理手工数据补充的配置
	HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfo.EdbInfoId, obj.GetSource(), 0, searchExistMap, isFindConfigDateRealData)
	return
}

func (obj EdbTradeAnalysis) UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo *EdbInfo) (err error) {
	err, _ = UnifiedModifyEdbInfoMaxAndMinInfo(edbInfo)
	return
}