package data_manage

import (
	"encoding/json"
	"eta/eta_api/controllers/data_manage/correlation"
	"eta/eta_api/controllers/data_manage/cross_variety"
	"eta/eta_api/controllers/data_manage/future_good"
	"eta/eta_api/controllers/data_manage/line_equation"
	"eta/eta_api/controllers/data_manage/line_feature"
	"eta/eta_api/controllers/data_manage/range_analysis"
	"eta/eta_api/models"
	aiPredictModel "eta/eta_api/models/ai_predict_model"
	"eta/eta_api/models/data_manage"
	"eta/eta_api/models/system"
	"eta/eta_api/services"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/services/data"
	"eta/eta_api/services/data/excel"
	"eta/eta_api/utils"
	"fmt"
	"strings"
	"time"
)

// CommonChartInfoDetailFromUniqueCode
// @Title 根据编码获取图表详情
// @Description 根据编码获取图表详情接口
// @Param   UniqueCode   query   int  true       "图表唯一编码,如果是管理后台访问,传固定字符串:7c69b590249049942070ae9dcd5bf6dc"
// @Param   IsCache   query   bool  true       "是否走缓存,默认false"
// @Success 200 {object} data_manage.ChartInfoDetailFromUniqueCodeResp
// @router /chart_info/common/detail/from_unique_code [get]
func (this *ChartInfoController) CommonChartInfoDetailFromUniqueCode() {
	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
	}
	uniqueCode := this.GetString("UniqueCode")
	if uniqueCode == "" {
		br.Msg = "参数错误"
		br.ErrMsg = "参数错误,uniqueCode is empty"
		return
	}

	//是否走缓存
	isCache, _ := this.GetBool("IsCache")

	status := true
	chartInfo, err := data_manage.GetChartInfoViewByUniqueCode(uniqueCode)
	if err != nil {
		if utils.IsErrNoRow(err) {
			status = false
		} else {
			br.Msg = "获取失败"
			br.ErrMsg = "获取图表信息失败,Err:" + err.Error()
			return
		}
	}

	if chartInfo == nil {
		status = false
	}

	if !status {
		resp := new(data_manage.ChartInfoDetailFromUniqueCodeResp)
		endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
		resp.EdbInfoList = endInfoList
		resp.ChartInfo = chartInfo
		resp.Status = false

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

	switch chartInfo.Source {
	case utils.CHART_SOURCE_DEFAULT:
		resp, isOk, msg, errMsg := GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_FUTURE_GOOD:
		resp, isOk, msg, errMsg := future_good.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_FUTURE_GOOD_PROFIT:
		resp, isOk, msg, errMsg := future_good.GetFutureGoodProfitChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_CORRELATION, utils.CHART_SOURCE_ROLLING_CORRELATION:
		resp, isOk, msg, errMsg := correlation.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_LINE_EQUATION:
		resp, isOk, msg, errMsg := line_equation.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_LINE_FEATURE_STANDARD_DEVIATION, utils.CHART_SOURCE_LINE_FEATURE_PERCENTILE, utils.CHART_SOURCE_LINE_FEATURE_FREQUENCY:
		resp, isOk, msg, errMsg := line_feature.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_CROSS_HEDGING:
		resp, isOk, msg, errMsg := cross_variety.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_BALANCE_EXCEL:
		resp, isOk, msg, errMsg := getBalanceChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_RANGE_ANALYSIS:
		resp, isOk, msg, errMsg := range_analysis.GetChartInfoDetailFromUniqueCode(chartInfo, isCache, sysUser)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	case utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY, utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY:
		resp, isOk, msg, errMsg := GetAiPredictChartInfoDetailFromUniqueCode(chartInfo, isCache)
		if !isOk {
			if strings.Contains(errMsg, utils.ErrNoRow()) {
				endInfoList := make([]*data_manage.ChartEdbInfoMapping, 0)
				resp.EdbInfoList = endInfoList
				resp.ChartInfo = chartInfo
				resp.Status = false

				br.Data = resp
				br.Ret = 200
				br.Success = true
				br.Msg = "获取成功"
				return
			}
			br.Msg = msg
			br.ErrMsg = errMsg
			return
		}
		br.Ret = 200
		br.Success = true
		br.Msg = "获取成功"
		br.Data = resp
	default:
		br.Msg = "错误的图表"
		br.ErrMsg = "错误的图表"
		return
	}
}

func getBalanceChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCache bool, sysUser *system.Admin) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)
	defer func() {
		if !isOk {
			if errMsg != "" {
				uniqueCode := ""
				if chartInfo != nil {
					uniqueCode = chartInfo.UniqueCode
				}
				tmpTip := fmt.Sprintf("查询图表详情失败,getBalanceChartInfoDetailFromUniqueCode UniqueCode:%s,err:%s", uniqueCode, errMsg)
				utils.FileLog.Info(tmpTip)
				go alarm_msg.SendAlarmMsg(tmpTip, 3)
			}
		}
	}()
	resp, isOk, msg, errMsg = data.CheckBalanceChartCacheAndPermission(chartInfo, isCache, sysUser)
	if isOk {
		return
	}
	msg = `获取失败`
	// 相关联指标
	mappingListTmp, dataListMap, err, errMsg := excel.GetBalanceExcelChartSingle(chartInfo.ChartInfoId, 0, "")
	if err != nil {
		errMsg = "获取失败"
		err = fmt.Errorf(" 获取图表,指标信息失败 Err:%s", err.Error())
		return
	}
	var chartInfoResp *data_manage.ChartInfoDetailResp
	chartInfoResp, err, errMsg = data.GetBalanceExcelChartDetail(chartInfo, mappingListTmp, sysUser, dataListMap)
	if err != nil {
		msg = "查询图表详情失败"
		errMsg = "查询图表详情失败,Err:" + err.Error()
		return
	}
	resp = &data_manage.ChartInfoDetailFromUniqueCodeResp{
		ChartInfo:            chartInfoResp.ChartInfo,
		Status:               true,
		EdbInfoList:          chartInfoResp.EdbInfoList,
		XEdbIdValue:          chartInfoResp.XEdbIdValue,
		YDataList:            chartInfoResp.YDataList,
		XDataList:            chartInfoResp.XDataList,
		BarChartInfo:         chartInfoResp.BarChartInfo,
		CorrelationChartInfo: chartInfoResp.CorrelationChartInfo,
		DataResp:             chartInfoResp.DataResp,
	}
	// 将数据加入缓存
	if utils.Re == nil {
		cacheData, _ := json.Marshal(resp)
		key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
		utils.Rc.Put(key, cacheData, 2*time.Hour)
	}
	isOk = true

	return
}

// GeneralChartToken
// @Title 根据图表唯一code生成token
// @Description 根据编码获取图表详情接口
// @Param   UniqueCode   query   string  true       "图表/表格唯一编码"
// @Param   Source   query   string  true       "来源,枚举值:chart、table"
// @Success 200 {object} data_manage.ChartInfoDetailFromUniqueCodeResp
// @router /chart_info/common/general_token [get]
func (this *ChartInfoController) GeneralChartToken() {
	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
	}
	uniqueCode := this.GetString("UniqueCode")
	if uniqueCode == "" {
		br.Msg = "参数错误"
		br.ErrMsg = "参数错误,uniqueCode is empty"
		return
	}
	source := this.GetString("Source", "chart")

	businessConf, err := models.GetBusinessConfByKey(models.BusinessConfIsOpenChartExpired)
	if err != nil {
		br.Msg = "获取失败"
		br.ErrMsg = "获取配置失败,Err:" + err.Error()
		return
	}

	var token string
	if businessConf.ConfVal == `true` {
		// 缓存key
		sourceType := source
		if source == `table` {
			sourceType = source
		}
		token, err = services.GeneralChartToken(sourceType, uniqueCode)
		if err != nil {
			br.Msg = "获取失败"
			br.ErrMsg = "获取失败"
			return
		}
	}

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

// GetAiPredictChartInfoDetailFromUniqueCode 根据编码获取AI预测模型图表详情
func GetAiPredictChartInfoDetailFromUniqueCode(chartInfo *data_manage.ChartInfoView, isCache bool) (resp *data_manage.ChartInfoDetailFromUniqueCodeResp, isOk bool, msg, errMsg string) {
	var err error
	msg = "获取成功"
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("UniqueCode获取图表详情失败, %v", err)
			msg = "获取失败"
			errMsg = fmt.Sprintf(tips)
			utils.FileLog.Info(tips)
		}
	}()
	if chartInfo == nil {
		err = fmt.Errorf("图表信息不存在")
		return
	}
	if chartInfo.Source != utils.CHART_SOURCE_AI_PREDICT_MODEL_DAILY && chartInfo.Source != utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY {
		err = fmt.Errorf("图表来源有误, Source: %d", chartInfo.Source)
		return
	}
	resp = new(data_manage.ChartInfoDetailFromUniqueCodeResp)

	// 获取图表标的
	edbMappings, e := data_manage.GetChartEdbMappingsByChartInfoId(chartInfo.ChartInfoId)
	if e != nil {
		err = fmt.Errorf("获取图表指标关联失败, %v", e)
		return
	}
	if len(edbMappings) == 0 {
		err = fmt.Errorf("图表指标关联不存在, %v", e)
		return
	}
	indexId := edbMappings[0].EdbInfoId
	if indexId <= 0 {
		err = fmt.Errorf("图表标的有误")
		return
	}
	indexOb := new(aiPredictModel.AiPredictModelIndex)
	indexItem, e := indexOb.GetItemById(indexId)
	if e != nil {
		err = fmt.Errorf("获取图表标的失败, %v", e)
		return
	}
	if indexItem != nil && indexItem.AiPredictModelIndexId <= 0 {
		err = fmt.Errorf("图表标的不存在, IndexId: %d", indexId)
		return
	}

	// 获取标的数据
	indexData := make([]*aiPredictModel.AiPredictModelData, 0)
	dataSource := aiPredictModel.ModelDataSourceDaily
	if chartInfo.Source == utils.CHART_SOURCE_AI_PREDICT_MODEL_MONTHLY {
		dataSource = aiPredictModel.ModelDataSourceMonthly
	}
	dataOb := new(aiPredictModel.AiPredictModelData)
	dataCond := fmt.Sprintf(` AND %s = ?`, dataOb.Cols().IndexCode)
	dataPars := make([]interface{}, 0)
	dataPars = append(dataPars, indexItem.IndexCode)
	list, e := dataOb.GetItemsByCondition(dataCond, dataPars, []string{}, fmt.Sprintf("%s DESC", dataOb.Cols().DataTime))
	if e != nil {
		err = fmt.Errorf("获取标的数据失败, %v", e)
		return
	}
	for _, v := range list {
		if v.Source == dataSource {
			indexData = append(indexData, v)
			continue
		}
	}

	//判断是否存在缓存,如果存在缓存,那么直接从缓存中获取
	key := data.GetChartInfoDataKey(chartInfo.ChartInfoId)
	if utils.Re == nil && isCache {
		if utils.Re == nil && utils.Rc.IsExist(key) {
			if chartData, e := utils.Rc.RedisBytes(key); e == nil {
				e = json.Unmarshal(chartData, &resp)
				if e != nil || resp == nil {
					return
				}
				isOk = true
				return
			}
		}
	}

	// 图表详情
	chartDetail, e := services.GetAiPredictChartDetailByData(indexItem, indexData, dataSource)
	if e != nil {
		err = fmt.Errorf("获取图表详情失败, %v", e)
		return
	}
	resp.ChartInfo = chartDetail.ChartInfo
	resp.EdbInfoList = chartDetail.EdbInfoList
	resp.XEdbIdValue = chartDetail.XEdbIdValue
	resp.YDataList = chartDetail.YDataList
	resp.XDataList = chartDetail.XDataList
	resp.BarChartInfo = chartDetail.BarChartInfo
	resp.CorrelationChartInfo = chartDetail.CorrelationChartInfo
	resp.DataResp = chartDetail.DataResp
	resp.Status = true

	if utils.Re == nil {
		jsonData, _ := json.Marshal(resp)
		_ = utils.Rc.Put(key, jsonData, 10*time.Minute)
	}
	isOk = true
	return
}