package data_manage

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

// CalculateSave
// @Title 生成预测指标运算
// @Description 生成预测指标运算接口
// @Param	request	body data_manage.PredictEdbInfoCalculateSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /predict_edb_info/calculate/save [post]
func (this *PredictEdbInfoController) 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.PredictEdbInfoCalculateSaveReq
	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

	// 基础的一些数据校验
	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
	}

	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		br.Msg = "参数解析异常!"
		br.ErrMsg = "参数解析失败,Err:" + err.Error()
		return
	}
	respItem, err := data.SavePredictEdbData(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
}

// CalculateBatchSave
// @Title 生成预测指标运算(同比、同差)
// @Description 生成预测指标运算(同比、同差)接口
// @Param	request	body data_manage.PredictEdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /predict_edb_info/calculate/batch/save [post]
func (this *PredictEdbInfoController) CalculateBatchSave() {
	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.PredictEdbInfoCalculateBatchSaveReq
	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

	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
	}

	// 添加计算指标
	reqJson, err := json.Marshal(req)
	if err != nil {
		br.Msg = "参数解析异常!"
		br.ErrMsg = "参数解析失败,Err:" + err.Error()
		return
	}
	respItem, err := data.BatchSavePredictEdbData(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
}

// BatchCalculateBatchSave
// @Title 批量添加 生成预测指标运算(同比、同差)
// @Description 批量添加 生成预测指标运算(同比、同差)接口
// @Param	request	body data_manage.PredictEdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /predict_edb_info/calculate/batch/save/batch [post]
func (this *PredictEdbInfoController) BatchCalculateBatchSave() {
	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 reqList []data_manage.BatchPredictEdbInfoCalculateBatchSaveReq
	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
		//
		//if fromEdbInfoId <= 0 {
		//	resp.Fail = append(resp.Fail, data_manage.BatchEdbInfoCalculateBatchSaveFailResp{
		//		CalculateId: v.CalculateId,
		//		Msg:         "请选择指标",
		//	})
		//	continue
		//}

		req.AdminId = sysUser.AdminId
		req.AdminName = sysUser.RealName

		//加入缓存机制,避免创建同一个名称的指标 start
		redisKey := fmt.Sprint("predict_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

		reqJson, err := json.Marshal(req)
		if err != nil {
			br.Msg = "参数解析异常!"
			br.ErrMsg = "参数解析失败,Err:" + err.Error()
			return
		}
		respItem, err := data.BatchSavePredictEdbData(string(reqJson), this.Lang)
		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{
			CalculateId: v.CalculateId,
			EdbInfoId:   result.EdbInfoId,
			UniqueCode:  result.UniqueCode,
			ClassifyId:  req.ClassifyId,
		})
	}

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

// CalculateComputeCorrelation
// @Title 拟合残差计算相关性(预测指标)
// @Description 拟合残差计算相关性(预测指标)接口
// @Param	request	body data_manage.PredictEdbInfoCalculateBatchSaveReq true "type json string"
// @Success Ret=200 返回指标id
// @router /predict_edb_info/calculate/compute_correlation [post]
func (this *PredictEdbInfoController) 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.PredictEdbInfoCalculateBatchSaveReq
	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
	}
	respItem, err := data.PredictCalculateComputeCorrelation(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
	br.IsAddLog = true
}