package services

import (
	"encoding/json"
	"errors"
	"eta/eta_api/models/data_manage"
	excelModel "eta/eta_api/models/data_manage/excel"
	"eta/eta_api/models/data_manage/excel/request"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/services/sandbox"
	"eta/eta_api/utils"
	"fmt"
	"time"
)

// 全局的指标替换
func DealReplaceEdbCache() {
	var err error
	for {
		utils.Rc.Brpop(utils.CACHE_KEY_REPLACE_EDB, func(b []byte) {
			defer func() {
				if err != nil {
					utils.FileLog.Info("DealReplaceEdbCache err:" + err.Error())
					go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg："+err.Error(), 3)
				}
			}()
			record := new(data_manage.ReplaceEdbInfoItem)
			if err = json.Unmarshal(b, &record); err != nil {
				fmt.Println("json unmarshal wrong!")
				return
			}
			oldEdbInfo := record.OldEdbInfo
			newEdbInfo := record.NewEdbInfo
			deleteCache := true
			setNxKey := fmt.Sprintf("EDB_INFO_REPLACE:%d-%d", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)
			defer func() {
				if deleteCache {
					utils.Rc.Delete(setNxKey)
				}
			}()
			if !utils.Rc.SetNX(setNxKey, 1, 30*time.Minute) {
				deleteCache = false
				err = fmt.Errorf("替换表格中的指标失败旧指标：%d为新指标%d:正在处理中", oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)
				return
			}

			// 替换相关性图表配置
			_, err = data_manage.ReplaceMultipleGraphConfigChartEdb(oldEdbInfo, newEdbInfo)
			if err != nil {
				err = fmt.Errorf("替换相关性图表配置失败,errmsg:%s", err.Error())
				return
			}
			// 替换拟合方程指标
			_, err = data_manage.ReplaceEdbInfoInLineEquationMultipleGraphConfig(oldEdbInfo, newEdbInfo)
			if err != nil {
				err = fmt.Errorf("替换拟合方程指标失败,errmsg:%s", err.Error())
				return
			}

			// 替换表格中的指标
			err = ReplaceEdbInExcel(oldEdbInfo, newEdbInfo)
			if err != nil {
				err = fmt.Errorf("替换表格中的指标失败,errmsg:%s", err.Error())
				return
			}

			//替换逻辑图中的指标
			err = sandbox.ReplaceEdbInSandbox(oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId)
			if err != nil {
				err = fmt.Errorf("替换逻辑图中的指标失败,errmsg:%s", err.Error())
				return
			}
		})
	}
}

// ReplaceEdbInExcel 替换表格中的指标
func ReplaceEdbInExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo) (err error) {
	defer func() {
		if err != nil {
			go alarm_msg.SendAlarmMsg("替换表格中的指标失败提醒,errmsg："+err.Error(), 3)
		}
	}()
	//查询和指标相关的时间序列表格和混合表格
	mappingList, err := excelModel.GetExcelEdbMappingByEdbInfoIdAndSource(oldEdbInfo.EdbInfoId, []int{utils.TIME_TABLE, utils.MIXED_TABLE})
	if err != nil {
		err = fmt.Errorf("查询和指标相关的表格失败，错误：%s", err.Error())
		return
	}
	updateList := make([]*excelModel.ExcelInfo, 0)
	// 循环列表，根据表格类型单独处理
	for _, excelMapping := range mappingList {
		//查询和指标相关的混合表格
		excelInfo, tmpErr := excelModel.GetExcelInfoById(excelMapping.ExcelInfoId)
		if tmpErr != nil {
			err = fmt.Errorf("查询和指标相关的混合表格失败，错误：%s", tmpErr.Error())
			return
		}
		// 清除缓存
		key := utils.HZ_CHART_LIB_EXCEL_TABLE_DETAIL + ":" + excelInfo.UniqueCode
		if utils.Re == nil {
			_ = utils.Rc.Delete(key)
		}
		// 根据表格类型，调用不同的处理函数
		switch excelMapping.Source {
		case utils.TIME_TABLE: // 时间序列表格
			// 替换余额表格中的指标
			newExcelInfo, e := replaceEdbInTimeExcel(oldEdbInfo, newEdbInfo, excelInfo)
			if e != nil {
				err = fmt.Errorf("替换余额表格中的指标失败，错误：%s", e.Error())
				return
			}
			updateList = append(updateList, newExcelInfo)
		case utils.MIXED_TABLE, utils.BALANCE_TABLE:
			// 替换余额表格中的指标
			newExcelInfo, e := replaceEdbInBalanceExcel(oldEdbInfo, newEdbInfo, excelInfo)
			if e != nil {
				err = fmt.Errorf("替换余额表格中的指标失败，错误：%s", e.Error())
				return
			}
			updateList = append(updateList, newExcelInfo)
		default:
			// 其他表格类型的处理逻辑
		}
	}

	err = excelModel.ReplaceEdbInExcel(oldEdbInfo.EdbInfoId, newEdbInfo.EdbInfoId, updateList)
	if err != nil {
		err = fmt.Errorf("替换表格中的指标失败，错误：%s", err.Error())
		return
	}

	//todo 是否需要刷新表格中的指标数据
	return
}

func replaceEdbInBalanceExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, excelInfo *excelModel.ExcelInfo) (newExcelInfo *excelModel.ExcelInfo, err error) {
	newExcelInfo = excelInfo
	var mixedTableReq request.MixedTableReq
	err = json.Unmarshal([]byte(excelInfo.Content), &mixedTableReq)
	if err != nil {
		err = fmt.Errorf("表格json转结构体失败，Err:" + err.Error())
		return
	}
	// 处理data
	configList := mixedTableReq.Data
	for ck, rowList := range configList {
		for rk, cell := range rowList {
			switch cell.DataType {
			case request.EdbDT: // 指标信息
				if cell.EdbInfoId == oldEdbInfo.EdbInfoId {
					//更换成新指标ID
					configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId
				}
			case request.InsertDataDT, request.PopInsertDataDT: // 插值、弹框插值
				if cell.EdbInfoId == oldEdbInfo.EdbInfoId {
					//更换成新指标ID
					configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId
				}
			case request.InsertEdbCalculateDataDT: // 插入指标计算公式生成的值
				var config request.CalculateConf
				err = json.Unmarshal([]byte(cell.Value), &config)
				if err != nil {
					return
				}
				if cell.EdbInfoId == oldEdbInfo.EdbInfoId {
					//更换成新指标ID
					configList[ck][rk].EdbInfoId = newEdbInfo.EdbInfoId
				}
				if config.EdbInfoId == oldEdbInfo.EdbInfoId {
					config.EdbInfoId = newEdbInfo.EdbInfoId
					var configStr []byte
					configStr, err = json.Marshal(config)
					if err != nil {
						return
					}
					configList[ck][rk].Value = string(configStr)
				}

			case request.DateDT: // 日期类型
				// 指标日期类型的单元格需要额外将指标id取出来
				if cell.DataTimeType == request.EdbDateDT {
					var config request.EdbDateConf
					err = json.Unmarshal([]byte(cell.Value), &config)
					if err != nil {
						return
					}
					if config.EdbInfoId == oldEdbInfo.EdbInfoId {
						config.EdbInfoId = newEdbInfo.EdbInfoId
						var configStr []byte
						configStr, err = json.Marshal(config)
						if err != nil {
							return
						}
						configList[ck][rk].Value = string(configStr)
					}
				}
			}
		}
	}

	mixedTableReq.Data = configList
	var newContentByte []byte
	newContentByte, err = json.Marshal(mixedTableReq)
	if err != nil {
		return
	}
	// 生成的新内容替换原先的旧内容
	excelInfo.Content = string(newContentByte)
	newExcelInfo = excelInfo
	return
}

func replaceEdbInTimeExcel(oldEdbInfo, newEdbInfo *data_manage.EdbInfo, excelInfo *excelModel.ExcelInfo) (newExcelInfo *excelModel.ExcelInfo, err error) {
	newExcelInfo = excelInfo

	var tableDataConfig request.TimeTableDataConfig
	err = json.Unmarshal([]byte(excelInfo.Content), &tableDataConfig)
	if err != nil {
		err = errors.New("表格json转结构体失败，Err:" + err.Error())
		return
	}
	if len(tableDataConfig.EdbInfoIdList) <= 0 {
		return
	}
	// 实际期数没有的情况下，直接返回吧
	if tableDataConfig.Num <= 0 {
		return
	}

	// 先处理edbInfoList
	for k, id := range tableDataConfig.EdbInfoIdList {
		if id == oldEdbInfo.EdbInfoId {
			tableDataConfig.EdbInfoIdList[k] = newEdbInfo.EdbInfoId
		}
	}

	// 先处理tableEdbInfoList
	for k, tableEdbInfo := range tableDataConfig.TableEdbInfoList {
		if tableEdbInfo.EdbInfoId == oldEdbInfo.EdbInfoId {
			tableDataConfig.TableEdbInfoList[k].EdbInfoId = newEdbInfo.EdbInfoId
		}
	}

	var newContentByte []byte
	newContentByte, err = json.Marshal(tableDataConfig)
	if err != nil {
		return
	}
	// 生成的新内容替换原先的旧内容
	excelInfo.Content = string(newContentByte)
	newExcelInfo = excelInfo
	return
}
