package models

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

type BaseFromTradeShIndex struct {
	BaseFromTradeShIndexId int `orm:"column(base_from_trade_shanghai_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 BaseFromShDataSimple struct {
	Id        int `orm:"column(base_from_trade_shanghai_index_id);pk"`
	DealCode  string
	BuyCode   string
	SoldCode  string
	DataTime  string
	DealValue string
	BuyValue  string
	SoldValue string
}

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

func GetShDataByTradeCode(condition string, pars []interface{}) (item []*BaseFromShDataSimple, err error) {
	sql := ` SELECT * FROM base_from_trade_shanghai_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 AddEdbDataFromSh(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()

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

	var isAdd bool
	addSql := ` INSERT INTO edb_data_sh(edb_info_id,edb_code,data_time,value,create_time,modify_time,data_timestamp) values `
	existMap := make(map[string]string)

	for _, sv := range shBaseDataAll {
		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 RefreshEdbDataFromSh(edbInfoId int, edbCode, startDate string) (err error) {
	source := utils.DATA_SOURCE_SH
	subSource := utils.DATA_SUB_SOURCE_EDB

	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 := GetShDataByTradeCode(condition, pars)
	if err != nil {
		return
	}

	// 真实数据的最大日期  , 插入规则配置的日期
	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_sh(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
		eDate := item.DataTime
		dataTime, err := time.ParseInLocation(utils.FormatDate, eDate, time.Local)
		if err != nil {
			return err
		}
		if _, ok := existMap[v.DataTime]; !ok {
			sValue := itemValue
			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
}

type RefreshSHExchangeReq struct {
	Url      string `description:"交易所链接"`
	Exchange string `description:"交易所"`
	Date     string `description:"日期"`
	Data     SHMessage
}

type Position []struct {
	ContractCode     string      `json:"INSTRUMENTID"`
	ProductSortNo    int         `json:"PRODUCTSORTNO"`
	Rank             int         `json:"RANK"`
	ParticipantID1   string      `json:"PARTICIPANTID1"`
	ParticipantName1 string      `json:"PARTICIPANTABBR1"`
	Deal             interface{} `json:"CJ1"`
	Change1          interface{} `json:"CJ1_CHG"`
	ParticipantID2   string      `json:"PARTICIPANTID2"`
	ParticipantName2 string      `json:"PARTICIPANTABBR2"`
	BuyIn            interface{} `json:"CJ2"`
	Change2          interface{} `json:"CJ2_CHG"`
	ParticipantID3   string      `json:"PARTICIPANTID3"`
	ParticipantName3 string      `json:"PARTICIPANTABBR3"`
	SoldOut          interface{} `json:"CJ3"`
	Change3          interface{} `json:"CJ3_CHG"`
	ProductName      string      `json:"PRODUCTNAME"`
}

type SHMessage struct {
	Position   Position `json:"o_cursor"`
	Length     string   `json:"showlength"`
	Code       string   `json:"o_code"`
	Msg        string   `json:"o_msg"`
	ReportDate string   `json:"report_date"`
	UpdateDate string   `json:"update_date"`
	PrintDate  string   `json:"print_date"`
}

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

func AddBaseFromTradeShangHaiIndex(item *BaseFromTradeShanghaiIndex) (lastId int64, err error) {
	o := orm.NewOrm()
	lastId, err = o.Insert(item)
	return
}

func GetBaseFromTradeShangHaiIndexAll(dateStr string) (list []*BaseFromTradeShanghaiIndex, err error) {
	o := orm.NewOrm()
	sql := `SELECT * FROM base_from_trade_shanghai_index WHERE data_time=?`
	_, err = o.Raw(sql, dateStr).QueryRows(&list)
	return
}

func ModifyBaseFromTradeShangHaiIndex(dealValue, buyValue, soldValue int, dataId int) (err error) {
	o := orm.NewOrm()
	sql := `UPDATE base_from_trade_shanghai_index SET deal_value=?,buy_value=?,sold_value=?,modify_time=NOW() WHERE base_from_trade_shanghai_index_id=? `
	_, err = o.Raw(sql, dealValue, buyValue, soldValue, dataId).Exec()
	return
}