package data_manage

import (
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"strings"
	"time"
)

// ChartInfoCorrelation 相关性图表-扩展信息
type ChartInfoCorrelation struct {
	CorrelationChartInfoId int       `orm:"column(correlation_chart_info_id);pk" description:"相关性图表ID(chart_info表source=3的)"`
	LeadValue              int       `description:"领先值"`
	LeadUnit               string    `description:"领先单位"`
	CalculateValue         int       `description:"计算窗口"`
	CalculateUnit          string    `description:"计算频度"`
	BaseCalculateValue     int       `description:"基础计算窗口（滚动相关性的时候用到）"`
	BaseCalculateUnit      string    `description:"基础计算频度（滚动相关性的时候用到）"`
	DateType               int       `description:"日期类型:1:00年至今,2:10年至今,3:15年至今，4：年初至今，5:自定义时间,6:起始日期至今"`
	StartDate              time.Time `description:"开始日期"`
	EndDate                time.Time `description:"结束日期"`
	EdbInfoIdFirst         int       `description:"A指标ID"`
	EdbInfoIdSecond        int       `description:"B指标ID"`
	PeriodData             string    `description:"X轴-期数数据"`
	CorrelationData        string    `description:"Y轴-相关性系数"`
	CreateTime             time.Time `description:"创建时间"`
	ModifyTime             time.Time `description:"更新时间"`
	AnalysisMode           int       `description:"分析模式: 0-单因子; 1-多因子"`
}

type CorrelationInfo struct {
	LeadValue       int    `description:"领先值"`
	LeadUnit        string `description:"领先单位"`
	CalculateValue  int    `description:"计算窗口"`
	CalculateUnit   string `description:"计算频度"`
	StartDate       string `description:"开始日期"`
	EndDate         string `description:"结束日期"`
	EdbInfoIdFirst  int    `description:"A指标ID"`
	EdbInfoIdSecond int    `description:"B指标ID"`
	PeriodData      string `description:"X轴-期数数据"`
	CorrelationData string `description:"Y轴-相关性系数"`
	AnalysisMode    int    `description:"分析模式: 0-单因子; 1-多因子"`
}

func (m *ChartInfoCorrelation) TableName() string {
	return "chart_info_correlation"
}

func (m *ChartInfoCorrelation) Create() (err error) {
	o := orm.NewOrmUsingDB("data")
	_, err = o.Insert(m)
	if err != nil {
		return
	}
	//m.CorrelationChartInfoId = int(id)
	return
}

func (m *ChartInfoCorrelation) Update(cols []string) (err error) {
	o := orm.NewOrmUsingDB("data")
	_, err = o.Update(m, cols...)
	return
}

func (m *ChartInfoCorrelation) Delete() (err error) {
	o := orm.NewOrmUsingDB("data")
	sql := fmt.Sprintf(`DELETE FROM %s WHERE correlation_chart_info_id = ? LIMIT 1`, m.TableName())
	_, err = o.Raw(sql, m.CorrelationChartInfoId).Exec()
	return
}

func (m *ChartInfoCorrelation) GetItemById(id int) (err error) {
	o := orm.NewOrmUsingDB("data")
	sql := fmt.Sprintf(`SELECT * FROM %s WHERE correlation_chart_info_id = ? LIMIT 1`, m.TableName())
	err = o.Raw(sql, id).QueryRow(&m)
	return
}

func (m *ChartInfoCorrelation) GetItemByCondition(condition string, pars []interface{}) (err error) {
	o := orm.NewOrmUsingDB("data")
	sql := fmt.Sprintf(`SELECT * FROM %s WHERE 1=1 %s LIMIT 1`, m.TableName(), condition)
	err = o.Raw(sql, pars).QueryRow(&m)
	return
}

func (m *ChartInfoCorrelation) GetItemsByCondition(condition string, pars []interface{}, fieldArr []string, orderRule string) (items []*ChartInfoCorrelation, err error) {
	o := orm.NewOrmUsingDB("data")
	fields := strings.Join(fieldArr, ",")
	if len(fieldArr) == 0 {
		fields = `*`
	}
	order := ``
	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
}

// CreateCorrelationChartAndEdb 新增相关性图表
func CreateCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation) (chartInfoId int, err error) {
	o := orm.NewOrmUsingDB("data")
	tx, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = tx.Rollback()
		} else {
			_ = tx.Commit()
		}
	}()

	// 新增图表信息
	newId, err := tx.Insert(chartInfo)
	if err != nil {
		return
	}
	// 指标mapping
	chartInfoId = int(newId)
	if len(edbMappingList) > 0 {
		for i := range edbMappingList {
			edbMappingList[i].ChartInfoId = chartInfoId
		}
		_, err = tx.InsertMulti(len(edbMappingList), edbMappingList)
		if err != nil {
			return
		}
	}
	// 相关性信息
	correlationInfo.CorrelationChartInfoId = chartInfoId
	if _, err = tx.Insert(correlationInfo); err != nil {
		return
	}
	return
}

// FactorCorrelationConfig 因子指标系列-相关性配置
type FactorCorrelationConfig struct {
	LeadValue      int                       `description:"领先期数"`
	LeadUnit       string                    `description:"频度"`
	CalculateValue int                       `description:"计算窗口"`
	CalculateUnit  string                    `description:"计算频度"`
	SeriesEdb      []CorrelationSeriesEdbReq `description:"关联系列指标"`
}

// CorrelationChartLegend 相关性图表图例
type CorrelationChartLegend struct {
	LegendName string `description:"图例名称"`
	Color      string `description:"图例颜色"`
	EdbInfoId  int    `description:"指标ID"`
	SeriesId   int    `description:"因子指标系列ID"`
}

// CorrelationSeriesEdbReq 指标系列
type CorrelationSeriesEdbReq struct {
	EdbInfoId int `description:"指标ID"`
	SeriesId  int `description:"因子指标系列ID"`
}

// CorrelationChartInfoExtraConfig 相关性图表额外设置
type CorrelationChartInfoExtraConfig struct {
	LegendConfig []*CorrelationChartLegend `description:"图例设置"`
}

// CreateMultiFactorCorrelationChartAndEdb 新增多因子相关性图表
func CreateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, seriesMappings []*FactorEdbSeriesChartMapping) (chartInfoId int, err error) {
	o := orm.NewOrmUsingDB("data")
	tx, e := o.Begin()
	if e != nil {
		err = fmt.Errorf("orm begin err: %v", e)
		return
	}
	defer func() {
		if err != nil {
			_ = tx.Rollback()
			return
		}
		_ = tx.Commit()
	}()

	// 新增图表信息
	chartId, e := tx.Insert(chartInfo)
	if e != nil {
		err = fmt.Errorf("chart insert err: %v", e)
		return
	}
	chartInfo.ChartInfoId = int(chartId)
	chartInfoId = chartInfo.ChartInfoId

	// 指标mapping
	if len(edbMappingList) > 0 {
		for i := range edbMappingList {
			edbMappingList[i].ChartInfoId = chartInfoId
		}
		_, e = tx.InsertMulti(200, edbMappingList)
		if e != nil {
			err = fmt.Errorf("edb mappings insert err: %v", e)
			return
		}
	}

	// 相关性信息
	correlationInfo.CorrelationChartInfoId = chartInfoId
	if _, e = tx.Insert(correlationInfo); e != nil {
		err = fmt.Errorf("correlate chart insert err: %v", e)
		return
	}

	// 指标系列-图表关联
	if len(seriesMappings) > 0 {
		for _, v := range seriesMappings {
			v.ChartInfoId = chartInfoId
		}
		if _, e = tx.InsertMulti(200, seriesMappings); e != nil {
			err = fmt.Errorf("series chart mappings insert err: %v", e)
			return
		}
	}
	return
}

// UpdateMultiFactorCorrelationChartAndEdb 编辑多因子相关性图表
func UpdateMultiFactorCorrelationChartAndEdb(chartInfo *ChartInfo, edbMappingList []*ChartEdbMapping, correlationInfo *ChartInfoCorrelation, seriesMappings []*FactorEdbSeriesChartMapping, chartUpdateCols, correlateUpdateCols []string) (err error) {
	o := orm.NewOrmUsingDB("data")
	tx, e := o.Begin()
	if e != nil {
		err = fmt.Errorf("orm begin err: %v", e)
		return
	}
	defer func() {
		if err != nil {
			_ = tx.Rollback()
			return
		}
		_ = tx.Commit()
	}()

	// 更新图表信息
	_, e = tx.Update(chartInfo, chartUpdateCols...)
	if e != nil {
		err = fmt.Errorf("chart update err: %v", e)
		return
	}

	// 指标mapping
	sql := `DELETE FROM chart_edb_mapping WHERE chart_info_id = ?`
	_, e = tx.Raw(sql, chartInfo.ChartInfoId).Exec()
	if e != nil {
		err = fmt.Errorf("clear chart edb mapping err: %v", e)
		return
	}
	if len(edbMappingList) > 0 {
		for i := range edbMappingList {
			edbMappingList[i].ChartInfoId = chartInfo.ChartInfoId
		}
		_, e = tx.InsertMulti(200, edbMappingList)
		if e != nil {
			err = fmt.Errorf("edb mappings insert err: %v", e)
			return
		}
	}

	// 相关性信息
	_, e = tx.Update(correlationInfo, correlateUpdateCols...)
	if e != nil {
		err = fmt.Errorf("correlate chart update err: %v", e)
		return
	}

	// 指标系列-图表关联
	sql = `DELETE FROM factor_edb_series_chart_mapping WHERE chart_info_id = ?`
	_, e = tx.Raw(sql, chartInfo.ChartInfoId).Exec()
	if e != nil {
		err = fmt.Errorf("clear chart series mapping err: %v", e)
		return
	}
	if len(seriesMappings) > 0 {
		for _, v := range seriesMappings {
			v.ChartInfoId = chartInfo.ChartInfoId
		}
		if _, e = tx.InsertMulti(200, seriesMappings); e != nil {
			err = fmt.Errorf("series chart mappings insert err: %v", e)
			return
		}
	}
	return
}

// FactorCorrelationEditDetail 编辑页详情
type FactorCorrelationEditDetail struct {
	ChartInfoId       int                                    `description:"图表ID"`
	UniqueCode        string                                 `description:"图表唯一编码"`
	BaseEdbInfo       *ChartEdbInfoMapping                   `description:"标的指标信息"`
	EdbSeries         []*FactorEdbSeriesDetail               `description:"指标系列"`
	CorrelationConfig CorrelationConfig                      `description:"相关性基础配置"`
	CorrelationMatrix []FactorEdbSeriesCorrelationMatrixItem `description:"相关性矩阵"`
}
