package data_manage

import (
	"encoding/json"
	"eta/eta_api/utils"
	"fmt"
	"github.com/beego/beego/v2/client/orm"
	"time"
)

type ChartSeries struct {
	ChartSeriesId int       `orm:"column(chart_series_id);pk"`
	SeriesName    string    `description:"系列名称"`
	SeriesNameEn  string    `description:"系列英文名称"`
	ChartInfoId   int       `description:"图表ID"`
	ChartStyle    string    `description:"图表类型"`
	ChartColor    string    `description:"颜色"`
	ChartWidth    int       `description:"线条大小"`
	IsPoint       int       `description:"是否用数据点展示(0 否,1是)"`
	IsNumber      int       `description:"是否用数值展示(0 否,1是)"`
	IsAxis        int       `description:"1:左轴,0:右轴"`
	MaxData       float64   `description:"上限"`
	MinData       float64   `description:"下限"`
	IsOrder       bool      `description:"true:正序,false:逆序"`
	CreateTime    time.Time `description:"创建时间"`
	ModifyTime    time.Time `description:"修改时间"`
	UniqueFlag    string    `description:"唯一标识"`
}

func (c *ChartSeries) TableName() string {
	return "chart_series"
}

func GetChartSeriesByChartInfoId(chartInfoId int) (items []*ChartSeries, err error) {
	o := orm.NewOrmUsingDB("data")
	sql := "SELECT * FROM chart_series WHERE chart_info_id = ?"
	_, err = o.Raw(sql, chartInfoId).QueryRows(&items)
	return
}

// EditChartSeriesAndEdbMapping
func EditChartSeriesAndEdbMapping(extraConfigStr string, chartInfoId int) (err error) {
	o := orm.NewOrmUsingDB("data")
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()

	// 获取已经存在的系列
	series, err := GetChartSeriesByChartInfoId(chartInfoId)
	if err != nil {
		return
	}
	//整理成系列map
	seriesMap := make(map[int]struct{})
	seriesDeleteMap := make(map[int]struct{})
	for _, v := range series {
		seriesMap[v.ChartSeriesId] = struct{}{}
		seriesDeleteMap[v.ChartSeriesId] = struct{}{}
	}
	var sectionExtraConfig ChartSectionAllExtraConf
	err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
	if err != nil {
		err = fmt.Errorf("截面组合图配置异常")
		return
	}

	// 删除所有的指标映射
	_, err = o.Raw("DELETE FROM chart_series_edb_mapping WHERE chart_info_id = ?", chartInfoId).Exec()
	if err != nil {
		return
	}

	seriesList := sectionExtraConfig.SeriesList
	for _, v := range seriesList {
		seriesId := v.ChartSeriesId
		tmp := &ChartSeries{
			ChartSeriesId: v.ChartSeriesId,
			SeriesName:    v.SeriesName,
			SeriesNameEn:  v.SeriesNameEn,
			ChartInfoId:   chartInfoId,
			ChartStyle:    v.ChartStyle,
			ChartColor:    v.ChartColor,
			ChartWidth:    v.ChartWidth,
			IsPoint:       v.IsPoint,
			IsNumber:      v.IsNumber,
			IsAxis:        v.IsAxis,
			MaxData:       v.MaxData,
			MinData:       v.MinData,
			ModifyTime:    time.Now(),
		}
		if _, ok := seriesMap[v.ChartSeriesId]; !ok {
			if seriesId > 0 {
				err = fmt.Errorf("系列ID错误")
				return
			}
			//新增
			tmp.CreateTime = time.Now()
			seriesIdTmp, e := to.Insert(tmp)
			if e != nil {
				err = fmt.Errorf("AddChartSeries Err:" + e.Error())
				return
			}
			seriesId = int(seriesIdTmp)
		} else {
			//编辑
			delete(seriesDeleteMap, v.ChartSeriesId)
			_, e := to.Update(tmp)
			if e != nil {
				err = fmt.Errorf("UpdateChartSeries Err:" + e.Error())
				return
			}
		}

		addSeriesEdbList := make([]*ChartSeriesEdbMapping, 0)
		for _, edbItem := range v.EdbInfoList {
			dateConfStrByte, e := json.Marshal(edbItem.DateConf)
			if e != nil {
				err = e
				return
			}
			dateConfStr := string(dateConfStrByte)
			edbTmp := &ChartSeriesEdbMapping{
				ChartSeriesId: seriesId,    //todo 系列ID
				ChartInfoId:   chartInfoId, //todo 表图ID
				EdbInfoId:     edbItem.EdbInfoId,
				//EdbAliasName:            "",
				//EdbAliasNameEn:          "",
				DateConfName: edbItem.DateConfName,
				DateConf:     dateConfStr,
				DateConfType: edbItem.DateConfType,
				CreateTime:   time.Now(),
				ModifyTime:   time.Now(),
			}
			addSeriesEdbList = append(addSeriesEdbList, edbTmp)
		}
		if len(addSeriesEdbList) > 0 {
			_, err = to.InsertMulti(len(addSeriesEdbList), addSeriesEdbList)
			if err != nil {
				err = fmt.Errorf("AddChartSeries Err:" + err.Error())
				return
			}
		}
	}
	//删除旧的系列和ID
	seriesIds := make([]int, 0)
	for id, _ := range seriesDeleteMap {
		seriesIds = append(seriesIds, id)
	}
	if len(seriesIds) > 0 {
		sql := `DELETE FROM chart_series WHERE chart_series_id IN (` + utils.GetOrmInReplace(len(seriesIds)) + `) and chart_info_id=?`
		_, err = to.Raw(sql, seriesIds, chartInfoId).Exec()
		if err != nil {
			err = fmt.Errorf("删除系列失败 Err:" + err.Error())
			return
		}
		sql = `DELETE FROM chart_series_edb_mapping WHERE chart_series_id IN (` + utils.GetOrmInReplace(len(seriesIds)) + `) and chart_info_id=?`
		_, err = to.Raw(sql, seriesIds, chartInfoId).Exec()
		if err != nil {
			err = fmt.Errorf("删除系列指标 Err:" + err.Error())
			return
		}
	}

	return
}

func AddChartSeriesAndEdbMapping(extraConfigStr string, chartInfoId int) (err error) {
	o := orm.NewOrmUsingDB("data")
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()

	var sectionExtraConfig ChartSectionAllExtraConf
	err = json.Unmarshal([]byte(extraConfigStr), &sectionExtraConfig)
	if err != nil {
		err = fmt.Errorf("截面组合图配置异常")
		return
	}
	seriesList := sectionExtraConfig.SeriesList
	for _, v := range seriesList {
		tmp := &ChartSeries{
			SeriesName:   v.SeriesName,
			SeriesNameEn: v.SeriesNameEn,
			ChartInfoId:  chartInfoId,
			ChartStyle:   v.ChartStyle,
			ChartColor:   v.ChartColor,
			ChartWidth:   v.ChartWidth,
			IsPoint:      v.IsPoint,
			IsNumber:     v.IsNumber,
			IsAxis:       v.IsAxis,
			MaxData:      v.MaxData,
			MinData:      v.MinData,
			IsOrder:      false, //todo 是否排序
			CreateTime:   time.Now(),
			ModifyTime:   time.Now(),
		}
		seriesIdTmp, e := to.Insert(tmp)
		if e != nil {
			err = fmt.Errorf("AddChartSeries Err:" + e.Error())
			return
		}
		seriesId := int(seriesIdTmp)
		addSeriesEdbList := make([]*ChartSeriesEdbMapping, 0)
		for _, edbItem := range v.EdbInfoList {
			dateConfStrByte, e := json.Marshal(edbItem.DateConf)
			if e != nil {
				err = e
				return
			}
			dateConfStr := string(dateConfStrByte)
			edbTmp := &ChartSeriesEdbMapping{
				ChartSeriesId: seriesId,    //todo 系列ID
				ChartInfoId:   chartInfoId, //todo 表图ID
				EdbInfoId:     edbItem.EdbInfoId,
				//EdbAliasName:            "",
				//EdbAliasNameEn:          "",
				DateConfName: edbItem.DateConfName,
				DateConfType: edbItem.DateConfType,
				DateConf:     dateConfStr,
				CreateTime:   time.Now(),
				ModifyTime:   time.Now(),
			}
			addSeriesEdbList = append(addSeriesEdbList, edbTmp)
		}
		if len(addSeriesEdbList) > 0 {
			_, e = to.InsertMulti(len(addSeriesEdbList), addSeriesEdbList)
			if e != nil {
				err = fmt.Errorf("AddChartSeries Err:" + e.Error())
				return
			}
		}
	}
	return
}

func DeleteChartSeriesAndEdbMapping(chartInfoId int) (err error) {
	o := orm.NewOrmUsingDB("data")
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()

	sql := ` DELETE FROM chart_series WHERE chart_info_id=? `
	_, err = to.Raw(sql, chartInfoId).Exec()
	if err != nil {
		return
	}
	sql = ` DELETE FROM  chart_series_edb_mapping WHERE chart_info_id=? `
	_, err = to.Raw(sql, chartInfoId).Exec()
	return
}

func CopyChartSeriesAndEdbMapping(seriesList []*ChartSeries, seriesEdbInfoList []*ChartSeriesEdbMapping, chartInfoId int) (err error) {
	o := orm.NewOrmUsingDB("data")
	to, err := o.Begin()
	if err != nil {
		return
	}
	defer func() {
		if err != nil {
			_ = to.Rollback()
		} else {
			_ = to.Commit()
		}
	}()
	seriesEdbMap := make(map[int][]*ChartSeriesEdbMapping)
	for _, v := range seriesEdbInfoList {
		seriesEdbMap[v.ChartSeriesId] = append(seriesEdbMap[v.ChartSeriesId], v)
	}
	for _, v := range seriesList {
		tmp := &ChartSeries{
			SeriesName:   v.SeriesName,
			SeriesNameEn: v.SeriesNameEn,
			ChartInfoId:  chartInfoId,
			ChartStyle:   v.ChartStyle,
			ChartColor:   v.ChartColor,
			ChartWidth:   v.ChartWidth,
			IsPoint:      v.IsPoint,
			IsNumber:     v.IsNumber,
			IsAxis:       v.IsAxis,
			MaxData:      v.MaxData,
			MinData:      v.MinData,
			CreateTime:   time.Now(),
			ModifyTime:   time.Now(),
		}
		seriesIdTmp, e := to.Insert(tmp)
		if e != nil {
			err = fmt.Errorf("AddChartSeries Err:" + e.Error())
			return
		}
		seriesId := int(seriesIdTmp)
		addSeriesEdbList := make([]*ChartSeriesEdbMapping, 0)
		mappingList, ok := seriesEdbMap[v.ChartSeriesId]
		if ok {
			for _, edbItem := range mappingList {
				edbTmp := &ChartSeriesEdbMapping{
					ChartSeriesId: seriesId,    //todo 系列ID
					ChartInfoId:   chartInfoId, //todo 表图ID
					EdbInfoId:     edbItem.EdbInfoId,
					//EdbAliasName:            "",
					//EdbAliasNameEn:          "",
					DateConfName: edbItem.DateConfName,
					DateConfType: edbItem.DateConfType,
					DateConf:     edbItem.DateConf,
					CreateTime:   time.Now(),
					ModifyTime:   time.Now(),
				}
				addSeriesEdbList = append(addSeriesEdbList, edbTmp)
			}
			if len(addSeriesEdbList) > 0 {
				_, e = to.InsertMulti(len(addSeriesEdbList), addSeriesEdbList)
				if e != nil {
					err = fmt.Errorf("AddChartSeries Err:" + e.Error())
					return
				}
			}
		}
	}
	return
}

type ChartSectionSeriesValSortAsc []ChartSectionSeriesValSort
type ChartSectionSeriesValSortDesc []ChartSectionSeriesValSort

type ChartSectionSeriesValSort struct {
	Index int
	Value float64
}

func (s ChartSectionSeriesValSortAsc) Len() int {
	return len(s)
}

func (s ChartSectionSeriesValSortAsc) Less(i, j int) bool {
	return s[i].Value < s[j].Value // 升序排序,如果想要降序则改为 s[i].Value > s[j].Value
}

func (s ChartSectionSeriesValSortAsc) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (s ChartSectionSeriesValSortDesc) Len() int {
	return len(s)
}

func (s ChartSectionSeriesValSortDesc) Less(i, j int) bool {
	return s[i].Value > s[j].Value // 升序排序,如果想要降序则改为 s[i].Value > s[j].Value
}

func (s ChartSectionSeriesValSortDesc) Swap(i, j int) {
	s[i], s[j] = s[j], s[i]
}

func (c *ChartSeries) CreateMulti(items []*ChartSeries) (err error) {
	if len(items) == 0 {
		return
	}
	o := orm.NewOrmUsingDB("data")
	_, err = o.InsertMulti(utils.MultiAddNum, items)
	return
}

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