package models

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

// BridgeJiaYueIndexDataParams 桥接服务-获取嘉悦指标数据入参
type BridgeJiaYueIndexDataParams struct {
	IndexCode         string `json:"index_code" form:"index_code" description:"指标编码"`
	SourceExtend      string `json:"source_extend" form:"source_extend" description:"来源"`
	StartDate         string `json:"start_date" form:"start_date" description:"开始日期"`
	EndDate           string `json:"end_date" form:"end_date" description:"结束日期"`
	IndexCodeRequired int    `json:"index_code_required" form:"index_code_required" description:"指标编码是否必填: 0-否; 1-是"`
}

// BridgeJiaYueResultIndexData 桥接服务-获取嘉悦指标数据响应体
type BridgeJiaYueResultIndexData struct {
	Code int                      `json:"code" description:"状态码"`
	Msg  string                   `json:"msg" description:"提示信息"`
	Data BridgeJiaYueIndexAndData `json:"data" description:"返回数据"`
}

// BridgeJiaYueIndexAndData 桥接服务-嘉悦指标和数据
type BridgeJiaYueIndexAndData struct {
	Id             int                       `description:"指标自增ID" json:"id"`
	IndexCode      string                    `description:"指标编码" json:"index_code"`
	IndexName      string                    `description:"指标名称" json:"index_name"`
	SourceType     string                    `description:"指标来源" json:"source_type"`
	Unit           string                    `description:"单位" json:"unit"`
	Frequency      string                    `description:"频度" json:"frequency"`
	LastDate       time.Time                 `description:"指标最新时间" json:"last_date"`
	LastUpdateTime time.Time                 `description:"最新更新时间" json:"last_update_time"`
	Status         int                       `description:"指标状态" json:"status"`
	IndexData      []BridgeJiaYueIndexData   `description:"指标数据" json:"index_data"`
	MenuData       BridgeJiaYueIndexMenuData `description:"指标目录信息" json:"menu_data"`
}

// BridgeJiaYueIndexData 桥接服务-嘉悦指标数据
type BridgeJiaYueIndexData struct {
	Val        float64   `json:"val"`
	DataTime   time.Time `json:"data_time"`
	UpdateTime time.Time `json:"update_time"`
}

// BridgeJiaYueIndexMenuData 桥接服务-嘉悦指标目录信息
type BridgeJiaYueIndexMenuData struct {
	Id         int    `description:"目录ID" json:"id"`
	Type       string `description:"目录类型" json:"type"`
	Code       string `description:"目录编码" json:"code"`
	Name       string `description:"目录名称" json:"name"`
	Icon       string `description:"目录图标" json:"icon"`
	Sort       int    `description:"排序" json:"sort"`
	ParentId   int    `description:"父级目录ID" json:"parent_id"`
	ParentName string `description:"父级目录名称" json:"parent_name"`
	Path       string `description:"目录全路径" json:"path"`
}

// BridgeJiaYueIndexMenuWithLevel 桥接服务-嘉悦指标目录带层级
type BridgeJiaYueIndexMenuWithLevel struct {
	Level int `description:"层级"`
	Menu  BridgeJiaYueIndexMenuData
}

// BridgeJiaYueResultNewIndexData 桥接服务-获取嘉悦增量指标数据响应体
type BridgeJiaYueResultNewIndexData struct {
	Code int                        `json:"code" description:"状态码"`
	Msg  string                     `json:"msg" description:"提示信息"`
	Data []BridgeJiaYueIndexAndData `json:"data" description:"返回数据"`
}

// BridgeJiaYueResultMenuListData 桥接服务-获取嘉悦指标目录数据响应体
type BridgeJiaYueResultMenuListData struct {
	Code int                         `json:"code" description:"状态码"`
	Msg  string                      `json:"msg" description:"提示信息"`
	Data []BridgeJiaYueIndexMenuData `json:"data" description:"返回数据"`
}

// AddEdbDataFromJiaYue 新增嘉悦指标数据
func AddEdbDataFromJiaYue(tableName, edbCode string, dataList []BridgeJiaYueIndexData) (err error) {
	if tableName == "" {
		err = fmt.Errorf("数据表名为空")
		return
	}
	if edbCode == "" {
		err = fmt.Errorf("指标编码为空")
		return
	}
	if len(dataList) == 0 {
		return
	}

	sql := fmt.Sprintf(`INSERT INTO %s(edb_info_id, edb_code, data_time, value, create_time, modify_time, data_timestamp) VALUES `, tableName)
	for _, v := range dataList {
		val := utils.SubFloatToString(v.Val, 20)
		stamp := fmt.Sprint(v.DataTime.UnixMilli())
		sql += GetAddSql("0", edbCode, v.DataTime.Format(utils.FormatDate), stamp, val)
	}
	sql = strings.TrimRight(sql, ",")

	// 新增入库
	o := orm.NewOrm()
	_, e := o.Raw(sql).Exec()
	if e != nil {
		err = fmt.Errorf("insert data err: %s", e.Error())
	}
	return
}

// RefreshEdbDataFromJiaYue 刷新嘉悦指标数据
func RefreshEdbDataFromJiaYue(source, subSource, edbInfoId int, tableName, edbCode, startDate string, dataList []BridgeJiaYueIndexData) (err error) {
	if source <= 0 {
		err = fmt.Errorf("指标来源有误")
		return
	}
	if edbInfoId <= 0 {
		err = fmt.Errorf("指标ID有误")
		return
	}
	if tableName == "" {
		err = fmt.Errorf("数据表名为空")
		return
	}

	// 真实数据的最大日期, 插入规则配置的日期
	var realDataMaxDate, edbDataInsertConfigDate time.Time
	var edbDataInsertConfig *EdbDataInsertConfig
	var isFindConfigDateRealData bool //是否找到配置日期的实际数据的值
	{
		conf, e := GetEdbDataInsertConfigByEdbId(edbInfoId)
		if e != nil && e.Error() != utils.ErrNoRow() {
			return
		}
		edbDataInsertConfig = conf
		if edbDataInsertConfig != nil {
			edbDataInsertConfigDate = edbDataInsertConfig.Date
		}
	}

	// 获取已有数据
	cond := ` AND edb_info_id = ?`
	pars := make([]interface{}, 0)
	pars = append(pars, edbInfoId)
	var startDateTime time.Time
	if startDate != "" {
		cond += ` AND data_time >= ?`
		pars = append(pars, startDate)
		startDateTime, _ = time.ParseInLocation(utils.FormatDate, startDate, time.Local)
	}
	existList, e := GetEdbDataByCondition(source, subSource, cond, pars)
	if e != nil {
		err = fmt.Errorf("获取指标已有数据失败, Err: %s", e.Error())
		return
	}
	existMap := make(map[string]*EdbInfoSearchData)
	for _, v := range existList {
		existMap[v.DataTime] = v
	}

	// 比对数据
	hasNew := false
	strEdbInfoId := strconv.Itoa(edbInfoId)
	addExists := make(map[string]bool)
	sqlInsert := fmt.Sprintf(`INSERT INTO %s(edb_info_id, edb_code, data_time, value, create_time, modify_time, data_timestamp) VALUES `, tableName)
	for _, v := range dataList {
		val := utils.SubFloatToString(v.Val, 30)
		stamp := fmt.Sprint(v.DataTime.UnixMilli())
		dataTime := v.DataTime.Format(utils.FormatDate)

		// 如果传入的开始时间是空的, 且当前数据日期早于传入的开始日期, 那么需要判断下当前日期的数据是否存在
		if !startDateTime.IsZero() && v.DataTime.Before(startDateTime) {
			t, e := GetEdbDataByDate(source, subSource, edbCode, dataTime)
			if e == nil && t != nil {
				existMap[t.DataTime] = t
			}
		}

		// 下面代码主要目的是处理掉手动插入的数据判断
		{
			if realDataMaxDate.IsZero() || v.DataTime.After(realDataMaxDate) {
				realDataMaxDate = v.DataTime
			}
			if edbDataInsertConfigDate.IsZero() || v.DataTime.Equal(edbDataInsertConfigDate) {
				isFindConfigDateRealData = true
			}
		}

		// 新增数据
		exist, ok := existMap[dataTime]
		if !ok {
			// 不在历史数据中且与新增中的数据不重复
			if _, o := addExists[dataTime]; !o {
				hasNew = true
				sqlInsert += GetAddSql(strEdbInfoId, edbCode, dataTime, stamp, val)
				addExists[dataTime] = true
			}
			continue
		}

		// 更新数据
		if exist != nil && utils.SubFloatToString(exist.Value, 30) != val {
			if e = ModifyEdbDataById(source, subSource, exist.EdbDataId, val); e != nil {
				err = fmt.Errorf("modify edb data err: %s", e.Error())
				return
			}
		}
	}

	// 处理手工数据补充的配置
	HandleConfigInsertEdbData(realDataMaxDate, edbDataInsertConfig, edbInfoId, source, subSource, existMap, isFindConfigDateRealData)

	// 执行新增
	if !hasNew {
		return
	}
	o := orm.NewOrm()
	sqlInsert = strings.TrimRight(sqlInsert, ",")
	_, e = o.Raw(sqlInsert).Exec()
	if e != nil {
		err = fmt.Errorf("insert edb data err: %s", e.Error())
		return
	}
	return
}
