package data_manage

import (
	"eta/eta_task/global"
	"eta/eta_task/utils"
	"fmt"
	"strconv"
	"strings"
	"time"
)

type ShData struct {
	InputValue string `orm:"column(DATA_VALUE)" description:"日期"`
	DataTime   string `orm:"column(DATA_DATE)" description:"值"`
}

type BaseFromShDataSimple struct {
	Id        int `orm:"column(base_from_trade_shanghai_index_id);pk" gorm:"primaryKey"`
	DealCode  string
	BuyCode   string
	SoldCode  string
	DataTime  string
	DealValue string
	BuyValue  string
	SoldValue string
}

type BaseInfoFromSh struct {
	DealName string
	BuyName  string
	SoldName string
}

type BaseFromTradeShIndex struct {
	BaseFromTradeShIndexId int `orm:"column(base_from_trade_shanghai_index_id);pk" gorm:"primaryKey"`
	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
}

func GetEdbDataShMaxOrMinDate(edbCode string) (minDate, maxDate string, err error) {
	o := global.DbMap[utils.DbNameIndex]
	sql := ` SELECT MIN(data_time) AS minDate,MAX(data_time) AS maxDate FROM edb_data_sh WHERE edb_code=? `
	err = o.Raw(sql, edbCode).Row().Scan(&minDate, &maxDate)
	return
}

// RefreshEdbDataBySh 刷新上期所指标数据
func RefreshEdbDataBySh(edbInfoId int, edbCode, startDate, endDate string) (err error) {
	o := global.DbMap[utils.DbNameIndex]
	tx := o.Begin()
	if tx.Error != nil {
		return tx.Error
	}
	defer func() {
		if err != nil {
			tx.Rollback()
		} else {
			tx.Commit()
		}
	}()
	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)
	}

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

	glDataList, err := GetShDataByTradeCode(condition, pars)

	addSql := ` INSERT INTO edb_data_sh(edb_info_id,edb_code,data_time,value,create_time,modify_time,status,data_timestamp) values `
	var isAdd bool
	existMap := make(map[string]string)
	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 {
			count, err := GetEdbDataShByCodeAndDate(edbCode, v.DataTime)
			if err != nil && err.Error() != utils.ErrNoRow() {
				return err
			}
			if count <= 0 {
				eDate := item.DataTime
				sValue := itemValue
				if sValue != "" {
					dataTime, err := time.Parse(utils.FormatDate, eDate)
					if err != nil {
						return err
					}
					timestamp := dataTime.UnixNano() / 1e6
					timeStr := fmt.Sprintf("%d", timestamp)
					addSql += GetAddSql(edbInfoIdStr, edbCode, eDate, timeStr, sValue)
					isAdd = true
				}
			} else {
				err = ModifyEdbDataSh(int64(edbInfoId), v.DataTime, value)
				if err != nil {
					return err
				}
			}
		}
		existMap[v.DataTime] = value
	}
	if isAdd {
		addSql = strings.TrimRight(addSql, ",")
		err = tx.Exec(addSql, pars...).Error
		if err != nil {
			return err
		}
	}
	return
}

// GetBaseInfoFromShByIndexCode 获取指标信息
func GetBaseInfoFromShByIndexCode(indexCode, suffix string) (list []*BaseInfoFromSh, err error) {
	o := global.DbMap[utils.DbNameIndex]
	sql := `SELECT * FROM base_from_trade_shanghai_index WHERE %s_code=? `
	sql = fmt.Sprintf(sql, suffix)
	err = o.Raw(sql, indexCode).Find(&list).Error
	return
}

func GetShDataByTradeCode(condition string, pars []interface{}) (item []*BaseFromShDataSimple, err error) {
	sql := ` SELECT * FROM base_from_trade_shanghai_index WHERE 1=1 `
	o := global.DbMap[utils.DbNameIndex]
	if condition != "" {
		sql += condition
	}
	sql += ` ORDER BY data_time DESC `
	err = o.Raw(sql, pars).Find(&item).Error
	return
}

func AddEdbDataShBySql(sqlStr string) (err error) {
	o := global.DbMap[utils.DbNameIndex]
	err = o.Exec(sqlStr).Error
	return
}

func GetBaseFromShDataAllByIndexCode(indexCode, suffix string) (list []*BaseFromTradeShIndex, err error) {
	o := global.DbMap[utils.DbNameIndex]
	sql := `SELECT * FROM base_from_trade_shanghai_index WHERE %s_code=? `
	sql = fmt.Sprintf(sql, suffix)
	err = o.Raw(sql, indexCode).Find(&list).Error
	return
}

func GetEdbDataShByCodeAndDate(edbCode string, startDate string) (count int, err error) {
	o := global.DbMap[utils.DbNameIndex]
	sql := ` SELECT COUNT(1) AS count FROM edb_data_sh WHERE edb_code=? AND data_time=? `
	err = o.Raw(sql, edbCode, startDate).Scan(&count).Error
	return
}

func ModifyEdbDataSh(edbInfoId int64, dataTime, value string) (err error) {
	o := global.DbMap[utils.DbNameIndex]
	sql := ` UPDATE edb_data_sh SET value=?,modify_time=NOW() WHERE edb_info_id=? AND data_time=? `
	err = o.Exec(sql, value, edbInfoId, dataTime).Error
	return
}