package data

import (
	"errors"
	"eta/eta_api/models"
	"eta/eta_api/models/data_manage"
	"eta/eta_api/models/system"
	"eta/eta_api/services/alarm_msg"
	"eta/eta_api/utils"
	"fmt"
	"github.com/shopspring/decimal"
	"github.com/tealeg/xlsx"
	"strconv"
	"strings"
	"time"
)

func GetManualSysUser(keyWord string) (list []*data_manage.ManualSysUser, err error) {
	//departmentId := 1
	list = make([]*data_manage.ManualSysUser, 0)
	departmentItems, err := system.GetSysDepartmentAll()
	if err != nil {
		return list, err
	}
	for _, dv := range departmentItems {
		department := new(data_manage.ManualSysUser)
		department.ItemId = dv.DepartmentId * 10000
		department.ItemName = dv.DepartmentName

		fmt.Println(department.ItemId, department.ItemName)
		//GetSysuserList

		var condition string
		var pars []interface{}

		if keyWord != "" {
			condition += ` AND (real_name LIKE ? OR admin_name LIKE ? OR mobile LIKE ? )  `
			pars = utils.GetLikeKeywordPars(pars, keyWord, 3)
		}
		sysUsers, err := system.GetSysUserItems(condition, pars)
		if err != nil {
			return list, err
		}

		groups, err := system.GetSysGroupByDepartmentId(dv.DepartmentId)
		if err != nil {
			return list, err
		}
		dg := make([]*data_manage.ManualSysUser, 0)
		for _, v := range groups {
			group := new(data_manage.ManualSysUser)
			group.ItemId = v.DepartmentId * 100000
			group.ItemName = v.GroupName

			for _, sv := range sysUsers {
				user := new(data_manage.ManualSysUser)
				user.ItemId = sv.AdminId
				user.ItemName = sv.RealName
				if sv.GroupId == v.GroupId {
					group.Children = append(group.Children, user)
				}
			}
			if len(group.Children) > 0 {
				dg = append(dg, group)
			}
		}

		if len(groups) <= 0 {
			group := new(data_manage.ManualSysUser)
			group.ItemId = dv.DepartmentId * 100000
			group.ItemName = "无分组"

			for _, sv := range sysUsers {
				user := new(data_manage.ManualSysUser)
				user.ItemId = sv.AdminId
				user.ItemName = sv.RealName
				if sv.DepartmentId == dv.DepartmentId && sv.GroupId == 0 {
					group.Children = append(group.Children, user)
				}
			}
			if len(group.Children) > 0 {
				dg = append(dg, group)
			}
		}

		if len(dg) > 0 {
			department.Children = dg
			list = append(list, department)
		}
	}
	return
}

// GetManualEdbClassifyListByAdminId
// @Description: 根据账户类型获取手工指标分类ID集合
// @author: Roc
// @datetime 2024-07-16 13:18:39
// @param adminId int64
// @return classifyIdList []int
// @return err error
func GetManualEdbClassifyListByAdminId(adminId int64) (classifyIdList []int, err error) {
	var list []*models.EdbdataClassify
	if adminId <= 0 {
		list, err = models.GetAllChildManualEdbClassify()
	} else {
		userClassifyList, _ := models.GetManualUserClassify(int(adminId))
		var userClassifyIdList []int
		for _, v := range userClassifyList {
			userClassifyIdList = append(userClassifyIdList, v.ClassifyId)
		}
		list, err = models.GetChildManualEdbClassifyByIdList(userClassifyIdList)
	}
	if err != nil {
		return
	}
	for _, classify := range list {
		classifyIdList = append(classifyIdList, classify.ClassifyId)
	}

	return
}

type ManualIndexSource2EdbReq struct {
	EdbCode       string
	EdbName       string
	Frequency     string
	Unit          string
	ClassifyId    int
	AdminId       int
	AdminRealName string
}

// ManualIndexSource2Edb
// @Description: 新增手工数据源到指标库
// @author: Roc
// @datetime 2024-07-26 13:23:19
// @param req ManualIndexSource2EdbReq
// @param lang string
// @return edb *data_manage.EdbInfo
// @return err error
// @return errMsg string
// @return skip bool
func ManualIndexSource2Edb(req ManualIndexSource2EdbReq, lang string) (edb *data_manage.EdbInfo, err error, errMsg string, skip bool) {
	if req.EdbCode == "" {
		err = fmt.Errorf("指标ID为空")
		return
	}
	defer func() {
		if err != nil {
			tips := fmt.Sprintf("ManualIndexSource2Edb新增失败, Err: %s", err.Error())
			fmt.Println(tips)
			utils.FileLog.Info(tips)
		}
	}()
	source := utils.DATA_SOURCE_MANUAL

	// 是否已有指标数据
	dataList, e := data_manage.GetEdbDataAllByEdbCode(req.EdbCode, source, utils.DATA_SUB_SOURCE_EDB, utils.EDB_DATA_LIMIT)
	if e != nil {
		err = fmt.Errorf("获取指标数据失败, Err: %s", e.Error())
		return
	}

	// 新增指标数据
	if len(dataList) == 0 {
		res, e := AddEdbData(source, req.EdbCode, req.Frequency)
		if e != nil {
			err = fmt.Errorf("index_lib: 新增指标数据失败, Err: %s", e.Error())
			return
		}
		if res == nil {
			err = fmt.Errorf("index_lib: 新增指标数据失败, res nil")
			return
		}
		if res.Ret != 200 {
			err = fmt.Errorf("index_lib: 新增指标数据失败, Ret: %d", res.Ret)
			return
		}
	}

	// 是否新增过指标
	exist, e := data_manage.GetEdbInfoByEdbCode(source, req.EdbCode)
	if e != nil && e.Error() != utils.ErrNoRow() {
		err = fmt.Errorf("获取指标是否存在失败, err: %s", e.Error())
		return
	}
	if exist != nil {
		skip = true
		return
	}

	// 开始结束时间
	var startDate, endDate string
	minMax, e := data_manage.GetEdbInfoMaxAndMinInfo(source, utils.DATA_SUB_SOURCE_EDB, req.EdbCode)
	if e != nil && e.Error() != utils.ErrNoRow() {
		err = fmt.Errorf("MinMax: 获取指标极值失败, err: %s", e.Error())
		return
	}
	if minMax != nil {
		startDate = minMax.MinDate
		endDate = minMax.MaxDate
	}

	// 新增指标库
	edbInfo, e, msg, _ := EdbInfoAdd(source, utils.DATA_SUB_SOURCE_EDB, req.ClassifyId, req.EdbCode, req.EdbName, req.Frequency, req.Unit, startDate, endDate, req.AdminId, req.AdminRealName, lang)
	if e != nil {
		errMsg = msg
		err = fmt.Errorf("EdbInfo: 新增指标失败, err: %s", e.Error())
		return
	}
	edb = edbInfo

	// 新增es
	go AddOrEditEdbInfoToEs(edbInfo.EdbInfoId)

	return
}

// ImportManualData
// @Description: 数据导入
// @author: Roc
// @datetime 2024-08-01 11:27:21
// @param path string
// @param sysUser *system.Admin
// @return successCount int
// @return failCount int
// @return err error
// @return errMsg string
func ImportManualData(path string, sysUser *system.Admin) (successCount, failCount int, indexCount int, err error, errMsg string) {
	// 错误信息
	errMsgList := make([]string, 0)
	// 操作记录
	recordMap := make(map[string]string)
	defer func() {
		recordList := make([]*models.EdbinfoOpRecord, 0)
		for tradeCode, remark := range recordMap {
			recordList = append(recordList, &models.EdbinfoOpRecord{
				TradeCode:  tradeCode,
				Remark:     remark,
				UserId:     sysUser.AdminId,
				UserName:   sysUser.RealName,
				CreateTime: time.Now(),
			})

			// 修改最大最小值
			go ModifyManualEdbMaxMinDate(tradeCode)
		}
		if len(recordList) > 0 {
			go func() {
				obj := models.EdbinfoOpRecord{}
				_ = obj.MulCreate(recordList)
			}()
		}

		// 错误信息记录
		if len(errMsgList) > 0 {
			utils.FileLog.Info("导入失败, errMsgList: %v", strings.Join(errMsgList, "\n"))
		}
	}()
	errMsg = `导入失败`
	xlFile, err := xlsx.OpenFile(path)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	if len(xlFile.Sheets) <= 0 {
		errMsg = "导入模板异常"
		err = errors.New(errMsg)
		return
	}

	//导入失败数据
	failDataList := make([]*models.EdbdataImportFail, 0)
	var indexDataList []ImportManualIndexData
	// 指标名称列表
	indexNameList := make([]string, 0)

	// 模板校验,然后处理成标准化格式
	for _, sheet := range xlFile.Sheets {
		var tmpIndexDataList []ImportManualIndexData
		var tmpFailDataList []*models.EdbdataImportFail
		rowList := sheet.Rows
		if len(rowList) <= 0 {
			errMsg = sheet.Name + "页异常"
			err = errors.New(errMsg)
			return
		}

		templateType := 1 // 模板类型
		minCellNum := 6   // 模板最小列数
		headerCell := rowList[0].Cells

		// 确定模板
		for _, v := range headerCell {
			if v.String() == "导入模板2/Import Template 2" {
				templateType = 2
				minCellNum = 2
				break
			}
		}

		// 如果小于最少列数,则报错
		if len(headerCell) < minCellNum {
			errMsg = sheet.Name + "页模板异常"
			err = errors.New(errMsg)
			return
		}

		switch templateType {
		case 2:
			// 模板2需要走对应的取数逻辑
			tmpIndexDataList, tmpFailDataList, err, errMsg = getDataByTemplate2(sheet, sysUser.AdminId)
		default:
			// 模板1需要走对应的取数逻辑
			tmpIndexDataList, tmpFailDataList, err, errMsg = getDataByTemplate1(sheet, sysUser.AdminId)
		}
		indexDataList = append(indexDataList, tmpIndexDataList...)
		failDataList = append(failDataList, tmpFailDataList...)
	}

	indexDataListMap := make(map[string]ImportManualIndexData)
	for _, v := range indexDataList {
		indexData, ok := indexDataListMap[v.IndexName]
		if !ok {
			// 没有就赋值
			indexDataListMap[v.IndexName] = v
			indexNameList = append(indexNameList, v.IndexName)
			continue
		}

		indexData.Unit = v.Unit
		indexData.ClassName = v.ClassName
		indexData.Frequency = v.Frequency

		indexData.DataMap = v.DataMap
	}

	if len(indexNameList) <= 0 {
		return
	}

	//超管账号可以查看分类下的所有频度数据
	userId := sysUser.AdminId
	if sysUser.RoleTypeCode == utils.ROLE_TYPE_CODE_ADMIN {
		userId = 0
	}
	//获取账户所拥有权限的分类id集合
	classifyNameStrList, edbDataClassifyMap, err := GetEdbClassifyNameListByAdminId(int64(userId))
	if err != nil {
		errMsg = "获取分类数据失败"
		return
	}

	//指标map
	targetMap := make(map[string]*models.Edbinfo)
	defer func() {
		for _, target := range targetMap {
			//结束后,清除掉对应的缓存
			key := "import:edbinfo:data:" + target.TradeCode
			utils.Rc.Delete(key)

			//将该指标的code加入到 “手工数据导入后刷新” 缓存
			if utils.Re == nil {
				err := utils.Rc.LPush(utils.CACHE_IMPORT_MANUAL_DATA, target.TradeCode)
				if err != nil {
					fmt.Println("CACHE_IMPORT_MANUAL_DATA LPush Err:" + err.Error())
				}
			}
		}
	}()

	// 所有的指标数据map
	edbCodeDataMap := make(map[string]map[string]string)

	{
		// 获取指标信息
		manualIndexList, tmpErr := models.GetEdbinfoListBySecNameList(indexNameList)
		if tmpErr != nil {
			err = tmpErr
			errMsg = "获取指标信息失败"
			return
		}

		tradeCodeList := make([]string, 0)
		for _, v := range manualIndexList {
			targetMap[v.SecName] = v
			tradeCodeList = append(tradeCodeList, v.TradeCode)
			recordMap[v.TradeCode] = "更新数据"
		}

		// 获取明细数据
		dataList, tmpErr := models.GetTargetsDataListByCodeList(tradeCodeList)
		if tmpErr != nil {
			err = tmpErr
			errMsg = "获取指标明细数据失败"
			return
		}
		for _, tmpData := range dataList {
			_, ok := edbCodeDataMap[tmpData.TradeCode]
			if !ok {
				edbCodeDataMap[tmpData.TradeCode] = make(map[string]string)
			}
			edbCodeDataMap[tmpData.TradeCode][tmpData.Dt] = tmpData.Close
		}
	}

	//// TODO 成功数量超过20个指标,那就不导入了
	//if len(targetMap) >= 150 {
	//	failItem := new(models.EdbdataImportFail)
	//	failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
	//	failItem.ClassifyName = classifyName
	//	failItem.CreateDate = createDate
	//	failItem.SecName = secName
	//	failItem.Close = closeVal
	//	failItem.Remark = "导入指标数量过多"
	//	failItem.Frequency = frequency
	//	failItem.Unit = unit
	//	failDataList = append(failDataList, failItem)
	//	//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 获取分类:Err:"+err.Error(), utils.EmailSendToUsers)
	//	continue
	//}

	addDataList := make([]*models.Edbdata, 0)

	for _, v := range indexDataListMap {
		if len(v.DataMap) <= 0 {
			continue
		}
		var tmpDate, tmpValue string
		for date, val := range v.DataMap {
			tmpDate = date
			tmpValue = val
			break
		}
		// 指标名称是空的,说明是空列
		if v.IndexName == `` {
			continue
		}

		if !strings.Contains(strings.Join(classifyNameStrList, ","), v.ClassName) {
			failItem := &models.EdbdataImportFail{
				ClassifyName: v.ClassName,
				CreateDate:   tmpDate,
				SecName:      v.IndexName,
				Close:        tmpValue,
				Remark:       "没有该品种分类权限",
				SysUserId:    fmt.Sprint(sysUser.AdminId),
				Frequency:    v.Frequency,
				Unit:         v.Unit,
			}
			failDataList = append(failDataList, failItem)
			continue
		}

		//获取指标分类信息
		classify, ok := edbDataClassifyMap[v.ClassName]
		if !ok {
			failItem := &models.EdbdataImportFail{
				ClassifyName: v.ClassName,
				CreateDate:   tmpDate,
				SecName:      v.IndexName,
				Close:        tmpValue,
				Remark:       "指标分类不存在",
				SysUserId:    fmt.Sprint(sysUser.AdminId),
				Frequency:    v.Frequency,
				Unit:         v.Unit,
			}
			failDataList = append(failDataList, failItem)
			continue
		}

		target, ok := targetMap[v.IndexName]
		if !ok {
			if v.Frequency == "" {
				failItem := &models.EdbdataImportFail{
					ClassifyName: v.ClassName,
					CreateDate:   tmpDate,
					SecName:      v.IndexName,
					Close:        tmpValue,
					Remark:       "新增指标失败,频度字段为空",
					SysUserId:    fmt.Sprint(sysUser.AdminId),
					Frequency:    v.Frequency,
					Unit:         v.Unit,
				}
				failDataList = append(failDataList, failItem)
				continue
			}
			if v.Unit == "" {
				failItem := &models.EdbdataImportFail{
					ClassifyName: v.ClassName,
					CreateDate:   tmpDate,
					SecName:      v.IndexName,
					Close:        tmpValue,
					Remark:       "新增指标失败,单位字段为空",
					SysUserId:    fmt.Sprint(sysUser.AdminId),
					Frequency:    v.Frequency,
					Unit:         v.Unit,
				}
				failDataList = append(failDataList, failItem)
				continue
			}
			tmpErr := AddEdbInfo(v.IndexName, v.Unit, v.Frequency, "", sysUser.Mobile, classify.ClassifyId, sysUser.AdminId, sysUser.RealName)
			if tmpErr != nil {
				fmt.Println("line 158")

				failItem := &models.EdbdataImportFail{
					ClassifyName: v.ClassName,
					CreateDate:   tmpDate,
					SecName:      v.IndexName,
					Close:        tmpValue,
					Remark:       "新增指标失败",
					SysUserId:    fmt.Sprint(sysUser.AdminId),
					Frequency:    v.Frequency,
					Unit:         v.Unit,
				}
				failDataList = append(failDataList, failItem)
				continue
			}
			// 新增指标记录数
			indexCount++

			tmpTarget, tmpErr := models.GetTargetBySecName(v.IndexName)
			target = tmpTarget
			targetMap[v.IndexName] = target

			recordMap[target.TradeCode] = "创建指标"
		}

		if target == nil {
			fmt.Println("指标不存在")
			failItem := &models.EdbdataImportFail{
				ClassifyName: v.ClassName,
				CreateDate:   tmpDate,
				SecName:      v.IndexName,
				Close:        tmpValue,
				Remark:       "指标不存在",
				SysUserId:    fmt.Sprint(sysUser.AdminId),
				Frequency:    v.Frequency,
				Unit:         v.Unit,
			}
			failDataList = append(failDataList, failItem)
			continue
		}

		//设置10分钟缓存,不允许其他地方删除
		key := "import:edbinfo:data:" + target.TradeCode
		utils.Rc.SetNX(key, 1, time.Second*600)

		//更新指标信息
		{
			if v.Frequency == "" {
				failItem := &models.EdbdataImportFail{
					ClassifyName: v.ClassName,
					CreateDate:   tmpDate,
					SecName:      v.IndexName,
					Close:        tmpValue,
					Remark:       "更新指标失败,频度字段为空",
					SysUserId:    fmt.Sprint(sysUser.AdminId),
					Frequency:    v.Frequency,
					Unit:         v.Unit,
				}
				failDataList = append(failDataList, failItem)
				continue
			}
			if v.Unit == "" {
				failItem := &models.EdbdataImportFail{
					ClassifyName: v.ClassName,
					CreateDate:   tmpDate,
					SecName:      v.IndexName,
					Close:        tmpValue,
					Remark:       "更新指标失败,单位字段为空",
					SysUserId:    fmt.Sprint(sysUser.AdminId),
					Frequency:    v.Frequency,
					Unit:         v.Unit,
				}
				failDataList = append(failDataList, failItem)
				continue
			}

			updateCols := make([]string, 0)
			//更新指标分类
			if target.ClassifyId <= 0 && classify.ClassifyId > 0 {
				target.ClassifyId = classify.ClassifyId
				updateCols = append(updateCols, "ClassifyId")
			}
			if target.Frequency != v.Frequency {
				target.Frequency = v.Frequency
				target.NoticeTime = ""
				updateCols = append(updateCols, "Frequency", "NoticeTime")
			}
			if target.Unit != v.Unit {
				target.Unit = v.Unit
				updateCols = append(updateCols, "Unit")
			}
			if len(updateCols) > 0 {
				_ = target.Update(updateCols)
			}
		}

		{
			// 判断指标数据列表是否已经存在
			tmpDataMap, ok := edbCodeDataMap[target.TradeCode]
			if !ok {
				tmpDataMap = make(map[string]string)
				edbCodeDataMap[target.TradeCode] = tmpDataMap
			}

			for createDate, closeVal := range v.DataMap {
				//判断数据是否已经存在
				tmpVal, ok := tmpDataMap[createDate]
				//数据已存在,进行更新操作
				if ok {
					if tmpVal != closeVal {
						edbCodeDataMap[target.TradeCode][createDate] = closeVal
						tmpErr := models.ModifyTargetsDataByImport(target.TradeCode, createDate, closeVal)
						if tmpErr != nil {
							errMsgList = append(errMsgList, fmt.Sprintf("%s修改数据失败,日期:%s,值:%v,Err:%s", target.TradeCode, createDate, closeVal, tmpErr.Error()))
						}
					}
				} else { //数据不存在,进行新增操作
					if target.TradeCode != "" && createDate != "" && closeVal != "" {
						addDataList = append(addDataList, &models.Edbdata{
							TradeCode:  target.TradeCode,
							Dt:         createDate,
							Close:      closeVal,
							ModifyTime: time.Now(),
						})
						edbCodeDataMap[target.TradeCode][createDate] = closeVal
					}
				}
				successCount++
			}
		}
	}

	// 批量添加明细数据
	if len(addDataList) > 0 {
		tmpErr := models.OnlyMultiAddEdbdata(addDataList)
		if tmpErr != nil {
			fmt.Println("line 221")
			errMsgList = append(errMsgList, fmt.Sprintf("批量添加明细数据失败,Err:%s", tmpErr.Error()))
		}
	}

	// 失败数量
	failCount = len(failDataList)
	//fmt.Println("failDataList:", len(failDataList))
	if failCount > 0 {
		//先删除导入失败记录
		_ = models.DelEdbDataImportFail(sysUser.AdminId)

		// 批量添加导入失败记录
		err = models.MultiAddEdbdataImportFail(failDataList)
		if err != nil {
			go alarm_msg.SendAlarmMsg("导入数据 新增失败记录失败,Err:"+err.Error(), 3)
			//go utils.SendEmail(utils.APPNAME+"失败提醒", "导入数据 新增失败记录失败:Err:"+err.Error(), utils.EmailSendToUsers)
		}

		{
			//错误信息字符串切片,最后作为发送邮件通知使用
			failContents := make([]string, 0)
			for _, v := range failDataList {
				failContents = append(failContents, fmt.Sprint(v.SecName, "导入失败:", v.Remark))
			}
			utils.FileLog.Info("导入数据 存在部分数据导入失败:" + strings.Join(failContents, ";"))
			//导入失败的话,最后统一邮件提醒就好啦,不需要每次都去提醒
			go alarm_msg.SendAlarmMsg("导入数据 存在部分数据导入失败:"+strings.Join(failContents, ";"), 3)
		}
	}

	return
}

// ImportManualIndexData
// @Description: excel模板后的内容
type ImportManualIndexData struct {
	IndexName string            `description:"指标名称"`
	Unit      string            `description:"单位"`
	ClassName string            `description:"所属品种"`
	Frequency string            `description:"频度"`
	DataMap   map[string]string `description:"时间数据"`
}

// getDataByTemplate1
// @Description: 根据模板1获取数据
// @author: Roc
// @datetime 2024-07-24 16:17:45
// @param sheet *xlsx.Sheet
// @return indexDataList []ImportManualIndexData
// @return err error
// @return errMsg string
func getDataByTemplate1(sheet *xlsx.Sheet, sysUserId int) (indexDataList []ImportManualIndexData, failDataList []*models.EdbdataImportFail, err error, errMsg string) {
	fmt.Println("sheet name: ", sheet.Name)
	indexDataList = make([]ImportManualIndexData, 0)
	indexDataListMap := make(map[string]ImportManualIndexData, 0)
	failDataList = make([]*models.EdbdataImportFail, 0)

	//遍历行读取
	maxRow := sheet.MaxRow
	fmt.Println("maxRow:", maxRow)

	// 表头信息
	if maxRow <= 2 {
		errMsg = "模板异常1"
		err = errors.New(errMsg)
		return
	}

	// 表头校验
	{
		headerRow := sheet.Row(1)
		cells := headerRow.Cells
		if len(cells) < 6 {
			errMsg = "导入文件异常,请下载最新导入模板文件"
			err = errors.New(errMsg)
			return
		}

		templateFail := false
		if cells[0].Value != "品种/Variety" {
			templateFail = true
		}
		if cells[1].Value != "指标名称/Indicator Name" {
			templateFail = true
		}
		if cells[2].Value != "指标日期/Indicator Date" {
			templateFail = true
		}
		if cells[3].Value != "值/Value" {
			templateFail = true
		}
		if cells[4].Value != "频度/Frequency" {
			templateFail = true
		}
		if cells[5].Value != "单位/Unit" {
			templateFail = true
		}
		if templateFail {
			errMsg = "导入文件异常,请下载最新导入模板文件"
			err = errors.New(errMsg)
			return
		}
	}

	for i := 2; i < maxRow; i++ {
		row := sheet.Row(i)
		cells := row.Cells
		lenCell := len(cells)

		// 过滤空白行
		if lenCell <= 0 {
			continue
		}

		if lenCell < 6 {
			if cells[0].Value == `` {
				continue
			}
			errMsg = "导入文件异常,请下载最新导入模板文件"
			err = errors.New(errMsg)
			return
		}

		classifyName := strings.TrimSpace(cells[0].Value) //分类
		if classifyName == "" {                           //过滤空白行
			continue
		}
		// 指标名称
		cell1 := cells[1].Value
		indexName := strings.TrimSpace(cell1)
		if indexName == "" { //过滤空白行
			continue
		}
		//createDate := utils.ConvertToFormatDay(cell1) //录入日期
		createDate := cells[2].Value                      //指标日期
		frequency := strings.TrimSpace(cells[4].String()) //频度
		unit := strings.TrimSpace(cells[5].String())      //单位

		closeVal := cells[3].Value //值
		if strings.Contains(closeVal, "#N/A") {
			continue
		}

		currDate, tmpErr := getExcelDate(createDate)
		if tmpErr != nil {
			failDataList = append(failDataList, &models.EdbdataImportFail{
				//Id:           0,
				ClassifyName: classifyName,
				CreateDate:   createDate,
				SecName:      indexName,
				Close:        closeVal,
				Remark:       "日期格式异常",
				SysUserId:    strconv.Itoa(sysUserId),
				Frequency:    frequency,
				Unit:         unit,
			})
			continue
		}

		closeValFloat, tmpErr := cells[3].Float() //值
		if tmpErr != nil {
			failDataList = append(failDataList, &models.EdbdataImportFail{
				//Id:           0,
				ClassifyName: classifyName,
				CreateDate:   currDate,
				SecName:      indexName,
				Close:        cells[3].Value,
				Remark:       "值类型异常",
				SysUserId:    strconv.Itoa(sysUserId),
				Frequency:    frequency,
				Unit:         unit,
			})
			continue
		}
		newDecimal := decimal.NewFromFloat(closeValFloat)
		newDecimal.Round(4)
		closeVal = newDecimal.String()
		if strings.Contains(closeVal, "#N/A") {
			continue
		}

		_, ok := indexDataListMap[indexName]
		if !ok {
			indexDataListMap[indexName] = ImportManualIndexData{
				IndexName: indexName,
				Unit:      unit,
				ClassName: classifyName,
				Frequency: frequency,
				DataMap:   make(map[string]string),
			}
		}

		indexDataListMap[indexName].DataMap[currDate] = closeVal
	}

	for _, v := range indexDataListMap {
		indexDataList = append(indexDataList, v)
	}

	return
}

// getDataByTemplate2
// @Description: 根据模板2获取数据
// @author: Roc
// @datetime 2024-07-24 16:17:56
// @param sheet *xlsx.Sheet
// @return indexDataList []ImportManualIndexData
// @return err error
// @return errMsg string
func getDataByTemplate2(sheet *xlsx.Sheet, sysUserId int) (indexDataList []ImportManualIndexData, failDataList []*models.EdbdataImportFail, err error, errMsg string) {
	//fmt.Println("sheet name: ", sheet.Name)
	indexDataList = make([]ImportManualIndexData, 0)
	failDataList = make([]*models.EdbdataImportFail, 0)

	//遍历行读取
	maxRow := sheet.MaxRow
	//fmt.Println("maxRow:", maxRow)

	varietyList := make([]string, 0)
	indexNameList := make([]string, 0)
	unitList := make([]string, 0)
	frequencyList := make([]string, 0)

	// make(map[指标下标]map[日期]值)
	indexDateValueMap := make(map[int]map[string]string)

	// 表头信息
	if maxRow <= 4 {
		errMsg = "模板异常1"
		err = errors.New(errMsg)
		return
	}

	// 表头处理
	for i := 1; i <= 4; i++ {
		row := sheet.Row(i)
		cells := row.Cells
		//if len(cells) < 1 {
		//	errMsg = "模板异常2"
		//	err = errors.New(errMsg)
		//	return
		//}

		switch i {
		case 1:
			for k, v := range cells {
				if k == 0 {
					continue
				}
				varietyList = append(varietyList, strings.TrimSpace(v.String()))
			}
		case 2:
			for k, v := range cells {
				if k == 0 {
					continue
				}
				indexNameList = append(indexNameList, strings.TrimSpace(v.String()))
			}
		case 3:
			for k, v := range cells {
				if k == 0 {
					continue
				}
				unitList = append(unitList, strings.TrimSpace(v.String()))
			}
		case 4:
			for k, v := range cells {
				if k == 0 {
					continue
				}
				frequencyList = append(frequencyList, strings.TrimSpace(v.String()))
			}
		}
	}

	maxNameIndex := len(indexNameList) - 1
	maxUnitIndex := len(unitList) - 1
	maxClassNameIndex := len(varietyList) - 1
	maxFrequencyIndex := len(frequencyList) - 1

	// 数据处理
	for i := 5; i < maxRow; i++ {
		row := sheet.Row(i)
		cells := row.Cells
		//if len(cells) < 1 {
		//	errMsg = "模板异常2"
		//	err = errors.New(errMsg)
		//	return
		//}
		// 当前日期
		var currDate string

		// 日期是否异常,异常的话,就跳过,进入下一行数据处理
		var dateErr bool
		var emptyDate bool

		// 数据处理
		for k, v := range cells {
			if k == 0 {
				// 空日期数据
				if v.Value == `` {
					emptyDate = true
					continue
				}

				tmpCurrDate, tmpErr := getExcelDate(v.Value)
				if tmpErr != nil {
					dateErr = true
				}

				currDate = tmpCurrDate
				continue
			}
			key := k - 1

			// 空日期数据,那就不处理了,不记录该行错误信息
			if emptyDate {
				continue
			}

			// 日期异常,所以不处理该行了同时记录该行错误信息
			if dateErr {
				var indexName, unit, classifyName, frequency string
				if key <= maxNameIndex {
					indexName = indexNameList[key]
				}
				if key <= maxUnitIndex {
					unit = unitList[key]
				}
				if key <= maxClassNameIndex {
					classifyName = varietyList[key]
				}
				if key <= maxFrequencyIndex {
					frequency = frequencyList[key]
				}

				failDataList = append(failDataList, &models.EdbdataImportFail{
					//Id:           0,
					ClassifyName: classifyName,
					CreateDate:   currDate,
					SecName:      indexName,
					Close:        v.Value,
					Remark:       "日期格式异常",
					SysUserId:    strconv.Itoa(sysUserId),
					Frequency:    frequency,
					Unit:         unit,
				})

				continue
			}

			_, ok := indexDateValueMap[key]
			if !ok {
				indexDateValueMap[key] = make(map[string]string)
			}

			closeVal := v.Value //值
			// 没有数据,说明是空串
			if strings.Contains(closeVal, "#N/A") {
				indexDateValueMap[key][currDate] = ""
				continue
			}

			closeValFloat, tmpErr := v.Float() //值
			if tmpErr != nil {
				// TODO 错误数据记录
				//failItem := new(models.EdbdataImportFail)
				//failItem.SysUserId = strconv.Itoa(sysUser.AdminId)
				//failItem.ClassifyName = classifyName
				//failItem.CreateDate = createDate
				//failItem.SecName = secName
				//failItem.Close = cells[3].Value
				//failItem.Remark = "值类型异常"
				//failItem.Frequency = frequency
				//failItem.Unit = unit
				//failDataList = append(failDataList, failItem)
				indexDateValueMap[key][currDate] = ""
				continue
			}

			newDecimal := decimal.NewFromFloat(closeValFloat)
			newDecimal.Round(4)
			closeVal = newDecimal.String()
			if strings.Contains(closeVal, "#N/A") {
				indexDateValueMap[key][currDate] = ""
				continue
			}
			indexDateValueMap[key][currDate] = closeVal
		}

	}

	for i, indexName := range indexNameList {
		var unit, classifyName, frequency string
		if i <= maxUnitIndex {
			unit = unitList[i]
		}
		if i <= maxClassNameIndex {
			classifyName = varietyList[i]
		}
		if i <= maxFrequencyIndex {
			frequency = frequencyList[i]
		}
		indexData := ImportManualIndexData{
			IndexName: indexName,
			Unit:      unit,
			ClassName: classifyName,
			Frequency: frequency,
			DataMap:   indexDateValueMap[i],
		}
		indexDataList = append(indexDataList, indexData)
	}

	return
}

// getExcelDate
// @Description: 获取excel的日期
// @author: Roc
// @datetime 2024-07-23 17:26:12
// @param createDate string
// @return newCreateDate string
// @return err error
func getExcelDate(createDate string) (newCreateDate string, err error) {
	if strings.Contains(createDate, "-") {
		//如果是带有 - 的普通日期格式文本
		_, err = time.Parse("2006-1-2", createDate)
		if err == nil {
			newCreateDate = createDate
		}
	} else if strings.Contains(createDate, "/") {
		//如果是带有 / 的普通日期格式文本
		createDateTime, timeErr := time.Parse("2006/1/2", createDate)
		if timeErr != nil {
			err = timeErr
		} else {
			newCreateDate = createDateTime.Format("2006-01-02")
		}
	} else {
		//可能是excel的日期格式
		_, tmpErr := strconv.Atoi(createDate)
		if tmpErr != nil {
			err = tmpErr
		} else {
			newCreateDate = utils.ConvertToFormatDay(createDate) //录入日期
		}
	}

	return
}

// ModifyManualEdbMaxMinDate
// @Description: 修改手动录入的edb数据的最大最小日期
// @author: Roc
// @datetime 2024-08-01 15:34:31
// @param tradeCode string
func ModifyManualEdbMaxMinDate(tradeCode string) {
	// 获取最大最小日期
	item, err := models.GetEdbdataMaxMinDate(tradeCode)
	if err != nil {
		return
	}

	// 最新值
	latestValue, err := models.GetEdbdataLatestValue(tradeCode)
	if err != nil {
		return
	}

	// 修改指标的最大最小日期和最新值
	err = models.ModifyEdbinfoMaxMinDate(tradeCode, item.MinDate, item.MaxDate, latestValue)

	return
}

// GetUserManualClassifyIdList
// @Description: 获取用户手动录入的分类id列表
// @author: Roc
// @datetime 2024-08-02 15:09:11
// @param userId int
// @return classifyIdList []int
// @return err error
func GetUserManualClassifyIdList(userId int) (classifyIdList []int, err error) {
	classifyIdList = make([]int, 0)

	// 获取有用权限的分类
	classifyList, err := models.GetEdbdataClassify(int64(userId))
	if err != nil {
		return
	}

	if len(classifyList) > 0 {
		for _, v := range classifyList {
			classifyIdList = append(classifyIdList, v.ClassifyId)
			if v.Child != nil && len(v.Child) > 0 {
				for _, v2 := range v.Child {
					classifyIdList = append(classifyIdList, v2.ClassifyId)
				}
			}
		}
	}

	return
}