package models

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

type EdbDataFromWind struct {
	Close     map[string]float64 `json:"CLOSE"`
	Dt        map[string]int64   `json:"DT"`
	ErrorCode map[string]int64   `json:"ErrorCode"`
	ErrMsg    string
}

func AddEdbDataFromWind(edbCode string, item *EdbDataFromWind) (err error) {
	o := orm.NewOrm()

	var isAdd bool
	addSql := ` INSERT INTO edb_data_wind(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
	for k, v := range item.Dt {
		//timeStr := fmt.Sprintf("%d", v)
		v = v / 1000
		t := time.Unix(v, 0)
		dateTime := t.Format(utils.FormatDate)
		t, _ = time.ParseInLocation(utils.FormatDate, dateTime, time.Local) // 这里的目的是为了处理成北京时间,所以多转一遍
		timestamp := t.UnixNano() / 1e6
		timeStr := fmt.Sprintf("%d", timestamp)

		val := item.Close[k]
		saveVal := utils.SubFloatToString(val, 20)
		addSql += GetAddSql("0", edbCode, dateTime, timeStr, saveVal)

		isAdd = true
	}

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

// RefreshEdbDataFromWind 刷新wind指标数据
func RefreshEdbDataFromWind(edbInfoId int, edbCode, startDate string, item *EdbDataFromWind) (err error) {
	o := orm.NewOrm()
	source := utils.DATA_SOURCE_WIND
	subSource := utils.DATA_SUB_SOURCE_EDB

	// 真实数据的最大日期  , 插入规则配置的日期
	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
		}
	}

	var condition string
	var pars []interface{}

	condition += " AND edb_info_id=? "
	pars = append(pars, edbInfoId)

	var startDateTime time.Time
	if startDate != "" {
		condition += " AND data_time>=? "
		pars = append(pars, startDate)
		startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
	}

	existList, err := GetEdbDataByCondition(source, subSource, condition, pars)
	existMap := make(map[string]*EdbInfoSearchData)
	for _, v := range existList {
		existMap[v.DataTime] = v
	}
	addSql := ` INSERT INTO edb_data_wind(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 k, v := range item.Dt {
		//timeStr := fmt.Sprintf("%d", v)
		v = v / 1000
		t := time.Unix(v, 0)
		dateTime := t.Format(utils.FormatDate)
		t, _ = time.ParseInLocation(utils.FormatDate, dateTime, time.Local) // 这里的目的是为了处理成北京时间,所以多转一遍
		timestamp := t.UnixNano() / 1e6
		timeStr := fmt.Sprintf("%d", timestamp)

		val := item.Close[k]
		saveVal := utils.SubFloatToString(val, 30)

		//如果传入的开始时间是空的,且当前数据日期早于传入的开始日期,那么需要判断下当前日期的数据是否存在
		if !startDateTime.IsZero() && t.Before(startDateTime) {
			tmpItem, tmpErr := GetEdbDataByDate(source, subSource, edbCode, dateTime)
			if tmpErr == nil && tmpItem != nil {
				existMap[tmpItem.DataTime] = tmpItem
			}
		}

		if findItem, ok := existMap[dateTime]; !ok {
			if _, existOk := addMap[dateTime]; !existOk {
				isAdd = true
				addSql += GetAddSql(edbInfoIdStr, edbCode, dateTime, timeStr, saveVal)
				addMap[dateTime] = saveVal
			}
		} else {
			if findItem != nil && utils.SubFloatToString(findItem.Value, 30) != saveVal {
				err = ModifyEdbDataById(source, subSource, findItem.EdbDataId, saveVal)
				if err != nil {
					return err
				}
			}
		}

		// 下面代码主要目的是处理掉手动插入的数据判断
		{
			if realDataMaxDate.IsZero() || t.After(realDataMaxDate) {
				realDataMaxDate = t
			}
			if edbDataInsertConfigDate.IsZero() || t.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 {
			fmt.Println("RefreshEdbDataFromWind add Err", err.Error())
			return
		}
	}

	return
}

type ServerUrlCountGroup struct {
	ServerUrl string
	Total     int
}

// GetServerUrlCountGroupByServerUrl 获取服务器地址分组总数
func GetServerUrlCountGroupByServerUrl() (list []ServerUrlCountGroup, err error) {
	o := orm.NewOrm()
	sql := `select server_url,count(1) total from edb_info where source = 2 AND no_update=0 AND server_url != "" group by server_url; `
	_, err = o.Raw(sql).QueryRows(&list)
	return
}