package data_manage

import (
	"encoding/json"
	"eta/eta_mobile/controllers"
	"eta/eta_mobile/models"
	"eta/eta_mobile/models/data_manage"
	"eta/eta_mobile/models/data_manage/request"
	"eta/eta_mobile/models/data_manage/response"
	"eta/eta_mobile/services/data"
	"eta/eta_mobile/services/data/data_manage_permission"
	"eta/eta_mobile/services/elastic"
	"eta/eta_mobile/utils"
	"fmt"
	"github.com/rdlucklib/rdluck_tools/paging"
	"github.com/shopspring/decimal"
	"sort"
	"strconv"
	"strings"
	"time"
)

// PredictEdbInfoController 预测指标
type PredictEdbInfoController struct {
	controllers.BaseAuthController
}

// EdbChartList
// @Title 预测指标列表接口
// @Description 预测指标列表接口
// @Param   PageSize   query   int  true       "每页数据条数"
// @Param   CurrentIndex   query   int  true       "当前页页码，从1开始"
// @Param   ClassifyId   query   int  true       "分类id"
// @Param   AdminId   query   int  false       "创建人id"
// @Param   IsOnlyMe   query   bool  false       "是否只看我的"
// @Success 200 {object} response.PredictEdbInfoListResp
// @router /predict_edb_info/chart/list [get]
func (this *PredictEdbInfoController) EdbChartList() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	classifyId, _ := this.GetInt("ClassifyId")

	pageSize, _ := this.GetInt("PageSize")
	currentIndex, _ := this.GetInt("CurrentIndex")
	adminId, _ := this.GetInt("AdminId")
	isOnlyMe, _ := this.GetBool("IsOnlyMe")

	var total int
	page := paging.GetPaging(currentIndex, pageSize, total)

	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	var condition string
	var pars []interface{}

	// 预测指标
	condition += ` AND edb_info_type = ? `
	pars = append(pars, 1)

	// 筛选分类
	if classifyId > 0 {
		childClassify, e, _ := data.GetChildClassifyByClassifyId(classifyId)
		if e != nil && e.Error() != utils.ErrNoRow() {
			br.Msg = "获取失败"
			br.ErrMsg = "获取分类信息失败, GetEdbClassify,Err:" + e.Error()
			return
		}
		var classifyIds []int
		for _, v := range childClassify {
			classifyIds = append(classifyIds, v.ClassifyId)
		}
		condition += fmt.Sprintf(` AND classify_id IN (%s) `, utils.GetOrmInReplace(len(classifyIds)))
		pars = append(pars, classifyIds)
	}
	if adminId > 0 {
		condition += " AND sys_user_id = ? "
		pars = append(pars, adminId)
	}
	if isOnlyMe {
		condition += " AND sys_user_id = ? "
		pars = append(pars, sysUser.AdminId)
	}

	// 获取当前账号的不可见指标
	obj := data_manage.EdbInfoNoPermissionAdmin{}
	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		br.Msg = "获取失败"
		br.ErrMsg = "获取不可见指标配置数据失败，Err:" + err.Error()
		return
	}
	noPermissionEdbInfoIdList := make([]int, 0)
	for _, v := range confList {
		noPermissionEdbInfoIdList = append(noPermissionEdbInfoIdList, v.EdbInfoId)
	}
	noPermissionEdbInfoIdNum := len(noPermissionEdbInfoIdList)
	if noPermissionEdbInfoIdNum > 0 {
		condition += ` AND edb_info_id not in (` + utils.GetOrmInReplace(noPermissionEdbInfoIdNum) + `) `
		pars = append(pars, noPermissionEdbInfoIdList)
	}
	//获取指标信息
	dataCount, list, err := data_manage.GetEdbInfoFilterList(condition, pars, startSize, pageSize)
	if err != nil && err.Error() != utils.ErrNoRow() {
		br.Success = true
		br.Msg = "获取预测指标列表失败"
		br.ErrMsg = "获取预测指标列表失败,Err:" + err.Error()
		return
	}

	if list == nil || len(list) <= 0 || (err != nil && err.Error() == utils.ErrNoRow()) {
		list = make([]*data_manage.EdbInfoList, 0)
	} else {
		classifyIdList := make([]int, 0)
		for _, v := range list {
			classifyIdList = append(classifyIdList, v.ClassifyId)
		}

		// 指标权限
		{
			// 当前的分类
			classifyMap := make(map[int]*data_manage.EdbClassify)
			classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
			if err != nil {
				if err != nil {
					br.Msg = "获取失败"
					br.ErrMsg = "获取分类列表失败，Err:" + err.Error()
					return
				}
			}

			for _, v := range classifyList {
				classifyMap[v.ClassifyId] = v
			}

			// 获取所有有权限的指标和分类
			permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
			if err != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取所有有权限的指标和分类失败，Err:" + err.Error()
				return
			}

			for _, v := range list {
				if currClassify, ok := classifyMap[v.ClassifyId]; ok {
					v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, currClassify.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
					v.Button = data.GetEdbOpButton(sysUser, v.SysUserId, v.EdbType, v.EdbInfoType, v.HaveOperaAuth)
				}
			}
		}

		page = paging.GetPaging(currentIndex, pageSize, int(dataCount))
	}

	resp := response.PredictEdbInfoListResp{
		Paging: page,
		List:   list,
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// List
// @Title 指标数据列表接口
// @Description 指标数据列表接口
// @Param   PageSize   query   int  true       "每页数据条数"
// @Param   CurrentIndex   query   int  true       "当前页页码，从1开始"
// @Param   EdbInfoId   query   int  true       "指标id"
// @Param   KeyWord   query   string  false       "搜索关键词:指标ID/指标名称"
// @Success 200 {object} data_manage.EdbInfoListResp
// @router /predict_edb_info/list [get]
func (this *PredictEdbInfoController) List() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	edbInfoId, _ := this.GetInt("EdbInfoId")
	keyWord := this.GetString("KeyWord")

	pageSize, _ := this.GetInt("PageSize")
	currentIndex, _ := this.GetInt("CurrentIndex")

	var total int
	page := paging.GetPaging(currentIndex, pageSize, total)

	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	var condition string
	var pars []interface{}

	// 指标类型，0：普通指标，1：预测指标
	condition += " AND edb_info_type=? "
	pars = append(pars, 1)

	if edbInfoId > 0 {
		condition += " AND edb_info_id=? "
		pars = append(pars, edbInfoId)
	}

	if keyWord != "" {
		condition += ` AND  ( edb_code LIKE '%` + keyWord + `%'  OR  edb_name LIKE '%` + keyWord + `%' )`
		//pars = append(pars, keyWord)
		//pars = append(pars, keyWord)
	}

	resp := data_manage.EdbInfoListResp{}
	if condition == "" {
		item := new(data_manage.EdbInfoList)
		resp.Paging = page
		resp.Item = item
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		return
	}
	//获取指标信息
	edbInfoItem, err := data_manage.GetEdbInfoByCondition(condition, pars)
	if err != nil && err.Error() != utils.ErrNoRow() {
		br.Success = true
		br.Msg = "获取指标信息失败"
		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
		return
	}

	if edbInfoItem == nil || (err != nil && err.Error() == utils.ErrNoRow()) {
		item := new(data_manage.EdbInfoList)
		resp.Paging = page
		resp.Item = item
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		return
	}

	//获取英文频度
	edbInfoItem.FrequencyEn = data.GetFrequencyEn(edbInfoItem.Frequency)

	// 未来的指标预测数据
	predictDataList := make([]*data_manage.EdbData, 0)

	var existCondition string
	var existPars []interface{}
	existCondition += " AND edb_info_id=? "
	existPars = append(existPars, edbInfoId)

	//查询出所有的关联指标
	sourceEdbInfoCalculateMappingList, err := data_manage.GetEdbInfoCalculateListByCondition(existCondition, existPars)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取预测指标关联信息失败，Err:" + err.Error()
		return
	}
	if len(sourceEdbInfoCalculateMappingList) <= 0 {
		br.Msg = "获取失败"
		br.ErrMsg = "查找预测指标关联信息失败"
		return
	}

	//获取指标数据（实际已生成）
	{
		dataCount, dataList, err := data.GetPageData(edbInfoItem.EdbInfoId, edbInfoItem.Source, edbInfoItem.SubSource, edbInfoItem.LatestDate, startSize, pageSize)
		if err != nil && err.Error() != utils.ErrNoRow() {
			br.Msg = "获取指标信息失败"
			br.ErrMsg = "获取指标数据总数失败,Err:" + err.Error()
			return
		}
		page = paging.GetPaging(currentIndex, pageSize, dataCount)
		edbInfoItem.DataList = dataList
	}

	// 第一页才需要 获取预测指标未来的数据
	if currentIndex == 1 {
		predictDataList, err = data_manage.GetAllEdbDataListData(edbInfoItem.EdbInfoId, edbInfoItem.Source, edbInfoItem.SubSource, edbInfoItem.LatestDate)
		if err != nil {
			br.Msg = "获取指标信息失败"
			br.ErrMsg = "获取指标数据失败,Err:" + err.Error()
			return
		}
		if err != nil {
			br.Msg = "获取预测指标数据失败"
			br.ErrMsg = "获取预测指标数据失败" + err.Error()
			return
		}
	}

	// 如果预测数据没有，那么返回空数组
	if predictDataList == nil {
		predictDataList = make([]*data_manage.EdbData, 0)
	}
	edbInfoItem.PredictDataList = predictDataList

	// 如果实际数据没有，那么返回空数组
	if edbInfoItem.DataList == nil {
		edbInfoItem.DataList = make([]*data_manage.EdbData, 0)
	}
	//查询目录
	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfoItem.ClassifyId)
	if err != nil {
		br.Msg = err.Error()
		br.ErrMsg = errMsg
		return
	}

	// 权限校验
	{
		classifyMap := make(map[int]*data_manage.EdbClassifyIdItems)
		for _, v := range classifyList {
			classifyMap[v.ClassifyId] = v
		}
		if currClassify, ok := classifyMap[edbInfoItem.ClassifyId]; ok {
			haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfoItem.IsJoinPermission, currClassify.IsJoinPermission, this.SysUser.AdminId, edbInfoItem.EdbInfoId, edbInfoItem.ClassifyId)
			if err != nil {
				br.Msg = err.Error()
				br.ErrMsg = "校验指标权限失败，err:" + err.Error()
				return
			}
			edbInfoItem.HaveOperaAuth = haveOperaAuth
		}
	}

	resp.Paging = page
	resp.Item = edbInfoItem
	resp.ClassifyList = classifyList
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// Add
// @Title 新增指标接口
// @Description 新增指标接口
// @Param	request	body request.AddPredictEdbInfoReq true "type json string"
// @Success 200 {object} response.AddEdbInfoResp
// @router /predict_edb_info/add [post]
func (this *PredictEdbInfoController) Add() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	deleteCache := true
	cacheKey := "CACHE_EDB_INFO_ADD_" + strconv.Itoa(sysUser.AdminId)
	defer func() {
		if deleteCache {
			utils.Rc.Delete(cacheKey)
		}
	}()
	if !utils.Rc.SetNX(cacheKey, 1, 30*time.Second) {
		deleteCache = false
		br.Msg = "系统处理中，请稍后重试！"
		br.ErrMsg = "系统处理中，请稍后重试！" + sysUser.RealName + ";data:" + string(this.Ctx.Input.RequestBody)
		return
	}
	var req request.AddPredictEdbInfoReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	sourceEdbInfoId := req.SourceEdbInfoId
	if sourceEdbInfoId <= 0 {
		br.Msg = "请选择来源指标"
		br.IsSendEmail = false
		return
	}

	if req.EdbName == "" {
		br.Msg = "指标名称不能为空"
		br.IsSendEmail = false
		return
	}

	if req.ClassifyId <= 0 {
		br.Msg = "请选择分类"
		br.IsSendEmail = false
		return
	}

	if len(req.RuleList) <= 0 {
		br.Msg = "请填写预测规则"
		br.IsSendEmail = false
		return
	}

	// 根据截止日期重新排序
	ruleList := make([]request.RuleConfig, 0)
	{
		ruleMap := make(map[string]request.RuleConfig)
		dateIntList := make([]int64, 0)
		for _, v := range req.RuleList {
			confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
			if err != nil {
				br.Msg = "配置项中时间异常，请重新选择"
				br.ErrMsg = "配置项中时间异常，请重新选择,err:" + err.Error()
				br.IsSendEmail = false
				return
			}
			dateIntList = append(dateIntList, confEndDate.Unix())
			ruleMap[v.EndDate] = v
		}
		sort.Slice(dateIntList, func(i, j int) bool {
			return dateIntList[i] < dateIntList[j]
		})
		for _, dateInt := range dateIntList {
			currDateTime := time.Unix(dateInt, 0)
			item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
			if !ok {
				br.Msg = "配置项中时间异常，请重新选择"
				br.ErrMsg = "配置项中时间异常，请重新选择"
				br.IsSendEmail = false
				return
			}
			ruleList = append(ruleList, item)
		}
	}
	req.RuleList = ruleList

	//传入操作人
	req.AdminId = sysUser.AdminId
	req.AdminName = sysUser.RealName
	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.SaveBasePredictEdbData(string(reqJson), this.Lang)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}
	if respItem.Ret != 200 {
		br.Msg = respItem.Msg
		br.ErrMsg = respItem.ErrMsg
		return
	}
	resp := respItem.Data

	//添加es
	data.AddOrEditEdbInfoToEs(resp.EdbInfoId)

	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
	br.Data = resp
	br.IsAddLog = true
}

// ChartImageSet
// @Title 设置指标的图表图片
// @Description 设置指标的图表图片接口
// @Param	request	body data_manage.SetChartInfoImageReq true "type json string"
// @Success Ret=200 保存成功
// @router /predict_edb_info/image/set [post]
func (this *PredictEdbInfoController) ChartImageSet() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	var req data_manage.SetEdbInfoImageReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	if req.EdbInfoId > 0 && req.ImageUrl != "" {
		edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
		if err != nil {
			br.Msg = "保存失败"
			br.ErrMsg = "保存失败,Err:" + err.Error()
			if err.Error() == utils.ErrNoRow() {
				br.Msg = "找不到该指标"
				br.ErrMsg = "找不到该指标"
				br.IsSendEmail = false
			}
			return
		}

		edbInfo.ChartImage = req.ImageUrl
		err = edbInfo.Update([]string{"ChartImage"})
		if err != nil {
			br.Msg = "保存失败"
			br.ErrMsg = "保存失败,Err:" + err.Error()
			return
		}

		//修改es数据
		go data.AddOrEditEdbInfoToEs(req.EdbInfoId)
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
}

// Edit
// @Title 编辑指标接口
// @Description 编辑指标接口
// @Success 200 {object} request.EditEdbInfoReq
// @router /predict_edb_info/edit [post]
func (this *PredictEdbInfoController) Edit() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	var req request.AddPredictEdbInfoReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	edbInfoId := req.EdbInfoId
	if edbInfoId <= 0 {
		br.Msg = "请选择预测指标"
		br.IsSendEmail = false
		return
	}

	if req.EdbName == "" {
		br.Msg = "指标名称不能为空"
		br.IsSendEmail = false
		return
	}

	if req.ClassifyId <= 0 {
		br.Msg = "请选择分类"
		br.IsSendEmail = false
		return
	}

	if len(req.RuleList) <= 0 {
		br.Msg = "请填写预测规则"
		br.IsSendEmail = false
		return
	}

	// 根据截止日期重新排序
	ruleList := make([]request.RuleConfig, 0)
	{
		ruleMap := make(map[string]request.RuleConfig)
		dateIntList := make([]int64, 0)
		for _, v := range req.RuleList {
			confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
			if err != nil {
				br.Msg = "配置项中时间异常，请重新选择"
				br.ErrMsg = "配置项中时间异常，请重新选择,err:" + err.Error()
				br.IsSendEmail = false
				return
			}
			dateIntList = append(dateIntList, confEndDate.Unix())
			ruleMap[v.EndDate] = v
		}
		sort.Slice(dateIntList, func(i, j int) bool {
			return dateIntList[i] < dateIntList[j]
		})
		for _, dateInt := range dateIntList {
			currDateTime := time.Unix(dateInt, 0)
			item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
			if !ok {
				br.Msg = "配置项中时间异常，请重新选择"
				br.ErrMsg = "配置项中时间异常，请重新选择"
				br.IsSendEmail = false
				return
			}
			ruleList = append(ruleList, item)
		}
	}
	req.RuleList = ruleList

	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
	if err != nil {
		br.Msg = "修改失败"
		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
		return
	}

	var haveOperaAuth bool
	// 数据权限校验
	{
		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, this.SysUser.AdminId)
		if err != nil {
			br.Msg = err.Error()
			br.ErrMsg = "校验指标权限失败，err:" + err.Error()
			return
		}
	}

	// 编辑权限校验
	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId, haveOperaAuth)
	if !button.OpButton {
		br.Msg = "无权限操作"
		br.IsSendEmail = false
		return
	}

	//传入操作人
	req.AdminId = sysUser.AdminId
	req.AdminName = sysUser.RealName
	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.SaveBasePredictEdbData(string(reqJson), this.Lang)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}
	if respItem.Ret != 200 {
		br.Msg = respItem.Msg
		br.ErrMsg = respItem.ErrMsg
		return
	}
	resp := respItem.Data

	//修改es
	data.AddOrEditEdbInfoToEs(resp.EdbInfoId)

	// 刷新关联指标
	go data.EdbInfoRefreshAllFromBaseV2(resp.EdbInfoId, true, false)

	br.Ret = 200
	br.Success = true
	br.Msg = "修改成功"
	br.IsAddLog = true
}

// Refresh
// @Title 指标刷新接口
// @Description 指标刷新接口
// @Param   EdbInfoId   query   int  true       "指标id"
// @Success Ret=200 刷新成功
// @router /predict_edb_info/refresh [get]
func (this *PredictEdbInfoController) Refresh() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	edbInfoId, _ := this.GetInt("EdbInfoId")
	if edbInfoId <= 0 {
		br.Msg = "参数错误"
		br.ErrMsg = "参数错误"
		return
	}
	_, isAsync, err, errMsg := data.RefreshPredictEdbInfo(edbInfoId, false)
	if errMsg != `` {
		br.Msg = errMsg
		br.ErrMsg = errMsg
		if err != nil {
			br.ErrMsg = err.Error()
		} else {
			br.IsSendEmail = false
		}
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "刷新成功"
	if isAsync {
		br.Msg = "该指标关联指标较多，请10分钟后刷新页面查看最新数据"
	}
}

// Move
// @Title 移动指标接口
// @Description 移动指标接口
// @Success 200 {object} data_manage.MoveEdbInfoReq
// @router /predict_edb_info/move [post]
func (this *PredictEdbInfoController) Move() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	var req data_manage.MoveEdbInfoReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	if req.EdbInfoId <= 0 {
		br.Msg = "参数错误"
		br.ErrMsg = "指标id小于等于0"
		return
	}

	if req.ClassifyId <= 0 {
		br.Msg = "请选择分类"
		return
	}

	// 移动预测指标
	err, errMsg := data.MovePredictEdbInfo(req.EdbInfoId, req.ClassifyId, req.PrevEdbInfoId, req.NextEdbInfoId, sysUser, string(this.Ctx.Input.RequestBody), this.Ctx.Input.URI())
	if errMsg != `` {
		br.Msg = errMsg
		br.ErrMsg = errMsg
		if err != nil {
			br.ErrMsg = errMsg + ";Err:" + err.Error()
		} else {
			br.IsSendEmail = false
		}
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "移动成功"
}

// Detail
// @Title 获取指标详情
// @Description 获取指标详情接口
// @Param   EdbInfoId   query   int  true       "指标id"
// @Success 200 {object} response.PredictEdbInfo
// @router /predict_edb_info/detail [get]
func (this *PredictEdbInfoController) Detail() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	edbInfoId, _ := this.GetInt("EdbInfoId")
	if edbInfoId <= 0 {
		br.Msg = "参数错误"
		br.ErrMsg = "参数错误"
		return
	}
	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取指标信息失败，Err:" + err.Error()
		return
	}

	var ruleType int
	var fixedValue float64
	calculateList := make([]*data_manage.EdbInfoCalculateDetail, 0)
	predictEdbConfList := make([]data_manage.PredictEdbConfDetail, 0)
	calculateList, err = data_manage.GetEdbInfoCalculateDetail(edbInfoId, edbInfo.Source)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败，Err:" + err.Error()
		return
	}
	if edbInfo.EdbType == 1 {
		// 获取所有的指标预测规则配置
		tmpPredictEdbConfList, err := data_manage.GetPredictEdbConfListById(edbInfoId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			br.Msg = "获取失败"
			br.ErrMsg = "获取预测指标配置信息失败，Err:" + err.Error()
			return
		}
		for _, v := range tmpPredictEdbConfList {
			var tmpPredictEdbConfCalculateMappingDetail []*data_manage.PredictEdbConfCalculateMappingDetail
			if v.RuleType == 9 || v.RuleType == 14 {
				tmpPredictEdbConfCalculateMappingDetail, err = data_manage.GetPredictEdbConfCalculateMappingDetailListByConfigId(v.PredictEdbInfoId, v.ConfigId)
				if err != nil && err.Error() != utils.ErrNoRow() {
					br.Msg = "获取失败"
					br.ErrMsg = "获取预测指标配置与关联指标信息失败，Err:" + err.Error()
					return
				}
			}
			if len(tmpPredictEdbConfCalculateMappingDetail) <= 0 {
				tmpPredictEdbConfCalculateMappingDetail = make([]*data_manage.PredictEdbConfCalculateMappingDetail, 0)
			}
			tmp := data_manage.PredictEdbConfDetail{
				ConfigId:         v.ConfigId,
				PredictEdbInfoId: v.PredictEdbInfoId,
				SourceEdbInfoId:  v.SourceEdbInfoId,
				RuleType:         v.RuleType,
				FixedValue:       v.FixedValue,
				Value:            v.Value,
				EmptyType:        v.EmptyType,
				MaxEmptyType:     v.MaxEmptyType,
				EndDate:          v.EndDate,
				ModifyTime:       v.ModifyTime,
				CreateTime:       v.CreateTime,
				CalculateList:    tmpPredictEdbConfCalculateMappingDetail,
			}
			predictEdbConfList = append(predictEdbConfList, tmp)
		}
		//calculateList, err = data_manage.GetEdbInfoCalculateDetail(edbInfoId, edbInfo.Source)
		//if err != nil {
		//	br.Msg = "获取失败"
		//	br.ErrMsg = "获取失败，Err:" + err.Error()
		//	return
		//}
		if len(predictEdbConfList) == 0 {
			br.Msg = "找不到该预测指标配置"
			br.ErrMsg = "找不到该预测指标配置"
			return
		}
		predictEdbConf := predictEdbConfList[0]
		ruleType = predictEdbConf.RuleType
		fixedValue = predictEdbConf.FixedValue
	}

	findEdbInfoIdList := make([]int, 0)
	for k, v := range calculateList {
		if v.LatestDate != v.EndDate && v.LatestDate != `` && v.EndDate != `` {
			tmpLatestDate, _ := time.ParseInLocation(utils.FormatDate, v.LatestDate, time.Local)
			tmpEndDate, _ := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
			if tmpEndDate.After(tmpLatestDate) {
				findEdbInfoIdList = append(findEdbInfoIdList, v.FromEdbInfoId)
			}
		}
		v.EndValue = v.LatestValue
		calculateList[k] = v
	}
	if len(findEdbInfoIdList) > 0 {
		edbDataInsertConfigList, err := data_manage.GetEdbDataInsertConfigByEdbIdList(findEdbInfoIdList)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取失败插入值失败，Err:" + err.Error()
			return
		}
		edbDataInsertConfigMap := make(map[int]*data_manage.EdbDataInsertConfig)
		for _, v := range edbDataInsertConfigList {
			edbDataInsertConfigMap[v.EdbInfoId] = v
		}

		for k, v := range calculateList {
			edbDataInsertConfig, ok := edbDataInsertConfigMap[v.FromEdbInfoId]
			if !ok {
				continue
			}
			if v.EndDate != `` && v.EndDate == edbDataInsertConfig.Date.Format(utils.FormatDate) {
				t, tmpErr := decimal.NewFromString(edbDataInsertConfig.Value)
				if tmpErr != nil {
					continue
				}
				v.EndValue, _ = t.Float64()
			}
			calculateList[k] = v
		}
	}
	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfo.ClassifyId)
	if err != nil {
		br.Msg = err.Error()
		br.ErrMsg = errMsg
		return
	}

	edbInfoFull := new(response.EdbInfoFull)
	edbInfoFull.EdbInfo = edbInfo
	// 权限校验
	{
		classifyMap := make(map[int]*data_manage.EdbClassifyIdItems)
		for _, v := range classifyList {
			classifyMap[v.ClassifyId] = v
		}
		if currClassify, ok := classifyMap[edbInfo.ClassifyId]; ok {
			haveOperaAuth, err := data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassify.IsJoinPermission, this.SysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
			if err != nil {
				br.Msg = err.Error()
				br.ErrMsg = "校验指标权限失败，err:" + err.Error()
				return
			}
			edbInfoFull.HaveOperaAuth = haveOperaAuth
		}
	}

	// 拟合残差计算相关系数
	var correlationStr string
	if edbInfo.Source == utils.DATA_SOURCE_PREDICT_CALCULATE_NHCC {
		var aEdbInfo, bEdbInfo *data_manage.EdbInfoCalculateDetail
		for _, v := range calculateList {
			if v.FromTag == "A" {
				aEdbInfo = v
				continue
			}
			if v.FromTag == "B" {
				bEdbInfo = v
				continue
			}
		}
		if aEdbInfo != nil && bEdbInfo != nil {
			edbInfoFromTagList := []data_manage.EdbInfoFromTag{
				{
					EdbInfoId: aEdbInfo.FromEdbInfoId,
					FromTag:   aEdbInfo.FromTag,
					MoveValue: aEdbInfo.MoveValue,
				}, {
					EdbInfoId: bEdbInfo.FromEdbInfoId,
					FromTag:   bEdbInfo.FromTag,
					MoveValue: bEdbInfo.MoveValue,
				},
			}

			req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
				AdminId:      sysUser.AdminId,
				AdminName:    sysUser.RealName,
				Formula:      edbInfo.CalculateFormula,
				EdbInfoIdArr: edbInfoFromTagList,
			}

			// 计算
			val, err, _ := data.CallCalculateComputeCorrelation(req2, this.Lang)
			if err == nil {
				correlationStr = val
			}
		}

	}

	resp := response.PredictEdbInfo{
		EdbInfoFull:    edbInfoFull,
		RuleType:       ruleType,
		FixedValue:     fixedValue,
		CalculateList:  calculateList,
		RuleList:       predictEdbConfList,
		CorrelationStr: correlationStr,
		ClassifyList:   classifyList,
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// FilterByEs
// @Title 指标筛选接口
// @Description 指标筛选接口
// @Param   KeyWord   query   string  false       "搜索关键词:指标ID/指标名称"
// @Param   FilterSource   query   int  false       "搜索来源:1:其他搜索,2:累计值转月值搜索,3:变频，4：基础指标，5：同比"
// @Param   Frequency   query   string  false       "频度"
// @Param   IsOnlyMe   query   bool  false       "是否只看我的"
// @Param   PageSize   query   int  true       "每页数据条数"
// @Param   CurrentIndex   query   int  true       "当前页页码，从1开始"
// @Success 200 {object} data_manage.EdbInfoList
// @router /predict_edb_info/filter_by_es [get]
func (this *PredictEdbInfoController) FilterByEs() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	pageSize, _ := this.GetInt("PageSize")
	currentIndex, _ := this.GetInt("CurrentIndex")

	var total int64

	var startSize int
	if pageSize <= 0 {
		pageSize = utils.PageSize20
	}
	if currentIndex <= 0 {
		currentIndex = 1
	}
	startSize = paging.StartIndex(currentIndex, pageSize)

	keyWord := this.GetString("Keyword")
	keyWord = strings.TrimSpace(keyWord) //移除字符串首尾空格
	//兼容前端
	if keyWord == `` {
		keyWord = this.GetString("KeyWord")
		keyWord = strings.TrimSpace(keyWord) //移除字符串首尾空格
	}
	filterSource, _ := this.GetInt("FilterSource")
	if filterSource <= 0 {
		filterSource = 1
	}
	//指标来源
	source, _ := this.GetInt("Source")

	frequency := this.GetString("Frequency") //频度
	isOnlyMe, _ := this.GetBool("IsOnlyMe")

	var edbInfoList []*data_manage.EdbInfoList
	var err error

	noPermissionEdbInfoIdList := make([]int, 0) //无权限指标
	// 获取当前账号的不可见指标
	{
		obj := data_manage.EdbInfoNoPermissionAdmin{}
		confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
		if err != nil && err.Error() != utils.ErrNoRow() {
			br.Msg = "获取失败"
			br.ErrMsg = "获取不可见指标配置数据失败，Err:" + err.Error()
			return
		}
		for _, v := range confList {
			noPermissionEdbInfoIdList = append(noPermissionEdbInfoIdList, v.EdbInfoId)
		}
	}

	// 是否走ES
	isEs := false
	if keyWord != "" {
		var keyWordArr []string
		keyWordArr = append(keyWordArr, keyWord)

		newKeyWord := strings.Split(keyWord, " ")
		keyWordArr = append(keyWordArr, newKeyWord...)
		if isOnlyMe {
			total, edbInfoList, err = elastic.SearchEdbInfoDataByAdminId(utils.DATA_INDEX_NAME, keyWord, startSize, pageSize, filterSource, source, 1, frequency, this.SysUser.AdminId)
		} else {
			total, edbInfoList, err = elastic.SearchEdbInfoData(utils.DATA_INDEX_NAME, keyWord, startSize, pageSize, filterSource, source, 1, frequency, noPermissionEdbInfoIdList)
		}
		isEs = true
	} else {
		var condition string
		var pars []interface{}
		// 预测指标
		condition += ` AND edb_info_type = ? `
		pars = append(pars, 1)
		// 无权限指标id
		lenNoPermissionEdbInfoIdList := len(noPermissionEdbInfoIdList)
		if lenNoPermissionEdbInfoIdList > 0 {
			condition += ` AND edb_info_id  not in (` + utils.GetOrmInReplace(lenNoPermissionEdbInfoIdList) + `) `
			pars = append(pars, noPermissionEdbInfoIdList)
		}

		switch filterSource {
		case 2:
			condition += ` AND frequency='月度' `
		case 3:
			condition += ` AND frequency <> '日度' `
		case 4:
			condition += ` AND edb_type = 1 `
		case 5:
			condition += ` AND source = 32 ` //来源（预测同比值）
		case 6:
			condition += ` AND frequency != ? `
			pars = append(pars, "年度")
		}

		//频度
		if frequency != "" {
			condition += ` AND frequency = ? `
			pars = append(pars, frequency)
		}

		if isOnlyMe {
			condition += " AND sys_user_id = ? "
			pars = append(pars, this.SysUser.AdminId)
		}

		total, edbInfoList, err = data_manage.GetEdbInfoFilterList(condition, pars, startSize, pageSize)
	}
	if err != nil {
		edbInfoList = make([]*data_manage.EdbInfoList, 0)
	}

	page := paging.GetPaging(currentIndex, pageSize, int(total))

	edbInfoListLen := len(edbInfoList)

	classifyIdList := make([]int, 0)
	for i := 0; i < edbInfoListLen; i++ {
		edbInfoList[i].EdbNameAlias = edbInfoList[i].EdbName
		classifyIdList = append(classifyIdList, edbInfoList[i].ClassifyId)
	}

	// 当前列表中的分类map
	classifyMap := make(map[int]*data_manage.EdbClassify)
	if edbInfoListLen > 0 {
		classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取分类列表失败，Err:" + err.Error()
			return
		}

		for _, v := range classifyList {
			classifyMap[v.ClassifyId] = v
		}

		// 获取所有有权限的指标和分类
		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取所有有权限的指标和分类失败，Err:" + err.Error()
			return
		}

		// 如果是ES的话，需要重新查一下指标的信息，主要是为了把是否授权字段找出来
		if isEs {
			edbInfoIdList := make([]int, 0)
			for i := 0; i < edbInfoListLen; i++ {
				edbInfoIdList = append(edbInfoIdList, edbInfoList[i].EdbInfoId)
				tmpEdbInfo := edbInfoList[i]
				if currClassify, ok := classifyMap[tmpEdbInfo.ClassifyId]; ok {
					edbInfoList[i].HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(tmpEdbInfo.IsJoinPermission, currClassify.IsJoinPermission, tmpEdbInfo.EdbInfoId, tmpEdbInfo.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
				}
			}

			tmpEdbList, err := data_manage.GetEdbInfoByIdList(edbInfoIdList)
			if err != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取所有有权限的指标和分类失败，Err:" + err.Error()
				return
			}
			edbInfoMap := make(map[int]*data_manage.EdbInfo)
			for _, v := range tmpEdbList {
				edbInfoMap[v.EdbInfoId] = v
			}

			for i := 0; i < edbInfoListLen; i++ {
				tmpEdbInfo, ok := edbInfoMap[edbInfoList[i].EdbInfoId]
				if !ok {
					continue
				}
				edbInfoList[i].IsJoinPermission = tmpEdbInfo.IsJoinPermission
			}
		}

		// 权限校验
		for i := 0; i < edbInfoListLen; i++ {
			tmpEdbInfo := edbInfoList[i]
			if currClassify, ok := classifyMap[tmpEdbInfo.ClassifyId]; ok {
				edbInfoList[i].HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(tmpEdbInfo.IsJoinPermission, currClassify.IsJoinPermission, tmpEdbInfo.EdbInfoId, tmpEdbInfo.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
			}
		}

	}

	for i := 0; i < edbInfoListLen; i++ {
		for j := 0; j < edbInfoListLen; j++ {
			if (edbInfoList[i].EdbNameAlias == edbInfoList[j].EdbNameAlias) &&
				(edbInfoList[i].EdbInfoId != edbInfoList[j].EdbInfoId) &&
				!(strings.Contains(edbInfoList[i].EdbName, edbInfoList[i].SourceName)) {
				edbInfoList[i].EdbName = edbInfoList[i].EdbName + "(" + edbInfoList[i].SourceName + ")"
			}
		}
	}
	//新增搜索词记录
	{
		searchKeyword := new(data_manage.SearchKeyword)
		searchKeyword.KeyWord = keyWord
		searchKeyword.CreateTime = time.Now()
		go data_manage.AddSearchKeyword(searchKeyword)
	}

	resp := data_manage.EdbInfoFilterDataResp{
		Paging: page,
		List:   edbInfoList,
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// RefreshAll
// @Title 指标全部刷新接口
// @Description 指标全部刷新接口
// @Param   EdbInfoId   query   int  true       "指标id"
// @Success Ret=200 全部刷新成功
// @router /predict_edb_info/refresh/all [get]
func (this *PredictEdbInfoController) RefreshAll() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	edbInfoId, _ := this.GetInt("EdbInfoId")
	if edbInfoId <= 0 {
		br.Msg = "参数错误"
		br.ErrMsg = "参数错误"
		return
	}
	_, isAsync, err, errMsg := data.RefreshPredictEdbInfo(edbInfoId, true)
	if errMsg != `` {
		br.Msg = errMsg
		br.ErrMsg = errMsg
		if err != nil {
			br.ErrMsg = err.Error()
		} else {
			br.IsSendEmail = false
		}
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "刷新成功"
	if isAsync {
		br.Msg = "该指标关联指标较多，请10分钟后刷新页面查看最新数据"
	}
}

// DataList
// @Title 获取指标数据
// @Description 获取指标数据
// @Param   EdbInfoId   query   int  true       "指标ID"
// @Param   DateType   query   int  true       "日期类型:1:00年至今,2:10年至今,3:15年至今，4：年初至今，5:自定义时间,6:自定义起始时间至今，7：18年至今,8:19年至今,9:20年至今,10:全部"
// @Param   StartDate   query   string  true       "自定义开始日期"
// @Param   EndDate   query   string  true       "自定义结束日期"
// @Param   Calendar   query   string  true       "公历/农历"
// @Param   SeasonStartDate   query   string  true       "季节性图开始日期"
// @Param   SeasonEndDate   query   string  true       "季节性图结束日期"
// @Param   ChartType   query   int  true       "生成样式:1:曲线图,2:季节性图"
// @Success 200 {object} data_manage.EdbInfoDataResp
// @router /predict_edb_info/data [get]
func (this *PredictEdbInfoController) DataList() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	edbInfoId, _ := this.GetInt("EdbInfoId")
	if edbInfoId <= 0 {
		br.Msg = "参数错误"
		return
	}
	dateType, _ := this.GetInt("DateType")
	if dateType <= 0 {
		dateType = 3
	}

	edbInfoType, _ := this.GetInt("EdbInfoType")
	if edbInfoType < 0 {
		edbInfoType = 1
	}

	startDate := this.GetString("StartDate")
	endDate := this.GetString("EndDate")
	startYear, _ := this.GetInt("StartYear")

	chartType, _ := this.GetInt("ChartType")
	if chartType <= 0 {
		chartType = 1
	}

	calendar := this.GetString("Calendar")
	if calendar == "" {
		calendar = "公历"
	}
	isTimeBetween := false //是否是时间区间

	if chartType == 2 {
		dateType = 0
		isTimeBetween = true
	}
	if dateType == 5 {
		isTimeBetween = true
	}
	fullEdb := new(response.EdbInfoFull)

	// 获取预测指标信息
	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
	if err != nil {
		br.Msg = "获取预测指标信息失败"
		br.ErrMsg = "获取预测指标信息失败,Err:" + err.Error()
		return
	}
	fullEdb.EdbInfo = edbInfo
	classifyList, err, errMsg := data.GetFullClassifyByClassifyId(edbInfo.ClassifyId)
	if err != nil {
		br.Msg = err.Error()
		br.ErrMsg = errMsg
		return
	}
	var currClassifyItem *data_manage.EdbClassifyIdItems
	for _, v := range classifyList {
		if v.ClassifyId == edbInfo.ClassifyId {
			currClassifyItem = v
			break
		}
	}
	if currClassifyItem != nil {
		fullEdb.HaveOperaAuth, err = data_manage_permission.CheckEdbPermission(edbInfo.IsJoinPermission, currClassifyItem.IsJoinPermission, sysUser.AdminId, edbInfo.EdbInfoId, edbInfo.ClassifyId)
		if err != nil {
			br.Msg = err.Error()
			br.ErrMsg = "校验指标权限失败，err:" + err.Error()
			return
		}
	}

	maxYear := 0
	if edbInfo.LatestDate != "" {
		latestDateT, _ := time.Parse(utils.FormatDate, edbInfo.LatestDate)
		maxYear = latestDateT.Year()
	}

	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
	if endDate == "" {
		endDate = time.Now().Format(utils.FormatDate)
	}

	if dateType == 10 {
		startDate = ""
		endDate = ""
	}
	// 按钮校验
	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId, fullEdb.HaveOperaAuth)
	button.AddButton = false

	resp := response.PredictEdbInfoDataResp{
		EdbInfo:      fullEdb,
		Button:       button,
		ClassifyList: classifyList,
	}

	if fullEdb.HaveOperaAuth {
		dataList, _, _, err, _ := data.GetPredictDataListByPredictEdbInfo(edbInfo, startDate, endDate, isTimeBetween)
		//lenDataList := len(dataList)
		//if lenDataList > 0 {
		//	tmpValue := dataList[lenDataList-1]
		//
		//	// 如果最大值 小于 预测值，那么将预测值作为最大值数据返回
		//	if edbInfo.MaxValue < tmpValue.Value {
		//		edbInfo.MaxValue = tmpValue.Value
		//	}
		//
		//	// 如果最小值 大于 预测值，那么将预测值作为最小值数据返回
		//	if edbInfo.MinValue > tmpValue.Value {
		//		edbInfo.MinValue = tmpValue.Value
		//	}
		//}

		// 季节性图、公历、农历处理
		resultDataList, err := data.GetChartDataList(dataList, chartType, calendar, edbInfo.LatestDate, startDate)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取失败,Err:" + err.Error()
			return
		}

		resp.DataList = resultDataList
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// ChartDataList
// @Title 获取指标数据
// @Description 获取指标数据
// @Param	request	body data_manage.AddPredictEdbInfoReq true "type json string"
// @Success 200 {object} data_manage.EdbInfoDataResp
// @router /predict_edb_info/chart/data/list [post]
func (this *PredictEdbInfoController) ChartDataList() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.PredictEdbInfoChartDataReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if req.SourceEdbInfoId <= 0 {
		br.Msg = "参数错误"
		return
	}

	dateType := req.DateType
	startDate := req.StartDate
	endDate := req.EndDate
	//seasonStartDate := req.SeasonStartDate
	//seasonEndDate := req.SeasonEndDate
	startYear := req.StartYear

	calendar := req.Calendar
	if calendar == "" {
		calendar = "公历"
	}

	isTimeBetween := false //是否是时间区间

	if req.ChartType == 2 {
		dateType = 0
		isTimeBetween = true
	}
	if dateType == 5 {
		isTimeBetween = true
	}

	// 规则列表
	// 根据截止日期重新排序
	ruleList := make([]request.RuleConfig, 0)
	{
		ruleMap := make(map[string]request.RuleConfig)
		dateIntList := make([]int64, 0)
		for _, v := range req.RuleList {
			confEndDate, err := time.Parse(utils.FormatDate, v.EndDate)
			if err != nil {
				br.Msg = "配置项中时间异常，请重新选择"
				br.ErrMsg = "配置项中时间异常，请重新选择,err:" + err.Error()
				br.IsSendEmail = false
				return
			}
			dateIntList = append(dateIntList, confEndDate.Unix())
			ruleMap[v.EndDate] = v
		}
		sort.Slice(dateIntList, func(i, j int) bool {
			return dateIntList[i] < dateIntList[j]
		})
		for _, dateInt := range dateIntList {
			currDateTime := time.Unix(dateInt, 0)
			item, ok := ruleMap[currDateTime.Format(utils.FormatDate)]
			if !ok {
				br.Msg = "配置项中时间异常，请重新选择"
				br.ErrMsg = "配置项中时间异常，请重新选择"
				br.IsSendEmail = false
				return
			}
			ruleList = append(ruleList, item)
		}
	}

	// 预测指标配置
	predictEdbConfAndDataList := make([]data_manage.PredictEdbConfAndData, 0)

	endDateStr := `` //数据的结束日期
	for _, v := range ruleList {
		endDateStr = v.EndDate //预测指标的结束日期
		confEndDate, err := time.ParseInLocation(utils.FormatDate, v.EndDate, time.Local)
		if err != nil {
			br.Msg = "配置项中时间异常，请重新选择"
			br.ErrMsg = "配置项中时间异常，请重新选择,err:" + err.Error()
			return
		}
		// 没有数据，自己瞎测试
		//switch v.RuleType {
		//case 3: //3：同比
		//	v.Value = "0.1"
		//case 4: //4：同差
		//	v.Value = "10"
		//case 5: //5：环比
		//	v.Value = "0.1"
		//case 6: //6：环差
		//	v.Value = "0.1"
		//case 7: //7：N期移动均值
		//	v.Value = "5"
		//case 8: //8：N期段线性外推值
		//	v.Value = "5"
		//}

		tmpDataList := make([]*data_manage.EdbDataList, 0)
		switch v.RuleType {
		case 9:
			// 获取计算参数
			/*formula, edbInfoList, edbInfoIdBytes, err, errMsg := data.GetCalculateByRuleByNineParams(v)
			if err != nil {
				br.Msg = "计算失败"
				if errMsg != "" {
					br.Msg = errMsg
				}
				br.Msg = err.Error()
				br.IsSendEmail = false
				return
			}
			// 获取计算数据
			tmpDataList, err = data.CalculateByRuleByNine(formula, edbInfoList, edbInfoIdBytes, v.EmptyType, v.MaxEmptyType)
			if err != nil {
				br.Msg = "计算失败"
				br.ErrMsg = err.Error()
				br.IsSendEmail = false
				return
			}*/
			reqJson, err := json.Marshal(v)
			respItem, err := data.PredictCalculateByNinePreview(string(reqJson), this.Lang)
			if err != nil {
				br.Msg = "获取失败"
				br.ErrMsg = "获取失败,Err:" + err.Error()
				return
			}
			if respItem.Ret != 200 {
				br.Msg = respItem.Msg
				br.ErrMsg = respItem.ErrMsg
				return
			}
			tmpDataList = respItem.Data.DataList
		}
		tmpPredictEdbConfAndData := data_manage.PredictEdbConfAndData{
			ConfigId:         0,
			PredictEdbInfoId: 0,
			SourceEdbInfoId:  req.SourceEdbInfoId,
			RuleType:         v.RuleType,
			FixedValue:       0,
			Value:            v.Value,
			EndDate:          confEndDate,
			ModifyTime:       time.Now(),
			CreateTime:       time.Now(),
			DataList:         tmpDataList,
		}
		predictEdbConfAndDataList = append(predictEdbConfAndDataList, tmpPredictEdbConfAndData)
	}

	// 来源指标
	sourceEdbInfoItem, err := data_manage.GetEdbInfoById(req.SourceEdbInfoId)
	if err != nil {
		br.Msg = "获取来源指标信息失败"
		br.ErrMsg = "获取来源指标信息失败"
		if err.Error() != utils.ErrNoRow() {
			br.ErrMsg = "获取来源指标信息失败,Err:" + err.Error()
		}
		br.Success = true
		return
	}
	// todo 确认预测指标是否用的是来源指标的最新日期
	maxYear := 0
	if sourceEdbInfoItem.LatestDate != "" {
		latestDateT, _ := time.Parse(utils.FormatDate, sourceEdbInfoItem.LatestDate)
		maxYear = latestDateT.Year()
	}

	startDate, endDate = utils.GetDateByDateTypeV2(dateType, startDate, endDate, startYear, maxYear)
	if endDate == "" {
		endDate = time.Now().Format(utils.FormatDate)
	}

	if dateType == 10 {
		startDate = ""
		endDate = ""
	}

	minValue := sourceEdbInfoItem.MinValue
	maxValue := sourceEdbInfoItem.MaxValue
	allDataList := make([]*data_manage.EdbDataList, 0)
	//获取指标数据（实际已生成）
	dataList, err := data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, sourceEdbInfoItem.EdbInfoId, startDate, endDate)
	if err != nil {
		br.Msg = "获取失败"
		br.Msg = "获取失败,Err:" + err.Error()
		return
	}

	// 如果选择了日期，那么需要筛选所有的数据，用于未来指标的生成
	if startDate != `` {
		allDataList, err = data_manage.GetEdbDataList(sourceEdbInfoItem.Source, sourceEdbInfoItem.SubSource, sourceEdbInfoItem.EdbInfoId, "", "")
		if err != nil {
			br.Msg = "获取失败"
			br.Msg = "获取失败,Err:" + err.Error()
			return
		}
	} else {
		allDataList = dataList
	}

	// 获取预测指标未来的数据
	if len(predictEdbConfAndDataList) > 0 {
		predictDataList := make([]*data_manage.EdbDataList, 0)
		if isTimeBetween { //如果是时间区间，那么
			reqEndDateTime, _ := time.ParseInLocation(utils.FormatDate, endDate, time.Local)
			endDateTime, _ := time.ParseInLocation(utils.FormatDate, req.PredictEndDate, time.Local)
			// 如果选择的时间区间结束日期 晚于 当天，那么预测数据截止到当天
			if reqEndDateTime.Before(endDateTime) {
				endDateStr = endDate
			}
		}

		// 获取预测数据
		var predictMinValue, predictMaxValue float64

		predictDataList, predictMinValue, predictMaxValue, err, errMsg := data.GetChartPredictEdbInfoDataListByConfList(predictEdbConfAndDataList, startDate, sourceEdbInfoItem.LatestDate, endDateStr, sourceEdbInfoItem.Frequency, req.DataDateType, allDataList)
		if err != nil {
			br.Msg = "获取预测指标数据失败"
			if errMsg != `` {
				br.Msg = errMsg
			}
			br.ErrMsg = "获取预测指标数据失败：" + err.Error()
			return
		}

		dataList = append(dataList, predictDataList...)
		if len(predictDataList) > 0 {
			// 如果最小值 大于 预测值，那么将预测值作为最小值数据返回
			if minValue > predictMinValue {
				minValue = predictMinValue
			}

			// 如果最大值 小于 预测值，那么将预测值作为最大值数据返回
			if maxValue < predictMaxValue {
				maxValue = predictMaxValue
			}
		}
	}

	// 季节性图、公历、农历处理
	resultDataList, err := data.GetChartDataList(dataList, req.ChartType, calendar, sourceEdbInfoItem.LatestDate, startDate)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}

	resp := response.PredictEdbInfoChartDataResp{
		MinValue: minValue,
		MaxValue: maxValue,
		DataList: resultDataList,
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// PredictRuleCalculateByNine
// @Title 根据预测规则9来计算数据
// @Description 获取指标数据
// @Param	request	body data_manage.RuleConfig true "type json string"
// @Success 200 {object} data_manage.EdbInfoDataResp
// @router /predict_edb_info/rule/calculate_by_nine [post]
func (this *PredictEdbInfoController) PredictRuleCalculateByNine() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}
	var req request.RuleConfig
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	respItem, err := data.PredictCalculateByNinePreview(string(reqJson), this.Lang)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}
	if respItem.Ret != 200 {
		br.Msg = respItem.Msg
		br.ErrMsg = respItem.ErrMsg
		return
	}
	resp := respItem.Data

	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}

// Modify
// @Title 修改指标信息接口
// @Description 编辑指标接口
// @Success 200 {object} request.EditEdbInfoReq
// @router /predict_edb_info/modify [post]
func (this *PredictEdbInfoController) Modify() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()
	sysUser := this.SysUser
	if sysUser == nil {
		br.Msg = "请登录"
		br.ErrMsg = "请登录，SysUser Is Empty"
		br.Ret = 408
		return
	}

	var req request.ModifyPredictEdbInfoReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	edbInfoId := req.EdbInfoId
	if edbInfoId <= 0 {
		br.Msg = "请选择预测指标"
		br.IsSendEmail = false
		return
	}

	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
	if err != nil {
		br.Msg = "修改失败"
		br.ErrMsg = "获取指标信息失败,Err:" + err.Error()
		return
	}

	var haveOperaAuth bool
	// 数据权限校验
	{
		haveOperaAuth, err = data_manage_permission.CheckEdbPermissionByEdbInfoId(edbInfo.EdbInfoId, edbInfo.ClassifyId, edbInfo.IsJoinPermission, this.SysUser.AdminId)
		if err != nil {
			br.Msg = err.Error()
			br.ErrMsg = "校验指标权限失败，err:" + err.Error()
			return
		}
	}

	// 编辑权限校验
	button := data.GetPredictEdbOpButton(this.SysUser, edbInfo.SysUserId, haveOperaAuth)
	if !button.OpButton {
		br.Msg = "无权限操作"
		br.IsSendEmail = false
		return
	}

	edbInfo.MaxValue = req.MaxValue
	edbInfo.MinValue = req.MinValue
	edbInfo.ModifyTime = time.Now()
	err = edbInfo.Update([]string{"MaxValue", "MinValue", "ModifyTime"})
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}

	//修改es
	data.AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)

	br.Ret = 200
	br.Success = true
	br.Msg = "修改成功"
	br.IsAddLog = true
}

//func init() {
//	r := new(regression.Regression)
//	r.SetObserved("Murders per annum per 1,000,000 inhabitants")
//	r.SetVar(0, "Inhabitants")
//	r.SetVar(1, "Percent with incomes below $5000")
//	r.SetVar(2, "Percent unemployed")
//	r.Train(
//		regression.DataPoint(11.2, []float64{587000, 16.5, 6.2}),
//		regression.DataPoint(13.4, []float64{643000, 20.5, 6.4}),
//		regression.DataPoint(40.7, []float64{635000, 26.3, 9.3}),
//		regression.DataPoint(5.3, []float64{692000, 16.5, 5.3}),
//		regression.DataPoint(24.8, []float64{1248000, 19.2, 7.3}),
//		regression.DataPoint(12.7, []float64{643000, 16.5, 5.9}),
//		regression.DataPoint(20.9, []float64{1964000, 20.2, 6.4}),
//		regression.DataPoint(35.7, []float64{1531000, 21.3, 7.6}),
//		regression.DataPoint(8.7, []float64{713000, 17.2, 4.9}),
//		regression.DataPoint(9.6, []float64{749000, 14.3, 6.4}),
//		regression.DataPoint(14.5, []float64{7895000, 18.1, 6}),
//		regression.DataPoint(26.9, []float64{762000, 23.1, 7.4}),
//		regression.DataPoint(15.7, []float64{2793000, 19.1, 5.8}),
//		regression.DataPoint(36.2, []float64{741000, 24.7, 8.6}),
//		regression.DataPoint(18.1, []float64{625000, 18.6, 6.5}),
//		regression.DataPoint(28.9, []float64{854000, 24.9, 8.3}),
//		regression.DataPoint(14.9, []float64{716000, 17.9, 6.7}),
//		regression.DataPoint(25.8, []float64{921000, 22.4, 8.6}),
//		regression.DataPoint(21.7, []float64{595000, 20.2, 8.4}),
//		regression.DataPoint(25.7, []float64{3353000, 16.9, 6.7}),
//	)
//	r.Run()
//
//	fmt.Printf("Regression formula:\n%v\n", r.Formula)
//	//fmt.Printf("Regression:\n%s\n", r)
//}

//func init() {
//	//data := []float64{4080, 4070, 4070, 4020, 4020, 4010, 3950, 3980, 4000, 3990, 4020}
//	//median, _ := stats.Median(data)
//	//fmt.Println(median) // 3.65
//	//stats.LinearRegression()
//
//	//data := []float64{ , , , , , , , , }
//
//	data := []Coordinate{
//		{1, 4080},
//		{2, 4070},
//		{3, 4070},
//		{4, 4020},
//		{5, 4020},
//		{6, 4010},
//		{7, 3950},
//		{8, 3980},
//		{9, 4000},
//		{10, 3990},
//		{11, 4020},
//	}
//
//	//r, _ := ct(data)
//
//	ct(data)
//	//fmt.Println(r)
//
//}

//func init() {
//	data.AddOrEditAllEdbInfoToEs()
//}

// ClassifyEdbInfoItems
// @Title 获取分类下指标接口
// @Description 获取分类下指标接口
// @Param   ClassifyId   query   int  true       "分类id"
// @Param   IsShowMe   query   bool  false       "是否只看我的"
// @Success 200 {object} data_manage.EdbClassifyListResp
// @router /predict_edb_info/items [get]
func (this *PredictEdbInfoController) ClassifyEdbInfoItems() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	classifyId, _ := this.GetInt("ClassifyId")
	if classifyId <= 0 {
		br.Msg = "参数错误,请刷新页面"
		return
	}

	// 是否只看我的
	isShowMe, _ := this.GetBool("IsShowMe")

	// 获取当前账号的不可见指标
	obj := data_manage.EdbInfoNoPermissionAdmin{}
	confList, err := obj.GetAllListByAdminId(this.SysUser.AdminId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		br.Msg = "获取失败"
		br.ErrMsg = "获取不可见指标配置数据失败，Err:" + err.Error()
		return
	}
	noPermissionEdbInfoIdMap := make(map[int]bool)
	for _, v := range confList {
		noPermissionEdbInfoIdMap[v.EdbInfoId] = true
	}

	// 如果选择了只看我的，那么只查询归属于我的账号
	sysUserId := 0
	if isShowMe {
		sysUserId = this.SysUser.AdminId
	}

	allEdbInfo, err := data_manage.GetEdbInfoByClassifyId(classifyId, 1, sysUserId)
	if err != nil && err.Error() != utils.ErrNoRow() {
		br.Msg = "获取失败"
		br.ErrMsg = "获取数据失败，Err:" + err.Error()
		return
	}

	list := make([]*data_manage.EdbClassifyItems, 0)

	edbInfoNum := len(allEdbInfo)
	if edbInfoNum > 0 {
		classifyIdList := make([]int, 0)
		for _, v := range allEdbInfo {
			classifyIdList = append(classifyIdList, v.ClassifyId)
		}

		classifyList, err := data_manage.GetEdbClassifyByIdList(classifyIdList)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取分类数据失败，Err:" + err.Error()
			return
		}

		// 分类map
		classifyMap := make(map[int]*data_manage.EdbClassify)
		for _, v := range classifyList {
			classifyMap[v.ClassifyId] = v
		}

		// 获取所有有权限的指标和分类
		permissionEdbIdList, permissionClassifyIdList, err := data_manage_permission.GetUserEdbAndClassifyPermissionList(this.SysUser.AdminId, 0, 0)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取所有有权限的指标和分类失败，Err:" + err.Error()
			return
		}

		for _, v := range allEdbInfo {
			// 如果指标不可见，那么就不返回该指标
			if _, ok := noPermissionEdbInfoIdMap[v.EdbInfoId]; ok {
				continue
			}

			// 数据权限
			if classifyInfo, ok := classifyMap[v.ClassifyId]; ok {
				v.HaveOperaAuth = data_manage_permission.CheckEdbPermissionByPermissionIdList(v.IsJoinPermission, classifyInfo.IsJoinPermission, v.EdbInfoId, v.ClassifyId, permissionEdbIdList, permissionClassifyIdList)
			}

			button := data.GetEdbOpButton(this.SysUser, v.SysUserId, v.EdbType, utils.EDB_INFO_TYPE, v.HaveOperaAuth)
			button.AddButton = false //不管有没有权限，指标都是没有添加按钮的
			v.Button = button

			list = append(list, v)
		}
	}

	resp := new(data_manage.ClassifyEdbInfoListResp)
	resp.EdbInfoList = list
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = resp
}
