package models

import (
	"eta/eta_index_lib/services/alarm_msg"
	"eta/eta_index_lib/utils"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"strconv"
	"strings"
	"time"
)

type EdbDataFromThs struct {
	DataVol   int64       `json:"dataVol"`
	Errmsg    string      `json:"errmsg"`
	Errorcode int64       `json:"errorcode"`
	Perf      interface{} `json:"perf"`
	Tables    []Tables    `json:"tables"`
}

// Tables 表格数据
type Tables struct {
	ID    []string  `json:"id"`
	Time  []string  `json:"time"`
	Value []float64 `json:"value"`
}

// 新增同花顺指标数据
func AddEdbDataFromThs(edbCode string, item EdbDataFromThs) (err error) {
	var errMsg string
	o := orm.NewOrm()
	defer func() {
		if err != nil {
			//go utils.SendEmail(utils.APP_NAME_CN+"【"+utils.RunMode+"】"+"失败提醒", " 同花顺数据获取失败:err:"+errMsg, utils.EmailSendToUsers)
			go alarm_msg.SendAlarmMsg("同花顺数据获取失败:err:"+errMsg, 3)
		}
	}()

	if len(item.Tables) > 0 {
		table := item.Tables[0]
		dataLen := len(table.Time)

		var isAdd bool
		addSql := ` INSERT INTO %s(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
		tableName := GetEdbDataTableName(utils.DATA_SOURCE_THS, utils.DATA_SUB_SOURCE_EDB)
		addSql = fmt.Sprintf(addSql, tableName)

		for i := 0; i < dataLen; i++ {
			eDate := table.Time[i]
			sValue := table.Value[i]
			dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
			if err != nil {
				errMsg = " time.Parse :" + err.Error()
				return err
			}
			timestamp := dataTime.UnixNano() / 1e6
			timeStr := fmt.Sprintf("%d", timestamp)
			addSql += GetAddSql("0", edbCode, eDate, timeStr, utils.SubFloatToString(sValue, 20))
			isAdd = true
		}
		if isAdd {
			addSql = strings.TrimRight(addSql, ",")
			_, err = o.Raw(addSql).Exec()
			if err != nil {
				errMsg = " tx.Exec Err :" + err.Error()
				return
			}
		}
	}
	return
}

// 刷新同花顺指标数据
func RefreshEdbDataFromThs(edbInfoId int, edbCode, startDate string, item EdbDataFromThs) (err error) {
	o := orm.NewOrm()
	source := utils.DATA_SOURCE_THS
	subSource := utils.DATA_SUB_SOURCE_DATE

	// 真实数据的最大日期  , 插入规则配置的日期
	var realDataMaxDate, edbDataInsertConfigDate time.Time
	var edbDataInsertConfig *EdbDataInsertConfig
	var isFindConfigDateRealData bool //是否找到配置日期的实际数据的值
	{
		edbDataInsertConfig, err = GetEdbDataInsertConfigByEdbId(edbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			return
		}
		if edbDataInsertConfig != nil {
			edbDataInsertConfigDate = edbDataInsertConfig.Date
		}
	}

	if len(item.Tables) > 0 {
		var condition string
		var pars []interface{}

		condition += " AND edb_info_id=? "
		pars = append(pars, edbInfoId)
		if startDate != "" {
			condition += " AND data_time>=? "
			pars = append(pars, startDate)
		}

		existList, err := GetEdbDataByCondition(source, subSource, condition, pars)
		if err != nil {
			return err
		}

		existMap := make(map[string]*EdbInfoSearchData)
		for _, v := range existList {
			existMap[v.DataTime] = v
		}

		table := item.Tables[0]
		dataLen := len(table.Time)
		addSql := ` INSERT INTO edb_data_ths(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
		var isAdd bool
		addMap := make(map[string]string)
		edbInfoIdStr := strconv.Itoa(edbInfoId)
		for i := 0; i < dataLen; i++ {
			eDate := table.Time[i]
			sValue := table.Value[i]
			sValueStr := utils.SubFloatToString(sValue, 30)

			dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
			if err != nil {
				return err
			}
			if findItem, ok := existMap[eDate]; !ok {
				if _, addOk := addMap[eDate]; !addOk {
					timestamp := dataTime.UnixNano() / 1e6
					timeStr := fmt.Sprintf("%d", timestamp)
					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, sValueStr)
					isAdd = true
					addMap[eDate] = sValueStr
				}
			} else {
				if findItem != nil && utils.SubFloatToString(findItem.Value, 30) != utils.SubFloatToString(sValue, 30) {
					err = ModifyEdbDataById(source, subSource, findItem.EdbDataId, sValueStr)
					if err != nil {
						return err
					}
				}
			}

			// 下面代码主要目的是处理掉手动插入的数据判断
			{
				if realDataMaxDate.IsZero() || dataTime.After(realDataMaxDate) {
					realDataMaxDate = dataTime
				}
				if edbDataInsertConfigDate.IsZero() || dataTime.Equal(edbDataInsertConfigDate) {
					isFindConfigDateRealData = true
				}
			}
		}

		// 处理手工数据补充的配置
		HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfoId, source, subSource, existMap, isFindConfigDateRealData)

		if isAdd {
			addSql = strings.TrimRight(addSql, ",")
			_, err = o.Raw(addSql).Exec()
			if err != nil {
				return err
			}
		}
	}
	return
}