package models

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

type BaseFromTradeZhengzhouIndex struct {
	BaseFromTradeZhengzhouIndexId int `orm:"column(base_from_trade_zhengzhou_index_id);pk"`
	Rank                          int
	DealShortName                 string
	DealName                      string
	DealCode                      string
	DealValue                     string
	DealChange                    int
	BuyShortName                  string
	BuyName                       string
	BuyCode                       string
	BuyValue                      string
	BuyChange                     int
	SoldShortName                 string
	SoldName                      string
	SoldCode                      string
	SoldValue                     string
	SoldChange                    int
	Frequency                     string
	ClassifyName                  string
	ClassifyType                  string
	CreateTime                    time.Time
	ModifyTime                    time.Time
	DataTime                      string
}

type BaseFromZzDataSimple struct {
	Id        int `orm:"column(base_from_trade_zhengzhou_index_id);pk"`
	DealCode  string
	BuyCode   string
	SoldCode  string
	DataTime  string
	DealValue string
	BuyValue  string
	SoldValue string
}

func GetBaseFromZhengzhouDataAllByIndexCode(indexCode, suffix string) (list []*BaseFromTradeZhengzhouIndex, err error) {
	o := orm.NewOrm()
	sql := `SELECT * FROM base_from_trade_zhengzhou_index WHERE %s_code=? `
	sql = fmt.Sprintf(sql, suffix)
	_, err = o.Raw(sql, indexCode).QueryRows(&list)
	return
}

func GetZzDataByTradeCode(condition string, pars []interface{}) (item []*BaseFromZzDataSimple, err error) {
	sql := ` SELECT * FROM base_from_trade_zhengzhou_index WHERE 1=1 `
	o := orm.NewOrm()
	if condition != "" {
		sql += condition
	}
	sql += ` ORDER BY data_time DESC `
	_, err = o.Raw(sql, pars).QueryRows(&item)
	return
}

// 新增郑商所指标数据
func AddEdbDataFromZz(edbCode string) (err error) {
	var suffix string
	if strings.Contains(edbCode, "deal") {
		suffix = "deal"
	} else if strings.Contains(edbCode, "buy") {
		suffix = "buy"
	} else if strings.Contains(edbCode, "sold") {
		suffix = "sold"
	}

	o := orm.NewOrm()

	zzBaseDataAll, err := GetBaseFromZhengzhouDataAllByIndexCode(edbCode, suffix)
	if err != nil && err.Error() != utils.ErrNoRow() {
		return
	}

	var isAdd bool
	addSql := ` INSERT INTO edb_data_zz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
	existMap := make(map[string]string)
	for _, sv := range zzBaseDataAll {
		eDate := sv.DataTime
		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
		if err != nil {
			fmt.Println("time.Parse Err:" + eDate)
			return err
		}
		timestamp := dataTime.UnixNano() / 1e6
		timeStr := fmt.Sprintf("%d", timestamp)
		if _, ok := existMap[eDate]; !ok {
			if suffix == "deal" {
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.DealValue)
			} else if suffix == "buy" {
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.BuyValue)
			} else {
				addSql += GetAddSql("0", edbCode, eDate, timeStr, sv.SoldValue)
			}
			isAdd = true
		}
		if suffix == "deal" {
			existMap[eDate] = sv.DealValue
		} else if suffix == "buy" {
			existMap[eDate] = sv.BuyValue
		} else {
			existMap[eDate] = sv.SoldValue
		}
	}
	if isAdd {
		addSql = strings.TrimRight(addSql, ",")
		utils.FileLog.Info("addSql:" + addSql)
		_, err = o.Raw(addSql).Exec()
		if err != nil {
			return err
		}
	}
	return
}

// 刷新郑商所指标数据
func RefreshEdbDataFromZz(edbInfoId int, edbCode, startDate string) (err error) {
	source := utils.DATA_SOURCE_ZZ
	subSource := utils.DATA_SUB_SOURCE_DATE

	o := orm.NewOrm()
	if err != nil {
		return
	}
	var suffix string
	if strings.Contains(edbCode, "deal") {
		suffix = "deal"
	} else if strings.Contains(edbCode, "buy") {
		suffix = "buy"
	} else if strings.Contains(edbCode, "sold") {
		suffix = "sold"
	}
	edbInfoIdStr := strconv.Itoa(edbInfoId)
	//计算数据
	var condition string
	var pars []interface{}

	if edbCode != "" {
		if suffix == "deal" {
			condition += " AND deal_code=? "
		} else if suffix == "buy" {
			condition += " AND buy_code=? "
		} else {
			condition += " AND sold_code=? "
		}
		pars = append(pars, edbCode)
	}

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

	glDataList, err := GetZzDataByTradeCode(condition, pars)
	if err != nil {
		return err
	}

	// 真实数据的最大日期  , 插入规则配置的日期
	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 existCondition string
	var existPars []interface{}

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

	existList, err := GetEdbDataByCondition(source, subSource, existCondition, existPars)
	if err != nil {
		return err
	}
	existMap := make(map[string]*EdbInfoSearchData)
	for _, v := range existList {
		existMap[v.DataTime] = v
	}

	addSql := ` INSERT INTO edb_data_zz(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
	var isAdd bool
	for _, v := range glDataList {
		var value string
		if suffix == "deal" {
			value = v.DealValue
		} else if suffix == "buy" {
			value = v.BuyValue
		} else {
			value = v.SoldValue
		}
		item := v
		itemValue := value
		if _, ok := existMap[v.DataTime]; !ok {
			eDate := item.DataTime
			sValue := itemValue
			dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
			if err != nil {
				return err
			}

			if sValue != "" {
				timestamp := dataTime.UnixNano() / 1e6
				timeStr := fmt.Sprintf("%d", timestamp)
				saveValue := sValue

				if findItem, ok := existMap[eDate]; !ok {
					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, saveValue)
					isAdd = true
				} else {
					if findItem != nil && utils.SubFloatToString(findItem.Value, 30) != sValue {
						err = ModifyEdbDataById(source, subSource, findItem.EdbDataId, sValue)
						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
}