package data_manage

import (
	"encoding/json"
	"eta/eta_api/controllers"
	"eta/eta_api/models"
	"eta/eta_api/models/data_manage"
	"eta/eta_api/services/data"
	"eta/eta_api/utils"
	"fmt"
	"net/url"
	"strconv"
	"strings"
	"time"
)

// 计算指标
type EdbInfoCalculateController struct {
	controllers.BaseAuthController
}

// @Title 生成计算指标
// @Description 生成计算指标接口
// @Param	request	body data_manage.EdbInfoCalculateSaveReq true "type json string"
// @Success Ret=200 返回图表id
// @router /edb_info/calculate/save [post]
func (this *ChartInfoController) CalculateSave() {
	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.EdbInfoCalculateSaveReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	req.EdbName = strings.Trim(req.EdbName, " ")
	if req.EdbName == "" {
		br.Msg = "指标名称不能为空"
		return
	}

	if req.Frequency == "" {
		br.Msg = "频率不能为空"
		return
	}

	if req.Unit == "" {
		br.Msg = "单位不能为空"
		return
	}

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

	if len(req.EdbInfoIdArr) <= 0 {
		br.Msg = "请选择指标"
		return
	}

	if req.CalculateFormula == "" {
		br.Msg = "请填写指标"
		return
	}
	calculateFormula := req.CalculateFormula
	calculateFormula = strings.Replace(calculateFormula, "（", "(", -1)
	calculateFormula = strings.Replace(calculateFormula, "）", ")", -1)
	calculateFormula = strings.Replace(calculateFormula, "，", ",", -1)
	calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
	calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
	req.CalculateFormula = calculateFormula

	//判断是否重复指标
	edbInfoMap := make(map[int]string)
	//移除研究员选择指标中的未使用的指标
	{
		//转大写的计算公式
		upperCalculateFormulaStr := strings.ToUpper(req.CalculateFormula)
		//用到的指标
		newEdbInfoIdArr := make([]data_manage.EdbInfoFromTag, 0)
		for _, tmpEdbInfo := range req.EdbInfoIdArr {
			_, ok := edbInfoMap[tmpEdbInfo.EdbInfoId]
			if ok {
				br.Msg = "选择指标失败，请勿选择重复指标！"
				return
			}
			edbInfoMap[tmpEdbInfo.EdbInfoId] = tmpEdbInfo.FromTag

			upperFromTag := strings.ToUpper(tmpEdbInfo.FromTag)
			if strings.Contains(upperCalculateFormulaStr, upperFromTag) {
				newEdbInfoIdArr = append(newEdbInfoIdArr, tmpEdbInfo)
			}
		}
		req.EdbInfoIdArr = newEdbInfoIdArr
	}

	var condition string
	var pars []interface{}
	condition += " AND edb_name=? "
	pars = append(pars, req.EdbName)

	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
	if err != nil {
		br.Msg = "判断指标名称是否存在失败"
		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
		return
	}

	if count > 0 {
		br.Msg = "指标名称已存在，请重新填写"
		br.ErrMsg = "指标名称已存在，请重新填写"
		br.IsSendEmail = false
		return
	}
	//检验公式
	var formulaStr string
	var edbInfoIdBytes []string
	for _, v := range req.EdbInfoIdArr {
		formulaStr += v.FromTag + ","
		edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag)
	}
	formulaMap := data.CheckFormula(req.CalculateFormula)
	for _, v := range formulaMap {
		if !strings.Contains(formulaStr, v) {
			br.Msg = "公式错误，请重新填写"
			return
		}
	}

	// 调用指标库去新增
	req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
		AdminId:   sysUser.AdminId,
		AdminName: sysUser.RealName,
		//EdbInfoId:        req.EdbInfoId,
		EdbName:          req.EdbName,
		Frequency:        req.Frequency,
		Unit:             req.Unit,
		ClassifyId:       req.ClassifyId,
		CalculateFormula: req.CalculateFormula,
		EdbInfoIdArr:     req.EdbInfoIdArr,
	}
	reqJson, err := json.Marshal(req2)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.AddEdbCalculateData(string(reqJson))
	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
}

// @Title 获取计算指标详情
// @Description 获取计算指标详情接口
// @Param   EdbInfoId   query   int  true       "指标id"
// @Success 200 {object} data_manage.CalculateDetailResp
// @router /edb_info/calculate/detail [get]
func (this *ChartInfoController) CalculateDetail() {
	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")
	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败，Err:" + err.Error()
		return
	}

	calculateList, err := data_manage.GetEdbInfoCalculateDetail(edbInfoId, edbInfo.Source)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败，Err:" + err.Error()
		return
	}
	resp := new(data_manage.CalculateDetailResp)
	resp.EdbInfoDetail = edbInfo
	resp.CalculateList = calculateList
	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
	br.Data = resp
}

// @Title 修改计算指标
// @Description 修改计算指标接口
// @Param	request	body data_manage.EdbInfoCalculateEditReq true "type json string"
// @Success Ret=200 返回图表id
// @router /edb_info/calculate/edit [post]
func (this *ChartInfoController) CalculateEdit() {
	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.EdbInfoCalculateEditReq
	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：" + strconv.Itoa(req.EdbInfoId)
		return
	}

	req.EdbName = strings.Trim(req.EdbName, " ")
	if req.EdbName == "" {
		br.Msg = "指标名称不能为空"
		return
	}

	if req.Frequency == "" {
		br.Msg = "频率不能为空"
		return
	}

	if req.Unit == "" {
		br.Msg = "单位不能为空"
		return
	}

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

	if len(req.EdbInfoIdArr) <= 0 {
		br.Msg = "请选择指标"
		return
	}

	if req.CalculateFormula == "" {
		br.Msg = "请填写指标"
		return
	}

	calculateFormula := req.CalculateFormula
	calculateFormula = strings.Replace(calculateFormula, "（", "(", -1)
	calculateFormula = strings.Replace(calculateFormula, "）", ")", -1)
	calculateFormula = strings.Replace(calculateFormula, "，", ",", -1)
	calculateFormula = strings.Replace(calculateFormula, "。", ".", -1)
	calculateFormula = strings.Replace(calculateFormula, "%", "*0.01", -1)
	req.CalculateFormula = calculateFormula
	fmt.Println("calculateFormula:" + calculateFormula)

	//判断是否重复指标
	edbInfoMap := make(map[int]string)
	//移除研究员选择指标中的未使用的指标
	{
		//转大写的计算公式
		upperCalculateFormulaStr := strings.ToUpper(req.CalculateFormula)
		//用到的指标
		newEdbInfoIdArr := make([]data_manage.EdbInfoFromTag, 0)
		for _, tmpEdbInfo := range req.EdbInfoIdArr {
			_, ok := edbInfoMap[tmpEdbInfo.EdbInfoId]
			if ok {
				br.Msg = "选择指标失败，请勿选择重复指标！"
				return
			}
			edbInfoMap[tmpEdbInfo.EdbInfoId] = tmpEdbInfo.FromTag

			upperFromTag := strings.ToUpper(tmpEdbInfo.FromTag)
			if strings.Contains(upperCalculateFormulaStr, upperFromTag) {
				newEdbInfoIdArr = append(newEdbInfoIdArr, tmpEdbInfo)
			}
		}
		req.EdbInfoIdArr = newEdbInfoIdArr
	}

	var condition string
	var pars []interface{}
	condition += " AND edb_name=? "
	pars = append(pars, req.EdbName)

	condition += " AND edb_info_id<>? "
	pars = append(pars, req.EdbInfoId)

	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
	if err != nil {
		br.Msg = "判断指标名称是否存在失败"
		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
		return
	}

	if count > 0 {
		br.Msg = "指标名称已存在，请重新填写"
		br.ErrMsg = "指标名称已存在，请重新填写"
		br.IsSendEmail = false
		return
	}

	//判断公式，指标是否有改动
	edbInfoDetail, err := data_manage.GetEdbInfoById(req.EdbInfoId)
	if err != nil {
		br.Msg = "修改失败"
		br.Msg = "获取指标信息失败,GetEdbInfoById Err:" + err.Error()
		return
	}
	if edbInfoDetail == nil {
		br.Msg = "修改失败"
		br.Msg = "指标信息不存在，EdbInfoId:" + strconv.Itoa(req.EdbInfoId)
		return
	}

	// 调用指标库去更新
	req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
		AdminId:          sysUser.AdminId,
		AdminName:        sysUser.RealName,
		EdbInfoId:        req.EdbInfoId,
		EdbName:          req.EdbName,
		Frequency:        req.Frequency,
		Unit:             req.Unit,
		ClassifyId:       req.ClassifyId,
		CalculateFormula: req.CalculateFormula,
		EdbInfoIdArr:     req.EdbInfoIdArr,
	}
	reqJson, err := json.Marshal(req2)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.EditEdbCalculateData(string(reqJson))
	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(req.EdbInfoId)

	// 修改关联的预测指标基础信息
	go data.ModifyPredictEdbBaseInfoBySourceEdb(edbInfoDetail)

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

// @Title 累计值转月-同比值-同差等计算新增
// @Description 累计值转月-同比值-同差等计算新增接口
// @Param	request	body data_manage.EdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /edb_info/calculate/batch/save [post]
func (this *ChartInfoController) CalculateBatchSave() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		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.EdbInfoCalculateBatchSaveReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	req.EdbName = strings.Trim(req.EdbName, " ")
	if req.EdbName == "" {
		br.Msg = "指标名称不能为空"
		return
	}

	if req.Frequency == "" {
		br.Msg = "频率不能为空"
		return
	}

	if req.Unit == "" {
		br.Msg = "单位不能为空"
		return
	}

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

	fromEdbInfoId := req.FromEdbInfoId

	var formulaInt int
	switch req.Source {
	case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS, utils.DATA_SOURCE_CALCULATE_HBZ, utils.DATA_SOURCE_CALCULATE_HCZ, utils.DATA_SOURCE_CALCULATE_TIME_SHIFT, utils.DATA_SOURCE_CALCULATE_CJJX:
		if req.Formula == "" {
			br.Msg = "请填写N值"
			return
		}
		formulaInt, _ = strconv.Atoi(req.Formula)
		if formulaInt <= 0 {
			br.Msg = "N值输入错误,请重新输入"
			return
		}
	case utils.DATA_SOURCE_CALCULATE_ZJPJ:
		//直接拼接指标
		//校验时间格式
		_, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local)
		if err != nil {
			br.Msg = "拼接日期有误,请重新输入"
			return
		}
	case utils.DATA_SOURCE_CALCULATE_NHCC: //拟合残差指标
		//指标校验
		if len(req.EdbInfoIdArr) != 2 {
			br.Msg = "选择的指标异常,请重新选择"
			return
		}
		fromEdbInfoId = req.EdbInfoIdArr[0].EdbInfoId

		//校验时间格式
		//数据格式：2022-11-01,2022-11-10
		timeList := strings.Split(req.Formula, ",")
		if len(timeList) != 2 {
			br.Msg = "选择时间有误,请重新输入"
			return
		}
		startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local)
		if err != nil {
			br.Msg = "开始日期有误,请重新输入"
			return
		}
		endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local)
		if err != nil {
			br.Msg = "结束日期有误,请重新输入"
			return
		}
		if utils.GetTimeSubDay(startDate, endDate) < 2 {
			br.Msg = "日期间隔不得少于两天"
			return
		}
	case utils.DATA_SOURCE_CALCULATE_ZSXY: // 指数修匀
		if req.Formula == "" {
			br.Msg = "请填写alpha值"
			return
		}
		alpha, e := strconv.ParseFloat(req.Formula, 64)
		if e != nil {
			br.Msg = "alpha值输入错误, 请重新输入"
			return
		}
		if alpha <= 0 || alpha >= 1 {
			br.Msg = "alpha值输入错误, 请重新输入"
			return
		}
	}

	notNeedFromEdbSourceList := []int{utils.DATA_SOURCE_CALCULATE_KSZS} // 不需要传入来源指标id的 指标类型
	if fromEdbInfoId <= 0 && !utils.InArrayByInt(notNeedFromEdbSourceList, req.Source) {
		br.Msg = "请选择指标"
		return
	}

	//加入缓存机制，避免创建同一个名称的指标 start
	redisKey := fmt.Sprint("edb_info:calculate:batch:save:", req.Source, ":", req.EdbName)
	isExist := utils.Rc.IsExist(redisKey)
	if isExist {
		br.Msg = "指标正在处理,请勿重复提交"
		return
	} else {
		//设置3分钟缓存
		utils.Rc.SetNX(redisKey, 1, time.Second*300)
		defer func() {
			utils.Rc.Delete(redisKey)
		}()
	}
	//加入缓存机制，避免创建同一个名称的指标 end

	req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
		AdminId:          sysUser.AdminId,
		AdminName:        sysUser.RealName,
		EdbInfoId:        req.EdbInfoId,
		EdbName:          req.EdbName,
		Frequency:        req.Frequency,
		Unit:             req.Unit,
		ClassifyId:       req.ClassifyId,
		Formula:          req.Formula, //N数值移动平均计算、环比值、环差值
		FromEdbInfoId:    req.FromEdbInfoId,
		CalculateFormula: req.CalculateFormula,
		Source:           req.Source,
		MoveType:         req.MoveType,
		MoveFrequency:    req.MoveFrequency,

		//CalculateFormula: edbInfo.CalculateFormula,
		EdbInfoIdArr: req.EdbInfoIdArr,
		Calendar:     req.Calendar,
	}

	// 调用指标库去更新
	reqJson, err := json.Marshal(req2)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.BatchSaveEdbCalculateData(string(reqJson))
	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
}

// @Title 累计值转月-同比值-同差等计算编辑
// @Description 累计值转月-同比值-同差等计算编辑接口
// @Param	request	body data_manage.EdbInfoCalculateBatchEditReq true "type json string"
// @Success Ret=200 返回指标id
// @router /edb_info/calculate/batch/edit [post]
func (this *ChartInfoController) CalculateBatchEdit() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		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.EdbInfoCalculateBatchEditReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

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

	if req.Frequency == "" {
		br.Msg = "频率不能为空"
		return
	}

	if req.Unit == "" {
		br.Msg = "单位不能为空"
		return
	}

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

	if req.EdbInfoId <= 0 {
		br.Msg = "请选择指标"
		return
	}

	var condition string
	var pars []interface{}
	condition += " AND edb_name=? "
	pars = append(pars, req.EdbName)

	condition += " AND edb_info_id<>? "
	pars = append(pars, req.EdbInfoId)

	count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
	if err != nil {
		br.Msg = "判断指标名称是否存在失败"
		br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
		return
	}

	if count > 0 {
		br.Msg = "指标名称已存在，请重新填写"
		br.ErrMsg = "指标名称已存在，请重新填写"
		br.IsSendEmail = false
		return
	}

	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			br.Msg = "指标已被删除，请刷新页面"
			br.ErrMsg = "指标已被删除，请刷新页面:Err:" + err.Error()
			return
		}
		br.Msg = "获取指标信息失败"
		br.ErrMsg = "获取指标信息失败:Err:" + err.Error()
		return
	}

	if req.Source <= 0 {
		req.Source = edbInfo.Source
	}

	var formulaInt int
	switch req.Source {
	case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS, utils.DATA_SOURCE_CALCULATE_HBZ, utils.DATA_SOURCE_CALCULATE_HCZ, utils.DATA_SOURCE_CALCULATE_TIME_SHIFT, utils.DATA_SOURCE_CALCULATE_CJJX:
		if req.Formula == "" {
			br.Msg = "请填写N值"
			return
		}
		formulaInt, _ = strconv.Atoi(req.Formula)
		if formulaInt <= 0 {
			br.Msg = "N值输入错误,请重新输入"
			return
		}
	case utils.DATA_SOURCE_CALCULATE_ZJPJ:
		//直接拼接指标

		//校验时间格式
		_, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local)
		if err != nil {
			br.Msg = "拼接日期有误,请重新输入"
			return
		}
	case utils.DATA_SOURCE_CALCULATE_NHCC: //拟合残差指标
		//指标校验
		if len(req.EdbInfoIdArr) != 2 {
			br.Msg = "选择的指标异常,请重新选择"
			return
		}

		//校验时间格式
		//数据格式：2022-11-01,2022-11-10
		timeList := strings.Split(req.Formula, ",")
		if len(timeList) != 2 {
			br.Msg = "选择时间有误,请重新输入"
			return
		}
		startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local)
		if err != nil {
			br.Msg = "开始日期有误,请重新输入"
			return
		}
		endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local)
		if err != nil {
			br.Msg = "结束日期有误,请重新输入"
			return
		}
		if utils.GetTimeSubDay(startDate, endDate) < 2 {
			br.Msg = "日期间隔不得少于两天"
			return
		}
	case utils.DATA_SOURCE_CALCULATE_ZSXY: // 指数修匀
		if req.Formula == "" {
			br.Msg = "请填写alpha值"
			return
		}
		alpha, e := strconv.ParseFloat(req.Formula, 64)
		if e != nil {
			br.Msg = "alpha值输入错误, 请重新输入"
			return
		}
		if alpha <= 0 || alpha >= 1 {
			br.Msg = "alpha值输入错误, 请重新输入"
			return
		}
	}

	// 构造请求
	req2 := &data_manage.EdbInfoCalculateBatchEditReqByEdbLib{
		EdbInfoId:     req.EdbInfoId,
		EdbName:       req.EdbName,
		Frequency:     req.Frequency,
		Unit:          req.Unit,
		ClassifyId:    req.ClassifyId,
		Formula:       req.Formula, //N数值移动平均计算、环比值、环差值
		FromEdbInfoId: req.FromEdbInfoId,
		Source:        req.Source,
		MoveType:      req.MoveType,
		MoveFrequency: req.MoveFrequency,
		EdbInfoIdArr:  req.EdbInfoIdArr,
		Calendar:      req.Calendar,
	}

	// 调用指标库去更新
	reqJson, err := json.Marshal(req2)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.BatchEditEdbCalculateData(string(reqJson))
	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.ModifyPredictEdbBaseInfoBySourceEdb(edbInfo)

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

// @Title 累计值转月-同比值-同差等重新计算
// @Description 累计值转月-同比值-同差等重新计算接口
// @Param	request	body data_manage.EdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /edb_info/calculate/batch/reset [post]
func (this *ChartInfoController) CalculateBatchReset() {
	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.EdbInfoCalculateBatchSaveReq
	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 = "参数错误:EdbInfoId:" + strconv.Itoa(req.EdbInfoId)
		return
	}

	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			br.Msg = "指标已被删除，请刷新页面"
			br.ErrMsg = "指标已删除，请刷新页面:Err:" + err.Error()
			return
		}
		br.Msg = "重新计算失败"
		br.ErrMsg = "获取指标信息失败:Err:" + err.Error()
		return
	}

	uniqueCode := edbInfo.UniqueCode
	sourName := edbInfo.SourceName
	edbInfoId := edbInfo.EdbInfoId
	//if source == utils.DATA_SOURCE_CALCULATE {
	//	//检验公式
	//	var formulaStr string
	//	var edbInfoIdBytes []string
	//	for _, v := range fromEdbInfoList {
	//		formulaStr += v.FromTag + ","
	//		edbInfoIdBytes = append(edbInfoIdBytes, v.FromTag)
	//	}
	//	formulaStr = strings.Trim(formulaStr, ",")
	//	formulaMap := data.CheckFormula(req.CalculateFormula)
	//	for _, v := range formulaMap {
	//		if !strings.Contains(formulaStr, v) {
	//			br.Msg = "公式错误，请重新填写"
	//			return
	//		}
	//	}
	//
	//	edbInfoList := make([]*data_manage.EdbInfo, 0)
	//
	//	for _, v := range fromEdbInfoList {
	//		edbInfo, err := data_manage.GetEdbInfoById(v.FromEdbInfoId)
	//		if err != nil {
	//			if err.Error() == utils.ErrNoRow() {
	//				br.Msg = "重新计算失败"
	//				br.Msg = "指标 " + strconv.Itoa(v.FromEdbInfoId) + " 不存在"
	//				return
	//			}
	//			br.Msg = "重新计算失败"
	//			br.Msg = "获取指标失败:Err:" + err.Error()
	//			return
	//		}
	//		edbInfoList = append(edbInfoList, edbInfo)
	//	}
	//	//清除历史数据
	//	err = data_manage.DeleteCalculateData(edbInfoId)
	//	if err != nil {
	//		br.Msg = "重新计算失败"
	//		br.Msg = "获取指标失败:Err:" + err.Error()
	//		return
	//	}
	//	err = data.Calculate(edbInfoList, int(edbInfoId), edbCode, edbInfo.CalculateFormula, edbInfoIdBytes)
	//	if err != nil {
	//		br.Msg = "重新计算失败"
	//		br.Msg = "生成计算指标失败,Calculate Err:" + err.Error()
	//		return
	//	}
	//} else if source == utils.DATA_SOURCE_CALCULATE_LJZZY {
	//	_, err = data_manage.AddCalculateLjzzy(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName)
	//} else if source == utils.DATA_SOURCE_CALCULATE_TBZ {
	//	sourName = "同比值"
	//	edbInfoId, err = data_manage.AddCalculateTbz(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName)
	//} else if source == utils.DATA_SOURCE_CALCULATE_TCZ {
	//	sourName = "同差值"
	//	edbInfoId, err = data_manage.AddCalculateTcz(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName)
	//} else if source == utils.DATA_SOURCE_CALCULATE_NSZYDPJJS {
	//	sourName = "N数值移动平均计算"
	//	formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
	//	edbInfoId, err = data_manage.AddCalculateNszydpjjs(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName, formulaInt)
	//} else if source == utils.DATA_SOURCE_CALCULATE_HBZ {
	//	sourName = "环比值"
	//	formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
	//	edbInfoId, err = data_manage.AddCalculateHbz(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName, formulaInt)
	//} else if source == utils.DATA_SOURCE_CALCULATE_HCZ {
	//	sourName = "环差值"
	//	formulaInt, _ := strconv.Atoi(edbInfo.CalculateFormula)
	//	edbInfoId, err = data_manage.AddCalculateHcz(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName, formulaInt)
	//} else if source == utils.DATA_SOURCE_CALCULATE_BP {
	//	sourName = "变频"
	//	edbInfoId, err = data_manage.AddCalculateBp(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName)
	//} else if source == utils.DATA_SOURCE_CALCULATE_TIME_SHIFT {
	//	sourName = "时间移位"
	//	if req.MoveFrequency == "" {
	//		req.MoveFrequency = edbInfo.MoveFrequency
	//	}
	//	if req.Formula == "" {
	//		req.Formula = edbInfo.CalculateFormula
	//	}
	//	edbInfoId, err = data_manage.AddCalculateTimeShift(&req, fromEdbInfo, edbCode, uniqueCode, sysUser.AdminId, sysUser.RealName)
	//} else if source == utils.DATA_SOURCE_CALCULATE_ZJPJ {
	//	sourName = "直接拼接"
	//	err = data_manage.RefreshAllCalculateZjpj(edbInfo)
	//} else if source == utils.DATA_SOURCE_CALCULATE_LJZTBPJ {
	//	sourName = "累计值同比拼接"
	//	err = data_manage.RefreshAllCalculateLjztbpj(edbInfo)
	//} else {
	//	br.Msg = "无效计算方式"
	//	br.ErrMsg = "无效计算方式,source:" + strconv.Itoa(source)
	//	return
	//}

	// 重新计算
	err, isAsync := data.EdbInfoRefreshAllFromBaseV2(edbInfoId, true)
	if err != nil {
		fmt.Println(edbInfoId, "RefreshEdbCalculateData err", time.Now())
		br.Msg = "重新计算失败"
		br.ErrMsg = "生成" + sourName + "失败,RefreshEdbCalculateData Err:" + err.Error()
		return
	}

	resp := new(data_manage.AddEdbInfoResp)
	resp.EdbInfoId = edbInfoId
	resp.UniqueCode = uniqueCode
	br.Ret = 200
	br.Success = true
	br.Msg = "重新计算成功"
	if isAsync {
		br.Msg = "该指标关联指标较多，请10分钟后刷新页面查看最新数据"
	}
	br.Data = resp
	br.IsAddLog = true
}

//累计值转月值
//func init() {
//	fmt.Println("start CalculateBatchSave")
//	req := new(data_manage.EdbInfoCalculateBatchSaveReq)
//	req.EdbInfoId = 100282
//
//	randStr := utils.GetRandDigit(4)
//	edbCode := `C` + time.Now().Format("060102") + randStr
//	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
//	uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
//	fromEdbInfo, _ := data_manage.GetEdbInfoById(req.EdbInfoId)
//	data_manage.AddCalculateLjzzy(req, fromEdbInfo, edbCode, uniqueCode, 1, "rdluck")
//	fmt.Println("end CalculateBatchSave")
//	return
//}

////同比值
//func init() {
//	fmt.Println("start AddCalculateTbz")
//	req := new(data_manage.EdbInfoCalculateBatchSaveReq)
//	req.EdbInfoId = 100092
//
//	randStr := utils.GetRandDigit(4)
//	edbCode := `C` + time.Now().Format("060102") + randStr
//	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
//	uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
//	fromEdbInfo, _ := data_manage.GetEdbInfoById(req.EdbInfoId)
//
//	data_manage.AddCalculateTbz(req, fromEdbInfo, edbCode, uniqueCode, 1, "rdluck")
//	fmt.Println("end AddCalculateTbz")
//	return
//}
//同差值

//func init() {
//	fmt.Println("start AddCalculateTbz")
//	req := new(data_manage.EdbInfoCalculateBatchSaveReq)
//	req.EdbInfoId = 100092
//
//	randStr := utils.GetRandDigit(4)
//	edbCode := `C` + time.Now().Format("060102") + randStr
//	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
//	uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
//	fromEdbInfo, _ := data_manage.GetEdbInfoById(req.EdbInfoId)
//
//	data_manage.AddCalculateTcz(req, fromEdbInfo, edbCode, uniqueCode, 1, "rdluck")
//
//	fmt.Println("end AddCalculateTbz")
//	return
//}

//N数值移动平均计算
//func init() {
//	fmt.Println("start AddCalculateTbz")
//	req := new(data_manage.EdbInfoCalculateBatchSaveReq)
//	req.FromEdbInfoId = 100081
//
//	randStr := utils.GetRandDigit(4)
//	edbCode := `C` + time.Now().Format("060102") + randStr
//	timestamp := strconv.FormatInt(time.Now().UnixNano(), 10)
//	uniqueCode := utils.MD5(utils.DATA_PREFIX + "_" + timestamp)
//	fromEdbInfo, _ := data_manage.GetEdbInfoById(req.FromEdbInfoId)
//	formulaInt := 3
//	fmt.Println("edbCode:", edbCode)
//	data_manage.AddCalculateNszydpjjs(req, fromEdbInfo, edbCode, uniqueCode, 1, "rdluck", formulaInt)
//
//	fmt.Println("end AddCalculateTbz")
//	return
//}

// ExecPythonCode
// @Title 执行python代码
// @Description 执行python代码接口
// @Param	request	body data_manage.EdbInfoCalculateSaveReq true "type json string"
// @Success Ret=200 返回图表id
// @router /edb_info/python/exec [post]
func (this *ChartInfoController) ExecPythonCode() {
	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.ExecPythonEdbReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	if req.PythonCode == "" {
		br.Msg = "python代码不能为空"
		return
	}

	resp, err := data.ExecPythonCode(req.PythonCode)
	if err != nil {
		br.Msg = "python代码执行失败，请检查代码"
		br.ErrMsg = "python代码执行失败,Err:" + err.Error()
		return
	}
	if resp.Ret != 200 {
		br.Msg = "python代码执行失败，请检查代码"
		br.ErrMsg = "python代码执行失败,Err:" + resp.ErrMsg
		return
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "运行成功"
	br.Data = resp.Data
}

// AddPythonEdb
// @Title 添加python指标
// @Description 添加python指标接口
// @Param	request	body data_manage.AddPythonEdbReq true "type json string"
// @Success 200 {object} data_manage.AddEdbInfoResp
// @router /edb_info/python/add [post]
func (this *ChartInfoController) AddPythonEdb() {
	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.PostAddPythonEdbReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		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
	}
	// 判断指标名称是否重复
	{
		var condition string
		var pars []interface{}
		condition += " AND edb_name=? "
		pars = append(pars, req.EdbName)

		condition += " AND edb_info_id<>? "
		pars = append(pars, req.EdbInfoId)

		count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
		if err != nil {
			br.Msg = "判断指标名称是否存在失败"
			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
			return
		}
		if count > 0 {
			br.Msg = "指标名称已存在，请重新填写"
			br.ErrMsg = "指标名称已存在，请重新填写"
			br.IsSendEmail = false
			return
		}
	}
	// 添加python指标
	respItem, err := data.AddPythonEdbData(string(reqJson))
	if err != nil {
		br.Msg = "添加失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}
	if respItem.Ret != 200 {
		br.Msg = "添加失败"
		br.ErrMsg = respItem.ErrMsg + ";EdbName:" + req.EdbName
		return
	}
	respData := respItem.Data.(map[string]interface{})
	tmpEdbInfoId, ok := respData["EdbInfoId"]
	if !ok {
		br.Msg = `数据转换异常`
		br.ErrMsg = fmt.Sprint("respData.EdbInfoId 数据转换异常;respData:", respData)
		return
	}
	//指标id
	edbInfoId := int64(tmpEdbInfoId.(float64))

	uniqueCode, ok := respData["UniqueCode"]
	if !ok {
		br.Msg = `数据转换异常`
		br.ErrMsg = fmt.Sprint("respData.UniqueCode 数据转换异常;respData:", respData)
		return
	}
	//添加es
	data.AddOrEditEdbInfoToEs(int(edbInfoId))

	//
	resp := data_manage.AddEdbInfoResp{
		EdbInfoId:  int(edbInfoId),
		UniqueCode: uniqueCode.(string),
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
	br.Data = resp
	br.IsAddLog = true
}

// EditPythonEdb
// @Title 修改python运算指标
// @Description 修改python运算指标接口
// @Param	request	body data_manage.AddPythonEdbReq true "type json string"
// @Success Ret=200 返回成功
// @router /edb_info/python/edit [post]
func (this *ChartInfoController) EditPythonEdb() {
	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.PostAddPythonEdbReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		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
	}

	// 判断指标名称是否重复
	{
		var condition string
		var pars []interface{}
		condition += " AND edb_name=? "
		pars = append(pars, req.EdbName)

		condition += " AND edb_info_id<>? "
		pars = append(pars, req.EdbInfoId)

		count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
		if err != nil {
			br.Msg = "判断指标名称是否存在失败"
			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
			return
		}
		if count > 0 {
			br.Msg = "指标名称已存在，请重新填写"
			br.ErrMsg = "指标名称已存在，请重新填写"
			br.IsSendEmail = false
			return
		}
	}
	//获取指标信息
	edbInfo, err := data_manage.GetEdbInfoById(req.EdbInfoId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			br.Msg = "指标已被删除，请刷新页面"
			br.ErrMsg = "指标已被删除，请刷新页面:Err:" + err.Error()
			return
		}
		br.Msg = "获取指标信息失败"
		br.ErrMsg = "获取指标信息失败:Err:" + err.Error()
		return
	}

	// 修改python运算指标
	respItem, err := data.EditPythonEdbData(string(reqJson))
	if err != nil {
		br.Msg = "保存失败"
		br.ErrMsg = "保存失败,Err:" + err.Error()
		return
	}
	if respItem.Ret != 200 {
		br.Msg = "保存失败"
		br.ErrMsg = respItem.ErrMsg + ";EdbName:" + req.EdbName
		return
	}

	//添加es
	data.AddOrEditEdbInfoToEs(req.EdbInfoId)
	resp := new(data_manage.AddEdbInfoResp)
	resp.EdbInfoId = req.EdbInfoId
	resp.UniqueCode = edbInfo.UniqueCode
	br.Ret = 200
	br.Success = true
	br.Data = resp
	br.Msg = "保存成功"
	br.IsAddLog = true
}

// GetPythonEdbCode
// @Title 获取python代码
// @Description 获取python代码接口
// @Param   EdbInfoId   query   int  true       "指标id"
// @Success 200 {object} data_manage.PythonEdbDetailResp
// @router /edb_info/python/detail [get]
func (this *ChartInfoController) GetPythonEdbCode() {
	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")
	edbInfo, err := data_manage.GetEdbInfoById(edbInfoId)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败，Err:" + err.Error()
		return
	}

	if edbInfo.Source != utils.DATA_SOURCE_PYTHON {
		br.Msg = "该指标不是Python运算指标"
		br.ErrMsg = "该指标不是Python运算指标"
		return
	}

	pythonCode, err := data_manage.GetEdbPythonCodeById(edbInfoId)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败，Err:" + err.Error()
		return
	}

	resp := data_manage.PythonEdbDetailResp{
		EdbInfoDetail: edbInfo,
		PythonCode:    pythonCode.PythonCode,
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
	br.Data = resp
}

// QueryEdbDataTable
// @Title 指标筛选接口
// @Description 指标筛选接口
// @Param   EdbInfoId   query   int  false       "指标id"
// @Success 200 {object} data_manage.EdbInfoList
// @router /edb_data/table/detail [get]
func (this *EdbInfoController) QueryEdbDataTable() {
	br := new(models.BaseResponse).Init()
	defer func() {
		this.Data["json"] = br
		this.ServeJSON()
	}()

	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
	}

	tableName := data_manage.GetEdbDataTableName(edbInfo.Source)

	columnList := []map[string]string{
		{
			"edb_code": "指标code",
		},
		{
			"data_time": "指标日期",
		},
		{
			"value": "指标对应的值",
		},
	}

	templateStr := fmt.Sprintf("sql1 = f\"\"\"SELECT data_time,`value` FROM %s WHERE edb_code = '%s' ORDER BY data_time DESC;\"\"\"\nraw = pandas_fetch_all(sql1, db)", tableName, edbInfo.EdbCode)
	info := data_manage.TableInfoResp{
		ColumnList:  columnList,
		TableName:   tableName,
		TemplateStr: url.PathEscape(templateStr),
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "获取成功"
	br.Data = info
}

// SaveAdjustEdbInfo
// @Title 保存数据调整接口
// @Description 保存数据调整接口
// @Param	request	body data_manage.AddPythonEdbReq true "type json string"
// @Success 200 {object} data_manage.AddEdbInfoResp
// @router /edb_info/adjust/save [post]
func (this *ChartInfoController) SaveAdjustEdbInfo() {
	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.SaveAdjustEdbInfoReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		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
	}
	// 判断指标名称是否重复
	{
		var condition string
		var pars []interface{}
		condition += " AND edb_name=? "
		pars = append(pars, req.EdbName)

		condition += " AND edb_info_id<>? "
		pars = append(pars, req.EdbInfoId)

		count, err := data_manage.GetEdbInfoCountByCondition(condition, pars)
		if err != nil {
			br.Msg = "判断指标名称是否存在失败"
			br.ErrMsg = "判断指标名称是否存在失败,Err:" + err.Error()
			return
		}
		if count > 0 {
			br.Msg = "指标名称已存在，请重新填写"
			br.ErrMsg = "指标名称已存在，请重新填写"
			br.IsSendEmail = false
			return
		}
	}
	// 添加数据调整指标
	respItem, err := data.SaveAdjustEdbInfo(string(reqJson))
	if err != nil {
		br.Msg = "添加失败"
		br.ErrMsg = "获取失败,Err:" + err.Error()
		return
	}
	if respItem.Ret != 200 {
		br.Msg = "添加失败"
		br.ErrMsg = respItem.ErrMsg + ";EdbName:" + req.EdbName
		return
	}
	respData := respItem.Data.(map[string]interface{})
	tmpEdbInfoId, ok := respData["EdbInfoId"]
	if !ok {
		br.Msg = `数据转换异常`
		br.ErrMsg = fmt.Sprint("respData.EdbInfoId 数据转换异常;respData:", respData)
		return
	}
	//指标id
	edbInfoId := int64(tmpEdbInfoId.(float64))

	uniqueCode, ok := respData["UniqueCode"]
	if !ok {
		br.Msg = `数据转换异常`
		br.ErrMsg = fmt.Sprint("respData.UniqueCode 数据转换异常;respData:", respData)
		return
	}
	//添加es
	data.AddOrEditEdbInfoToEs(int(edbInfoId))

	//
	resp := data_manage.AddEdbInfoResp{
		EdbInfoId:  int(edbInfoId),
		UniqueCode: uniqueCode.(string),
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
	br.Data = resp
	br.IsAddLog = true
}

// BatchCalculateBatchSave
// @Title 批量添加 累计值转月-同比值-同差等计算新增
// @Description 批量添加 累计值转月-同比值-同差等计算新增接口
// @Param	request	body data_manage.EdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /edb_info/calculate/batch/save/batch [post]
func (this *ChartInfoController) BatchCalculateBatchSave() {
	br := new(models.BaseResponse).Init()
	defer func() {
		if br.ErrMsg == "" {
			br.IsSendEmail = false
		}
		this.Data["json"] = br
		this.ServeJSON()
	}()

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

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

	resp := data_manage.BatchEdbInfoCalculateBatchSaveResp{
		Fail:    make([]data_manage.BatchEdbInfoCalculateBatchSaveFailResp, 0),
		Success: make([]data_manage.BatchEdbInfoCalculateBatchSaveSuccessResp, 0),
	}
	redisKeyList := make([]string, 0) //需要清理的缓存key列表
	defer func() {
		for _, redisKey := range redisKeyList {
			utils.Rc.Delete(redisKey)
		}
	}()

	for _, v := range reqList {
		req := v.CalculateInfo
		req.EdbName = strings.Trim(req.EdbName, " ")
		if req.EdbName == "" {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "指标名称不能为空",
			})
			continue
		}

		if req.Frequency == "" {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "频率不能为空",
			})
			continue
		}

		if req.Unit == "" {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "单位不能为空",
			})
			continue
		}

		if req.ClassifyId <= 0 {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "请选择分类",
			})
			continue
		}

		fromEdbInfoId := req.FromEdbInfoId

		var formulaInt int
		switch req.Source {
		case utils.DATA_SOURCE_CALCULATE_NSZYDPJJS, utils.DATA_SOURCE_CALCULATE_HBZ, utils.DATA_SOURCE_CALCULATE_HCZ, utils.DATA_SOURCE_CALCULATE_TIME_SHIFT, utils.DATA_SOURCE_CALCULATE_CJJX:
			if req.Formula == "" {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "请选择分类",
				})
				continue
			}
			formulaInt, _ = strconv.Atoi(req.Formula)
			if formulaInt <= 0 {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "N值输入错误,请重新输入",
				})
				continue
			}
		case utils.DATA_SOURCE_CALCULATE_ZJPJ:
			//直接拼接指标
			//校验时间格式
			_, err = time.ParseInLocation(utils.FormatDate, req.Formula, time.Local)
			if err != nil {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "拼接日期有误,请重新输入",
				})
				continue
			}
		case utils.DATA_SOURCE_CALCULATE_NHCC: //拟合残差指标
			//指标校验
			if len(req.EdbInfoIdArr) != 2 {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "选择的指标异常,请重新选择",
				})
				continue
			}
			fromEdbInfoId = req.EdbInfoIdArr[0].EdbInfoId

			//校验时间格式
			//数据格式：2022-11-01,2022-11-10
			timeList := strings.Split(req.Formula, ",")
			if len(timeList) != 2 {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "选择时间有误,请重新输入",
				})
				continue
			}
			startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local)
			if err != nil {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "开始日期有误,请重新输入",
				})
				continue
			}
			endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local)
			if err != nil {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "结束日期有误,请重新输入",
				})
				continue
			}
			if utils.GetTimeSubDay(startDate, endDate) < 2 {
				resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
					CalculateId: v.CalculateId,
					Msg:         "日期间隔不得少于两天",
				})
				continue
			}
		case utils.DATA_SOURCE_CALCULATE_ZSXY: // 指数修匀
			if req.Formula == "" {
				br.Msg = "请填写alpha值"
				return
			}
			alpha, e := strconv.ParseFloat(req.Formula, 64)
			if e != nil {
				br.Msg = "alpha值输入错误, 请重新输入"
				return
			}
			if alpha <= 0 || alpha >= 1 {
				br.Msg = "alpha值输入错误, 请重新输入"
				return
			}
		}

		if fromEdbInfoId <= 0 {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "请选择指标",
			})
			continue
		}

		//加入缓存机制，避免创建同一个名称的指标 start
		redisKey := fmt.Sprint("edb_info:calculate:batch:save:", sysUser.AdminId, ":", req.Source, ":", v.CalculateId)
		isExist := utils.Rc.IsExist(redisKey)
		if isExist {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "指标正在处理,请勿重复提交",
			})
			continue
		} else {
			//设置3分钟缓存
			utils.Rc.SetNX(redisKey, 1, time.Second*300)
			redisKeyList = append(redisKeyList, redisKey)
		}
		//加入缓存机制，避免创建同一个名称的指标 end

		req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
			AdminId:          sysUser.AdminId,
			AdminName:        sysUser.RealName,
			EdbInfoId:        req.EdbInfoId,
			EdbName:          req.EdbName,
			Frequency:        req.Frequency,
			Unit:             req.Unit,
			ClassifyId:       req.ClassifyId,
			Formula:          req.Formula, //N数值移动平均计算、环比值、环差值
			FromEdbInfoId:    req.FromEdbInfoId,
			CalculateFormula: req.CalculateFormula,
			Source:           req.Source,
			MoveType:         req.MoveType,
			MoveFrequency:    req.MoveFrequency,

			//CalculateFormula: edbInfo.CalculateFormula,
			EdbInfoIdArr: req.EdbInfoIdArr,
			Calendar:     req.Calendar,
		}

		// 调用指标库去更新
		reqJson, err := json.Marshal(req2)
		if err != nil {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "参数解析异常！",
				ErrMsg:      "参数解析失败，Err:" + err.Error(),
			})
			continue
		}
		respItem, err := data.BatchSaveEdbCalculateData(string(reqJson))
		if err != nil {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         "新增失败！",
				ErrMsg:      "新增失败，Err:" + err.Error(),
			})
			continue
		}
		if respItem.Ret != 200 {
			resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
				CalculateId: v.CalculateId,
				Msg:         respItem.Msg,
				ErrMsg:      respItem.ErrMsg,
			})
			continue
		}

		result := respItem.Data

		//添加es
		data.AddOrEditEdbInfoToEs(result.EdbInfoId)
		resp.Success = append(resp.Success, data_manage.BatchEdbInfoCalculateBatchSaveSuccessResp{
			ClassifyId:  req.ClassifyId,
			CalculateId: v.CalculateId,
			EdbInfoId:   result.EdbInfoId,
			UniqueCode:  result.UniqueCode,
		})
	}

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

// CalculateMapping
// @Title 获取计算指标与基础指标关联
// @Description 获取计算指标与基础指标关联
// @Param   EdbInfoId   query   int  true       "指标id"
// @Success 200 {object} data_manage.CalculateDetailResp
// @router /edb_info/calculate/mapping [get]
func (this *ChartInfoController) CalculateMapping() {
	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
	}
	item, e := data_manage.GetEdbInfoCalculateMappingDetail(edbInfoId)
	if e != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取失败，Err:" + e.Error()
		return
	}
	br.Ret = 200
	br.Success = true
	br.Msg = "保存成功"
	br.Data = item
}

// CalculateComputeCorrelation
// @Title 拟合残差计算相关性
// @Description 拟合残差计算相关性接口
// @Param	request	body data_manage.EdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /edb_info/calculate/compute_correlation [post]
func (this *ChartInfoController) CalculateComputeCorrelation() {
	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.EdbInfoCalculateBatchSaveReq
	err := json.Unmarshal(this.Ctx.Input.RequestBody, &req)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}

	if len(req.EdbInfoIdArr) != 2 {
		br.Msg = "选择的指标异常,请重新选择"
		return
	}
	fromEdbInfoId := req.EdbInfoIdArr[0].EdbInfoId

	//校验时间格式
	//数据格式：2022-11-01,2022-11-10
	timeList := strings.Split(req.Formula, ",")
	if len(timeList) != 2 {
		br.Msg = "选择时间有误,请重新输入"
		return
	}
	startDate, err := time.ParseInLocation(utils.FormatDate, timeList[0], time.Local)
	if err != nil {
		br.Msg = "开始日期有误,请重新输入"
		return
	}
	endDate, err := time.ParseInLocation(utils.FormatDate, timeList[1], time.Local)
	if err != nil {
		br.Msg = "结束日期有误,请重新输入"
		return
	}
	if utils.GetTimeSubDay(startDate, endDate) < 2 {
		br.Msg = "日期间隔不得少于两天"
		return
	}

	if fromEdbInfoId <= 0 {
		br.Msg = "请选择指标"
		return
	}

	req2 := &data_manage.EdbInfoCalculateBatchSaveReqByEdbLib{
		AdminId:          sysUser.AdminId,
		AdminName:        sysUser.RealName,
		EdbInfoId:        req.EdbInfoId,
		EdbName:          req.EdbName,
		Frequency:        req.Frequency,
		Unit:             req.Unit,
		ClassifyId:       req.ClassifyId,
		Formula:          req.Formula, //N数值移动平均计算、环比值、环差值
		FromEdbInfoId:    req.FromEdbInfoId,
		CalculateFormula: req.CalculateFormula,
		Source:           req.Source,
		MoveType:         req.MoveType,
		MoveFrequency:    req.MoveFrequency,

		//CalculateFormula: edbInfo.CalculateFormula,
		EdbInfoIdArr: req.EdbInfoIdArr,
		Calendar:     req.Calendar,
	}

	// 调用指标库去更新
	reqJson, err := json.Marshal(req2)
	if err != nil {
		br.Msg = "参数解析异常！"
		br.ErrMsg = "参数解析失败，Err:" + err.Error()
		return
	}
	respItem, err := data.CalculateComputeCorrelation(string(reqJson))
	if err != nil {
		br.Msg = "新增失败"
		br.ErrMsg = "新增失败,Err:" + err.Error()
		return
	}

	if respItem.Ret == 200 {
		br.Data = respItem.Data
	} else {
		br.Data = ``
	}

	br.Ret = 200
	br.Success = true
	br.Msg = "计算成功"
	br.IsAddLog = true
}
