package models

import (
	"eta/eta_index_lib/models/mgo"
	"eta/eta_index_lib/utils"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"go.mongodb.org/mongo-driver/bson"
	"strings"
	"time"
)

var (
	ThsHfPeriodArr = []int{1, 3, 5, 10, 15, 30, 60}                                                                                     // 时间周期
	ThsHfCPSArr    = []string{"no", "forward1", "forward2", "forward3", "forward4", "backward1", "backward2", "backward3", "backward4"} // 复权方式
	ThsHfFillArr   = []string{"Original", "Previous", "Blank"}                                                                          // 非交易间隔处理
)

// BaseFromThsHfIndex 同花顺高频数据
type BaseFromThsHfIndex struct {
	BaseFromThsHfIndexId    int       `orm:"column(base_from_ths_hf_index_id);pk"`
	BaseFromThsHfClassifyId int       `description:"分类ID"`
	IndexCode               string    `description:"指标编码"`
	IndexName               string    `description:"指标名称"`
	Unit                    string    `description:"单位"`
	Source                  string    `description:"数据来源"`
	Frequency               string    `description:"频度"`
	StartDate               time.Time `description:"开始日期(至时分秒)"`
	EndDate                 time.Time `description:"结束日期(至时分秒)"`
	Describe                string    `description:"指标描述"`
	Sort                    int       `description:"排序"`
	IsStop                  int       `description:"是否停更:0-否;1-停更"`
	TerminalCode            string    `description:"所属终端编码"`
	StockCode               string    `description:"证券代码"`
	Indicator               string    `description:"同花顺指标代码"`
	ApiPars                 string    `description:"API请求参数"`
	LatestValue             float64   `description:"最新值"`
	SysUserId               int       `description:"创建人ID"`
	SysUserRealName         string    `description:"创建人姓名"`
	CreateTime              time.Time `description:"创建时间"`
	ModifyTime              time.Time `description:"修改时间"`
}

func (m *BaseFromThsHfIndex) TableName() string {
	return "base_from_ths_hf_index"
}

type BaseFromThsHfIndexCols struct {
	PrimaryId               string
	BaseFromThsHfClassifyId string
	IndexCode               string
	IndexName               string
	Unit                    string
	Source                  string
	Frequency               string
	StartDate               string
	EndDate                 string
	Describe                string
	Sort                    string
	IsStop                  string
	TerminalCode            string
	StockCode               string
	Indicator               string
	ApiPars                 string
	LatestValue             string
	SysUserId               string
	SysUserRealName         string
	CreateTime              string
	ModifyTime              string
}

func (m *BaseFromThsHfIndex) Cols() BaseFromThsHfIndexCols {
	return BaseFromThsHfIndexCols{
		PrimaryId:               "base_from_ths_hf_index_id",
		BaseFromThsHfClassifyId: "base_from_ths_hf_classify_id",
		IndexCode:               "index_code",
		IndexName:               "index_name",
		Unit:                    "unit",
		Source:                  "source",
		Frequency:               "frequency",
		StartDate:               "start_date",
		EndDate:                 "end_date",
		Describe:                "describe",
		Sort:                    "sort",
		IsStop:                  "is_stop",
		TerminalCode:            "terminal_code",
		StockCode:               "stock_code",
		Indicator:               "indicator",
		ApiPars:                 "api_pars",
		LatestValue:             "latest_value",
		SysUserId:               "sys_user_id",
		SysUserRealName:         "sys_user_real_name",
		CreateTime:              "create_time",
		ModifyTime:              "modify_time",
	}
}

func (m *BaseFromThsHfIndex) Create() (err error) {
	o := orm.NewOrm()
	id, err := o.Insert(m)
	if err != nil {
		return
	}
	m.BaseFromThsHfIndexId = int(id)
	return
}

func (m *BaseFromThsHfIndex) CreateMulti(items []*BaseFromThsHfIndex) (err error) {
	if len(items) == 0 {
		return
	}
	o := orm.NewOrm()
	_, err = o.InsertMulti(len(items), items)
	return
}

func (m *BaseFromThsHfIndex) Update(cols []string) (err error) {
	o := orm.NewOrm()
	_, err = o.Update(m, cols...)
	return
}

func (m *BaseFromThsHfIndex) Remove() (err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
	_, err = o.Raw(sql, m.BaseFromThsHfIndexId).Exec()
	return
}

func (m *BaseFromThsHfIndex) MultiRemove(ids []int) (err error) {
	if len(ids) == 0 {
		return
	}
	o := orm.NewOrm()
	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s IN (%s)`, m.TableName(), m.Cols().PrimaryId, utils.GetOrmInReplace(len(ids)))
	_, err = o.Raw(sql, ids).Exec()
	return
}

func (m *BaseFromThsHfIndex) RemoveByCondition(condition string, pars []interface{}) (err error) {
	if condition == "" {
		return
	}
	o := orm.NewOrm()
	sql := fmt.Sprintf(`DELETE FROM %s WHERE %s`, m.TableName(), condition)
	_, err = o.Raw(sql, pars).Exec()
	return
}

func (m *BaseFromThsHfIndex) GetItemById(id int) (item *BaseFromThsHfIndex, err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`SELECT * FROM %s WHERE %s = ? LIMIT 1`, m.TableName(), m.Cols().PrimaryId)
	err = o.Raw(sql, id).QueryRow(&item)
	return
}

func (m *BaseFromThsHfIndex) GetItemByCondition(condition string, pars []interface{}, orderRule string) (item *BaseFromThsHfIndex, err error) {
	o := orm.NewOrm()
	order := ``
	if orderRule != "" {
		order = ` ORDER BY ` + orderRule
	}
	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s %s LIMIT 1`, m.TableName(), condition, order)
	err = o.Raw(sql, pars).QueryRow(&item)
	return
}

func (m *BaseFromThsHfIndex) GetCountByCondition(condition string, pars []interface{}) (count int, err error) {
	o := orm.NewOrm()
	sql := fmt.Sprintf(`SELECT COUNT(1) FROM %s WHERE 1=1 %s`, m.TableName(), condition)
	err = o.Raw(sql, pars).QueryRow(&count)
	return
}

func (m *BaseFromThsHfIndex) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*BaseFromThsHfIndex, err error) {
	o := orm.NewOrm()
	fields := strings.Join(fieldArr, ",")
	if len(fieldArr) == 0 {
		fields = `*`
	}
	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
	if orderRule != "" {
		order = ` ORDER BY ` + orderRule
	}
	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s`, fields, m.TableName(), condition, order)
	_, err = o.Raw(sql, pars).QueryRows(&items)
	return
}

func (m *BaseFromThsHfIndex) GetPageItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string, startSize, pageSize int) (items []*BaseFromThsHfIndex, err error) {
	o := orm.NewOrm()
	fields := strings.Join(fieldArr, ",")
	if len(fieldArr) == 0 {
		fields = `*`
	}
	order := fmt.Sprintf(`ORDER BY %s DESC`, m.Cols().CreateTime)
	if orderRule != "" {
		order = ` ORDER BY ` + orderRule
	}
	sql := fmt.Sprintf(`SELECT %s FROM %s WHERE 1=1 %s %s LIMIT ?,?`, fields, m.TableName(), condition, order)
	_, err = o.Raw(sql, pars, startSize, pageSize).QueryRows(&items)
	return
}

// BaseFromThsHfIndexItem 同花顺高频数据信息
type BaseFromThsHfIndexItem struct {
	IndexId    int    `description:"同花顺高频数据ID"`
	IndexCode  string `description:"指标编码"`
	IndexName  string `description:"指标名称"`
	Unit       string `description:"单位"`
	Source     string `description:"数据来源"`
	Frequency  string `description:"频度"`
	StartDate  string `description:"开始日期(至时分秒)"`
	EndDate    string `description:"结束日期(至时分秒)"`
	Describe   string `description:"指标描述"`
	Sort       int    `description:"排序"`
	CreateTime string `description:"创建时间"`
	ModifyTime string `description:"修改时间"`
}

func (m *BaseFromThsHfIndex) Format2Item() (item *BaseFromThsHfIndexItem) {
	item = new(BaseFromThsHfIndexItem)
	item.IndexId = m.BaseFromThsHfIndexId
	item.IndexCode = m.IndexCode
	item.IndexName = m.IndexName
	item.Unit = m.Unit
	item.Source = m.Source
	item.Frequency = m.Frequency
	item.StartDate = utils.TimeTransferString(utils.FormatDateTime, m.StartDate)
	item.EndDate = utils.TimeTransferString(utils.FormatDateTime, m.EndDate)
	item.Describe = m.Describe
	item.Sort = m.Sort
	item.CreateTime = utils.TimeTransferString(utils.FormatDateTime, m.CreateTime)
	item.ModifyTime = utils.TimeTransferString(utils.FormatDateTime, m.ModifyTime)
	return
}

// ThsHfSearchEdbReq 搜索指标请求体
type ThsHfSearchEdbReq struct {
	StockCode string `form:"StockCode" description:"证券代码" `
	EdbCode   string `form:"EdbCode" description:"指标代码"`
	StartTime string `form:"StartTime" description:"每日数据开始时间"`
	EndTime   string `form:"EndTime" description:"每日数据结束时间"`
	Interval  int    `form:"Interval" description:"时间周期"`
	Fill      string `form:"Fill" description:"非交易间隔处理"`
	CPS       string `form:"CPS" description:"复权方式"`
	BaseDate  string `form:"BaseDate" description:"复权基点"`
}

// ThsHfApiResp 同花顺接口响应
type ThsHfApiResp struct {
	ErrorCode int    `json:"errorcode"`
	ErrMsg    string `json:"errmsg"`
	Tables    []struct {
		ThsCode string               `json:"thscode"`
		Time    []string             `json:"time"`
		Table   map[string][]float64 `json:"table"`
	} `json:"tables"`
}

// ThsHfAppResp 同花顺公用机响应
type ThsHfAppResp struct {
	ErrorCode int    `json:"errorcode"`
	ErrMsg    string `json:"errmsg"`
	//Data      []interface{} `json:"data"`
	Data []struct {
		Time    string  `json:"time"`
		ThsCode string  `json:"thscode"`
		Open    float64 `json:"open"`
		Close   float64 `json:"close"`
	} `json:"data"`
}

// ThsHfIndexWithData 同花顺高频指标
type ThsHfIndexWithData struct {
	StockCode string            `description:"证券代码"`
	EdbCode   string            `description:"指标代码"`
	IndexData []*ThsHfIndexData `description:"指标数据"`
}

// ThsHfIndexData 同花顺高频指标数据
type ThsHfIndexData struct {
	DataTime time.Time `description:"数据时间(2006-01-02 15:04)"`
	Value    float64   `description:"数据值"`
}

type ThsHfBaseAddIndexItem struct {
	ClassifyId int    `description:"分类ID"`
	Unit       string `description:"单位"`
	IndexName  string `description:"指标名称"`
	Frequency  string `description:"频度"`
	StockCode  string `description:"证券代码"`
	EdbCode    string `description:"指标代码"`
}

// ThsHfBaseAddReq 新增至数据源请求
type ThsHfBaseAddReq struct {
	StartTime             string `description:"每日数据开始时间"`
	EndTime               string `description:"每日数据结束时间"`
	Interval              int    `description:"时间周期"`
	Fill                  string `description:"非交易间隔处理"`
	CPS                   string `description:"复权方式"`
	BaseDate              string `description:"复权基点"`
	SysAdminId            int    `description:"创建人ID"`
	SysAdminName          string `description:"创建人姓名"`
	ThsHfBaseAddIndexItem `description:"指标信息"`
}

// CreateIndexAndData 新增指标和数据
//func (m *BaseFromThsHfIndex) CreateIndexAndData(indexItem *BaseFromThsHfIndex, indexData []*BaseFromThsHfData) (err error) {
//	o := orm.NewOrm()
//	tx, e := o.Begin()
//	if e != nil {
//		err = fmt.Errorf("tx begin err: %v", e)
//		return
//	}
//	defer func() {
//		if err != nil {
//			_ = tx.Rollback()
//			return
//		}
//		_ = tx.Commit()
//	}()
//
//	lastId, e := tx.Insert(indexItem)
//	if e != nil {
//		err = fmt.Errorf("insert index err: %v", e)
//		return
//	}
//	indexId := int(lastId)
//	indexItem.BaseFromThsHfIndexId = indexId
//
//	if len(indexData) == 0 {
//		return
//	}
//	for _, v := range indexData {
//		v.BaseFromThsHfIndexId = indexId
//	}
//	if _, e = tx.InsertMulti(200, indexData); e != nil {
//		err = fmt.Errorf("insert index data err: %v", e)
//		return
//	}
//	return
//}

// ThsHfBaseRefreshReq 数据源刷新请求
type ThsHfBaseRefreshReq struct {
	BaseIndexCode string `description:"源指标编码"`
	RefreshType   int    `description:"刷新类型: 1-最近6小时; 2-全部刷新"`
}

// ThsHfEdbAddReq 新增至指标库
type ThsHfEdbAddReq struct {
	ConvertRule ThsHfIndexConvert2EdbRule
	NewIndex    *ThsHfIndexMultiSave2EdbPreItem `description:"新增指标"`
}

type ThsHfIndexConvert2EdbRule struct {
	ConvertType  int `description:"转换类型: 1-指定时间值; 2-区间计算值"`
	ConvertFixed struct {
		FixedDay  int    `description:"指定时间值日期: 1-当日; 2-前一日"`
		FixedTime string `description:"指定时间值时点(HH:mm:ss)"`
	} `description:"指定时间值"`
	ConvertArea struct {
		StartDay      int    `description:"起始时间日期: 1-当日; 2-前一日"`
		StartTime     string `description:"起始时间时点(HH:mm:ss)"`
		EndDay        int    `description:"截止时间日期: 1-当日; 2-前一日"`
		EndTime       string `description:"截止时间时点(HH:mm:ss)"`
		CalculateType int    `description:"计算类型: 1-区间均值; 2-最大值; 3-最小值"`
	} `description:"区间计算值"`
}

// ThsHfIndexMultiSave2EdbPreItem 批量新增指标库信息
type ThsHfIndexMultiSave2EdbPreItem struct {
	IndexId      int    `description:"指标ID"`
	IndexCode    string `description:"指标编码"`
	IndexName    string `description:"原指标名称"`
	NewIndexName string `description:"新指标名称"`
	StockCode    string `description:"证券代码"`
	EdbCode      string `description:"指标代码"`
	Unit         string `description:"单位"`
	Frequency    string `description:"原频度"`
	NewFrequency string `description:"新频度(固定日度)"`
	ClassifyId   int    `description:"指标库分类ID"`
	SysAdminId   int    `description:"创建人ID"`
	SysAdminName string `description:"创建人姓名"`
	Tips         string `description:"提示信息"`
	ErrMsg       string `description:"错误信息"`
}

// GetEdbInfoMaxAndMinInfo
// @Description: 获取指标的最新数据记录信息
// @author: Roc
// @receiver m
// @datetime 2024-07-02 14:50:50
// @param edbCode string
// @return item *EdbInfoMaxAndMinInfo
// @return err error
func (m BaseFromThsHfIndex) GetEdbInfoMaxAndMinInfo(edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
	if utils.UseMongo {
		return m.getEdbInfoMaxAndMinInfoByMongo(edbCode)
	}
	return m.getEdbInfoMaxAndMinInfoByMysql(edbCode)
}

// getEdbInfoMaxAndMinInfoByMongo
// @Description: 获取指标的最新数据记录信息(从mongo中获取)
// @author: Roc
// @receiver m
// @datetime 2024-07-02 14:41:20
// @param edbCode string
// @return item *EdbInfoMaxAndMinInfo
// @return err error
func (m BaseFromThsHfIndex) getEdbInfoMaxAndMinInfoByMongo(edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
	mogDataObj := new(mgo.BaseFromThsHfData)
	pipeline := []bson.M{
		{"$match": bson.M{"index_code": edbCode}},
		{"$group": bson.M{
			"_id":       nil,
			"min_date":  bson.M{"$min": "$data_time"},
			"max_date":  bson.M{"$max": "$data_time"},
			"min_value": bson.M{"$min": "$value"},
			"max_value": bson.M{"$max": "$value"},
		}},
		{"$project": bson.M{"_id": 0}}, // 可选,如果不需要_id字段
	}
	result, err := mogDataObj.GetEdbInfoMaxAndMinInfo(pipeline)
	if err != nil {
		fmt.Println("BaseFromThsHfIndex GetEdbInfoMaxAndMinInfo Err:" + err.Error())
		return
	}

	if !result.MaxDate.IsZero() {
		whereQuery := bson.M{"index_code": edbCode, "data_time": result.MaxDate}
		selectParam := bson.D{{"value", 1}, {"_id", 0}}
		latestValue, tmpErr := mogDataObj.GetLatestValue(whereQuery, selectParam)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		result.LatestValue = latestValue.Value
		result.EndValue = latestValue.Value
	}

	item = &EdbInfoMaxAndMinInfo{
		MinDate:     result.MinDate.Format(utils.FormatDateTime),
		MaxDate:     result.MaxDate.Format(utils.FormatDateTime),
		MinValue:    result.MinValue,
		MaxValue:    result.MaxValue,
		LatestValue: result.LatestValue,
		LatestDate:  result.LatestDate.Format(utils.FormatDateTime),
		EndValue:    result.EndValue,
	}
	return
}

// getEdbInfoMaxAndMinInfoByMysql
// @Description: 获取指标的最新数据记录信息(从mysql中获取)
func (m BaseFromThsHfIndex) getEdbInfoMaxAndMinInfoByMysql(edbCode string) (item *EdbInfoMaxAndMinInfo, err error) {
	dataObj := BaseFromThsHfData{}
	result, err := dataObj.GetIndexMinMax(edbCode)
	if err != nil {
		return
	}

	item = &EdbInfoMaxAndMinInfo{
		MinDate:     result.MinDate,
		MaxDate:     result.MaxDate,
		MinValue:    result.MinValue,
		MaxValue:    result.MaxValue,
		LatestValue: result.LatestValue,
		LatestDate:  result.LatestDate,
		EndValue:    result.EndValue,
	}
	return
}