package services

import (
	"errors"
	"eta/eta_api/models"
	"eta/eta_api/models/document_manage_model"
	"eta/eta_api/models/report_approve"
	"eta/eta_api/utils"
	"fmt"
	"sort"
	"time"

	"github.com/beego/beego/v2/core/logs"
)

// MoveReportClassify 移动分类
func MoveReportClassify(req models.ClassifyMoveReq) (err error, errMsg string) {
	classifyId := req.ClassifyId
	prevClassifyId := req.PrevClassifyId
	nextClassifyId := req.NextClassifyId

	//如果有传入 上一个兄弟节点分类id
	var (
		classifyInfo *models.Classify
		prevClassify *models.Classify
		nextClassify *models.Classify

		prevSort int
		nextSort int
	)

	// 移动对象为分类, 判断权限
	classifyInfo, err = models.GetClassifyById(classifyId)
	if err != nil {
		if utils.IsErrNoRow(err) {
			errMsg = "分类不存在, 请刷新页面"
			err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
			return
		}
		errMsg = "移动失败"
		err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
		return
	} else if classifyInfo.Id == 0 {
		errMsg = "分类不存在, 请刷新页面"
		err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
		return
	}

	parentClassifyId := classifyInfo.ParentId
	if prevClassifyId > 0 {
		prevClassify, err = models.GetClassifyById(prevClassifyId)
		if err != nil {
			if utils.IsErrNoRow(err) {
				errMsg = "上一个分类不存在, 请刷新页面"
				err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
				return
			}
			errMsg = "移动失败"
			err = fmt.Errorf("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
			return
		}
		if prevClassify.ParentId != parentClassifyId {
			errMsg = "禁止拖动到其他节点"
			err = fmt.Errorf(errMsg)
			return
		}
		prevSort = prevClassify.Sort
	}

	if nextClassifyId > 0 {
		//下一个兄弟节点
		nextClassify, err = models.GetClassifyById(nextClassifyId)
		if err != nil {
			if utils.IsErrNoRow(err) {
				errMsg = "下一个分类不存在, 请刷新页面"
				err = fmt.Errorf("获取分类信息失败,Err:" + err.Error())
				return
			}
			errMsg = "移动失败"
			err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
			return
		}
		if nextClassify.ParentId != parentClassifyId {
			errMsg = "禁止拖动到其他节点"
			err = fmt.Errorf(errMsg)
			return
		}
		nextSort = nextClassify.Sort
	}

	err, errMsg = moveReportClassify(classifyInfo, prevClassify, nextClassify, parentClassifyId, prevSort, nextSort)
	return
}

// moveReportClassify 移动分类
func moveReportClassify(classifyInfo, prevClassify, nextClassify *models.Classify, parentId, prevSort, nextSort int) (err error, errMsg string) {
	ob := new(models.Classify)
	updateCol := make([]string, 0)

	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
	if classifyInfo.ParentId != parentId {
		errMsg = "移动失败"
		err = fmt.Errorf("不支持目录层级变更")
		return
	}

	if prevSort > 0 {
		//如果是移动在两个兄弟节点之间
		if nextSort > 0 {
			//下一个兄弟节点
			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
			if prevSort == nextSort || prevSort == classifyInfo.Sort {
				//变更兄弟节点的排序
				updateSortStr := `sort + 2`

				//变更分类
				if prevClassify != nil {
					_ = models.UpdateClassifySortByParentId(parentId, prevClassify.Id, prevClassify.Sort, updateSortStr)
				} else {
					_ = models.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr)
				}

			} else {
				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
				if nextSort-prevSort == 1 {
					//变更兄弟节点的排序
					updateSortStr := `sort + 1`

					//变更分类
					if prevClassify != nil {
						_ = models.UpdateClassifySortByParentId(parentId, prevClassify.Id, prevSort, updateSortStr)
					} else {
						_ = models.UpdateClassifySortByParentId(parentId, 0, prevSort, updateSortStr)
					}

				}
			}
		}

		classifyInfo.Sort = prevSort + 1
		classifyInfo.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	} else if prevClassify == nil && nextClassify == nil && parentId > 0 {
		//处理只拖动到目录里,默认放到目录底部的情况
		var maxSort int
		maxSort, err = ob.GetMaxSortByParentId(parentId)
		if err != nil {
			errMsg = "移动失败"
			err = fmt.Errorf("查询组内排序信息失败,Err:" + err.Error())
			return
		}
		classifyInfo.Sort = maxSort + 1 //那就是排在组内最后一位
		classifyInfo.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	} else {
		// 拖动到父级分类的第一位
		firstPermission, tmpErr := ob.GetFirstClassifyByParentId(parentId)
		if tmpErr != nil && !utils.IsErrNoRow(tmpErr) {
			errMsg = "移动失败"
			err = fmt.Errorf("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
			return
		}

		//如果该分类下存在其他分类,且第一个其他分类的排序等于0,那么需要调整排序
		if firstPermission != nil && firstPermission.Id != 0 && firstPermission.Sort == 0 {
			updateSortStr := ` sort + 1 `
			_ = models.UpdateClassifySortByParentId(parentId, firstPermission.Id-1, 0, updateSortStr)
		}

		classifyInfo.Sort = 0 //那就是排在第一位
		classifyInfo.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	}

	//更新
	if len(updateCol) > 0 {
		err = classifyInfo.UpdateClassify(updateCol)
		if err != nil {
			errMsg = "移动失败"
			err = fmt.Errorf("修改失败,Err:" + err.Error())
			return
		}
	}
	return
}

// AddReportClassify
// @Description: 添加报告分类
// @author: Roc
// @datetime 2024-06-17 11:01:21
// @param classifyName string
// @param parentId int
// @param chartPermissionIdList []int
// @return err error
// @return errMsg string
// @return isSendEmail bool
func AddReportClassify(classifyName string, parentId int, chartPermissionIdList []int) (err error, errMsg string, isSendEmail bool) {
	isSendEmail = true
	errMsg = `添加失败`
	item, err := models.GetClassifyByName(classifyName, parentId)
	if err != nil && !utils.IsErrNoRow(err) {
		errMsg = "获取分类信息失败"
		if utils.IsErrNoRow(err) {
			errMsg = "分类名称:" + classifyName + "已存在"
			isSendEmail = false
		}
		return
	}
	if item != nil && item.Id > 0 {
		errMsg = "分类名称:" + classifyName + "已存在"
		isSendEmail = false
		err = errors.New(errMsg)
		return
	}

	level := 1

	// 父级分类
	var parentClassifyItem *models.Classify
	// 父级分类下的子分类数量
	var childClassifyCount int

	if parentId > 0 {
		// 获取父级分类信息
		parentClassifyItem, err = models.GetClassifyById(parentId)
		if err != nil {
			errMsg = "获取父级分类信息失败"
			if utils.IsErrNoRow(err) {
				errMsg = "父级分类不存在"
			}
			return
		}
		level = parentClassifyItem.Level + 1

		if level > 3 {
			errMsg = "分类层级不可超过三级"
			isSendEmail = false
			return
		}

		// 判断是否分类存在待操作的审批单
		err, errMsg = checkClassifyApprove(parentClassifyItem)
		if err != nil {
			return
		}

		// 获取父级分类下的子分类数量
		childClassifyCount, err = models.GetCountClassifyChildByParentId(parentId)
		if err != nil {
			errMsg = "获取父级分类的子分类信息失败"
			return
		}

		// 清除父级分类的收藏 战研2.1
		err = models.DeleteCollectByClassifyId(parentId)
		if err != nil {
			errMsg = "清除父级分类的收藏失败"
			return
		}

	}

	nowTime := time.Now().Local()
	classify := new(models.Classify)

	maxSort, err := classify.GetMaxSort()
	if err != nil {
		errMsg = "操作失败"
		err = errors.New("查询品种排序失败, Err: " + err.Error())
		return
	}
	classify.ClassifyName = classifyName
	classify.ParentId = parentId
	classify.CreateTime = nowTime
	classify.ModifyTime = nowTime
	classify.Sort = maxSort + 1
	classify.Enabled = 1
	classify.ShowType = 1             //默认列表格式
	classify.ReportDetailShowType = 1 //默认列表格式
	classify.IsShow = 1
	classify.Level = level

	err = models.AddClassify(classify)
	if err != nil {
		return
	}

	// 如果当前分类下,没有其他分类,则将当前分类下的所有报告放入新分类下
	count, err := models.GetClassifySubCountByParentId(parentId)
	if err != nil {
		return err, "查询分类下所有的分类记录数失败", false
	}

	if count == 1 {
		// 如果父级分类下 无其他子分类 并且有报告,修改报告到子级分类下
		reports, err := models.GetReportListByClassifyId(parentId)
		if err != nil {
			return err, "查询报告列表失败", false
		}
		if len(reports) > 0 {
			for _, report := range reports {
				// 一级分类不用判断,有报告一定有分类,二级分类如果等于0,就不用判断三级了
				if report.ClassifyIdSecond == 0 {
					report.ClassifyIdSecond = classify.Id
					report.ClassifyNameSecond = classifyName
				} else if report.ClassifyIdThird == 0 {
					report.ClassifyIdThird = classify.Id
					report.ClassifyNameThird = classifyName
				}

				// beego orm 不支持批量修改,所以只能一个一个修改
				err := models.UpdateReportInfo(report)
				if err != nil {
					return err, "修改报告分类失败", false
				}
			}
		}
		outsideReports, err := document_manage_model.GetOutsideReportListByClassifyId(parentId)
		if err != nil {
			return err, "查询外部报告列表失败", false
		}
		if len(outsideReports) > 0 {
			for _, report := range outsideReports {
				tempReport := report

				tempReport.ClassifyId = classify.Id
				tempReport.ClassifyName = classifyName
				// 修改报告
				err := document_manage_model.UpdateOutsideReport(&tempReport, []string{"ClassifyId", "ClassifyName"})
				if err != nil {
					return err, "修改外部报告分类失败", false
				}
			}
		}

	}

	//获取报告分类权限列表
	err = models.EditChartPermissionSearchKeyWordMappingMulti(classifyName, chartPermissionIdList, classify.Id)
	if err != nil {
		errMsg = "修改分类权限失败"
		return
	}

	// 修改CRM权限
	go func() {
		_ = EditClassifyChartPermissionSync(classifyName, classify.Id)
	}()

	// 如果父级分类不为空的话,那么就标记有子级分类,同时
	if parentClassifyItem != nil {
		parentClassifyItem.HasChild = 1
		parentClassifyItem.UpdateClassify([]string{"HasChild"})

		// 如果以前没有子级分类,那么就继承父级分类下的章节类型(创建新的章节与分类的关系)
		if childClassifyCount <= 0 {
			// 继承父级分类下的章节类型(创建新的章节与分类的关系)
			tmpErr := inheritReportChapterType(parentId, classify.Id)
			if tmpErr != nil {
				return
			}

			// 继承父级分类审批流
			go inheritReportApproveFlow(parentClassifyItem, classify)

			moveReportByAddClassify(parentClassifyItem, classify)
		}
	}

	return
}

// checkClassifyApprove
// @Description: 判断分类是否存在待操作的审批单
// @author: Roc
// @datetime 2024-06-27 13:19:15
// @param currClassify *models.Classify
// @return err error
// @return errMsg string
func checkClassifyApprove(currClassify *models.Classify) (err error, errMsg string) {
	errMsg = `判断是否有审批流关联失败`
	var firstClassifyId, secondClassifyId int
	if currClassify.ParentId > 0 {
		parentClassifyItem, tmpErr := models.GetClassifyById(currClassify.ParentId)
		if tmpErr != nil {
			err = tmpErr
			errMsg = "获取父级分类信息失败"
			if utils.IsErrNoRow(tmpErr) {
				errMsg = "父级分类不存在"
			}
			return
		}
		firstClassifyId = parentClassifyItem.Id
		secondClassifyId = currClassify.Id
	} else {
		firstClassifyId = currClassify.Id
	}
	// 校验审批流是否关联了进行中的审批
	{
		flowOb := new(report_approve.ReportApproveFlow)

		existCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ? AND %s = ?`, report_approve.ReportApproveFlowCols.ReportType, report_approve.ReportApproveFlowCols.ClassifyFirstId, report_approve.ReportApproveFlowCols.ClassifySecondId, report_approve.ReportApproveFlowCols.ClassifyThirdId)
		existPars := make([]interface{}, 0)
		existPars = append(existPars, report_approve.FlowReportTypeChinese, firstClassifyId, secondClassifyId, 0)
		flowItem, e := flowOb.GetItemByCondition(existCond, existPars, "")
		if e != nil {
			// 父级分类如果没有审批流,那么就正常进行就好了
			if !utils.IsErrNoRow(e) {
				err = errors.New("获取审批流是否已存在失败, Err: " + e.Error())
				return
			}
			err = nil
			return
		}
		if flowItem == nil {
			return
		}

		approvingOb := new(report_approve.ReportApprove)
		approvingCond := fmt.Sprintf(` AND %s = ? AND %s = ? AND %s = ?`, report_approve.ReportApproveCols.FlowId, report_approve.ReportApproveCols.FlowVersion, report_approve.ReportApproveCols.State)
		approvingPars := make([]interface{}, 0)
		approvingPars = append(approvingPars, flowItem.ReportApproveFlowId, flowItem.CurrVersion, report_approve.ReportApproveStateApproving)
		count, e := approvingOb.GetCountByCondition(approvingCond, approvingPars)
		if e != nil {
			err = errors.New("获取审批流关联进行中的审批数失败. Err: " + e.Error())
			return
		}
		if count > 0 {
			errMsg = "当前有未走完流程的报告,请走完流程后再做变更"
			err = errors.New(errMsg)
			return
		}
	}

	return
}

// 关于研报分类,因只允许报告或品种关联在最小分类下,所以当某个父分类(非三级分类)已关联报告或品种,需要在该父分类下增加子分类,则第一个子分类添加成功时,默认把该父分类关联的品种和报告转移至新创建的子分类(第一个子分类)下
// moveReportByAddClassify
// @Description: 报告和章节的转移
// @author: Roc
// @datetime 2024-06-17 16:29:56
// @param parentClassifyInfo *models.Classify
// @param currClassifyInfo *models.Classify
// @return err error
func moveReportByAddClassify(parentClassifyInfo, currClassifyInfo *models.Classify) (err error) {
	defer func() {
		if err != nil {
			utils.FileLog.Error(fmt.Sprint("历史报告更改分类失败,父级分类ID:", parentClassifyInfo.Id, ";当前分类ID:", currClassifyInfo.Id, ";错误信息:", err.Error()))
		}
	}()
	if currClassifyInfo.Level > 3 {
		err = errors.New("父级分类不支持三级分类以上")
		return
	}

	// 报告的分类归属调整,转为下一级的分类

	var condition, updateStr string
	pars := make([]interface{}, 0)
	switch currClassifyInfo.Level {
	case 3: // 当前分类是3级分类
		updateStr += ` classify_id_third = ?,classify_name_third = ?`
		condition += ` AND classify_id_second = ? `
	case 2: // 当前分类是2级分类
		updateStr += ` classify_id_second = ?,classify_name_second = ?`
		condition += ` AND classify_id_first = ? `
	default:
		err = errors.New("错误的分类层级")
		return
	}

	pars = append(pars, currClassifyInfo.Id, currClassifyInfo.ClassifyName, parentClassifyInfo.Id)

	// 获取当前分类下的所有章节类型
	currReportChapterTypeList, err := models.GetAllReportChapterTypeListByClassifyId(currClassifyInfo.Id)
	if err != nil {
		return
	}
	// 当前的章节类型ID ---> 继承的章节类型ID
	chapterTypeIdMap := make(map[int]int)
	for _, v := range currReportChapterTypeList {
		chapterTypeIdMap[v.ReportChapterTypeId] = v.InheritReportChapterTypeId
	}

	// 报告转移后,历史章节报告中的type_id也要修复成最新的type_id
	err = models.ModifyReportClassifyAndReportChapterTypeByCondition(condition, pars, updateStr, chapterTypeIdMap, parentClassifyInfo.Id, currClassifyInfo.Id, currClassifyInfo.ClassifyName)
	if err != nil {
		return
	}

	return
}

// inheritReportChapterType
// @Description: 继承父级分类下的章节类型
// @author: Roc
// @datetime 2024-06-17 14:41:04
// @param parentClassifyId int
// @param currClassifyId int
// @return err error
func inheritReportChapterType(parentClassifyId, currClassifyId int) (err error) {
	defer func() {
		if err != nil {
			utils.FileLog.Error(fmt.Sprint("继承父级分类下的章节类型失败,父级分类ID:", parentClassifyId, ";当前分类ID:", currClassifyId, ";错误信息:", err.Error()))
		}
	}()
	parentReportChapterTypeList, err := models.GetAllReportChapterTypeListByClassifyId(parentClassifyId)
	if err != nil {
		return
	}

	// 如果没有章节类型,那么就直接返回
	if len(parentReportChapterTypeList) <= 0 {
		return
	}

	addList := make([]*models.ReportChapterType, 0)
	for _, v := range parentReportChapterTypeList {
		addList = append(addList, &models.ReportChapterType{
			//ReportChapterTypeId:        0,
			ReportChapterTypeKey:       v.ReportChapterTypeKey,
			ReportChapterTypeThumb:     v.ReportChapterTypeThumb,
			BannerUrl:                  v.BannerUrl,
			ReportChapterTypeName:      v.ReportChapterTypeName,
			Sort:                       v.Sort,
			Enabled:                    v.Enabled,
			CreatedTime:                time.Now(),
			LastUpdatedTime:            time.Now(),
			ResearchType:               v.ResearchType,
			SelectedImage:              v.SelectedImage,
			UnselectedImage:            v.UnselectedImage,
			PcSelectedImage:            v.PcSelectedImage,
			PcUnselectedImage:          v.PcUnselectedImage,
			EditImgUrl:                 v.EditImgUrl,
			TickerTitle:                v.TickerTitle,
			IsShow:                     v.IsShow,
			PauseStartTime:             v.PauseStartTime,
			PauseEndTime:               v.PauseEndTime,
			IsSet:                      v.IsSet,
			YbIconUrl:                  v.YbIconUrl,
			YbBottomIcon:               v.YbBottomIcon,
			ReportClassifyId:           currClassifyId,
			InheritReportChapterTypeId: v.ReportChapterTypeId,
		})
	}

	obj := models.ReportChapterType{}
	err = obj.MultiCreate(addList)

	// 修改CRM权限
	go func() {
		var syncReq ChapterTypeSyncReq
		_, _ = ReportChapterTypeSync(&syncReq)
	}()

	return
}

// inheritReportApproveFlow
// @Description: 继承父级分类下的审批流
// @author: Roc
// @datetime 2024-06-17 14:41:04
// @param parentClassifyId int
// @param currClassifyId int
// @return err error
func inheritReportApproveFlow(parentClassifyItem, currClassifyItem *models.Classify) (err error) {
	defer func() {
		if err != nil {
			utils.FileLog.Error(fmt.Sprint("继承父级分类下的审批流失败,父级分类ID:", parentClassifyItem.Id, ";当前分类ID:", currClassifyItem.Id, ";错误信息:", err.Error()))
		}
	}()

	var firstClassify, secondClassify, thirdClassify *models.Classify
	if parentClassifyItem.ParentId > 0 {
		// 获取父级分类信息
		firstClassify, err = models.GetClassifyById(parentClassifyItem.ParentId)
		if err != nil {
			return
		}

		secondClassify = parentClassifyItem
		thirdClassify = currClassifyItem
	} else {
		firstClassify = parentClassifyItem
		secondClassify = currClassifyItem
	}

	flowObj := report_approve.ReportApproveFlow{}

	// 获取父级的审批流
	existCond := fmt.Sprintf(` AND %s = ? AND %s = ? `, report_approve.ReportApproveFlowCols.ReportType, report_approve.ReportApproveFlowCols.ClassifyFirstId)
	existPars := make([]interface{}, 0)
	existPars = append(existPars, report_approve.FlowReportTypeChinese, firstClassify.Id)

	// 如果这是第三级,那么说明只需要查找第二级的审批配置就好了
	if thirdClassify != nil {
		existCond = fmt.Sprintf(`%s AND %s = ?`, existCond, report_approve.ReportApproveFlowCols.ClassifySecondId)
		existPars = append(existPars, secondClassify.Id)
	}
	//if thirdClassify != nil {
	//	existCond = fmt.Sprintf(`%s AND %s = ?`, existCond, report_approve.ReportApproveFlowCols.ClassifyThirdId)
	//	existPars = append(existPars, thirdClassify.Id)
	//}

	parentFlow, err := flowObj.GetItemByCondition(existCond, existPars, "")
	if err != nil {
		// 如果没有配置审批流,那么就直接返回
		if utils.IsErrNoRow(err) {
			err = nil
		}
		return
	}

	// 获取父级的审批节点
	nodeObj := report_approve.ReportApproveNode{}
	nodeCond := fmt.Sprintf(` AND %s = ? AND %s = ?`, report_approve.ReportApproveNodeCols.ReportApproveFlowId, report_approve.ReportApproveNodeCols.CurrVersion)
	nodePars := make([]interface{}, 0)
	nodePars = append(nodePars, parentFlow.ReportApproveFlowId, parentFlow.CurrVersion)
	parentNodeList, err := nodeObj.GetItemsByCondition(nodeCond, nodePars, []string{}, "")
	if err != nil {
		return
	}

	// 新审批流
	currFlow := &report_approve.ReportApproveFlow{
		ReportApproveFlowId: 0,
		FlowName:            currClassifyItem.ClassifyName,
		ReportType:          parentFlow.ReportType,
		ClassifyFirstId:     firstClassify.Id,
		ClassifySecondId:    secondClassify.Id,
		//ClassifyThirdId:     0,
		CurrVersion: 1,
		Enabled:     1,
		CreateTime:  time.Now().Local(),
		ModifyTime:  time.Now().Local(),
	}
	if thirdClassify != nil {
		currFlow.ClassifyThirdId = thirdClassify.Id
	}

	// 新审批流的节点
	nodeItems := make([]*report_approve.ReportApproveNode, 0)
	for _, v := range parentNodeList {
		n := &report_approve.ReportApproveNode{
			//ReportApproveNodeId: 0,
			//ReportApproveFlowId: 0,
			PrevNodeId:  0,
			NextNodeId:  0,
			NodeType:    v.NodeType,
			ApproveType: v.ApproveType,
			Users:       v.Users,
			CurrVersion: 1,
			CreateTime:  time.Now().Local(),
		}
		nodeItems = append(nodeItems, n)
	}

	// 新增审批流和节点
	err = flowObj.CreateFlowAndNodes(currFlow, nodeItems)
	if err != nil {
		return
	}

	parentFlow.Enabled = 0
	err = parentFlow.Update([]string{"Enabled"})

	return
}

// EditReportClassify
// @Description: 编辑报告分类
// @author: Roc
// @datetime 2024-06-17 13:31:33
// @param classifyId int
// @param classifyName string
// @param chartPermissionIdList []int
// @return err error
// @return errMsg string
// @return isSendEmail bool
func EditReportClassify(classifyId int, classifyName string, chartPermissionIdList []int) (err error, errMsg string, isSendEmail bool) {
	isSendEmail = true
	errMsg = `修改失败`

	item, err := models.GetClassifyById(classifyId)
	if err != nil {
		errMsg = "获取分类信息失败"
		if utils.IsErrNoRow(err) {
			errMsg = "分类不存在, 或已被删除"
			isSendEmail = false
		}
		return
	}
	originName := item.ClassifyName

	// 重名校验
	existName, e := models.GetClassifyByName(classifyName, item.ParentId)
	if e != nil && !utils.IsErrNoRow(e) {
		errMsg = "获取信息失败"
		err = errors.New("获取重名分类失败, Err: " + err.Error())
		return
	}
	if existName != nil && existName.Id > 0 && existName.Id != item.Id {
		errMsg = "分类名称:" + classifyName + "已存在"
		err = errors.New(errMsg)
		isSendEmail = false
		return
	}
	item.ClassifyName = classifyName

	// ETA1.8.3:不允许修改上级分类  2024-6-17 13:21:01
	//item.ParentId = req.ParentId
	item.ModifyTime = time.Now().Local()
	cols := make([]string, 0)
	cols = append(cols, "ClassifyName", "ModifyTime")
	err = item.UpdateClassify(cols)
	if err != nil {
		return
	}

	err = models.EditChartPermissionSearchKeyWordMappingMulti(item.ClassifyName, chartPermissionIdList, item.Id)
	if err != nil {
		errMsg = "修改分类权限失败"
		return
	}

	// 修改CRM权限
	go func() {
		_ = EditClassifyChartPermissionSync(item.ClassifyName, item.Id)
	}()

	// TODO 修改分类的关联品种时,历史报告中关联的品种怎么处理?
	// 更新报告分类名称/父级分类后
	go func() {
		_ = AfterUpdateClassifyNameOrParent(item.Id, item.ParentId, item.ParentId, originName, item.ClassifyName, item.Level)
	}()

	return
}

// GetClassifyTreeRecursive 递归获取分类树形结构
func GetClassifyTreeRecursive(list []*models.ClassifyItem, parentId int) []*models.ClassifyItem {
	res := make([]*models.ClassifyItem, 0)
	for _, v := range list {
		if v.ParentId == parentId {
			v.Child = GetClassifyTreeRecursive(list, v.Id)
			res = append(res, v)
		}
	}
	return res
}

// GetParentClassifyListByParentIdList
// @Description: 递归获取父级分类信息,正常来讲只有三次
// @author: Roc
// @datetime 2024-06-19 13:23:33
// @param parentClassifyIdList []int
// @return list []*models.ClassifyList
// @return err error
func GetParentClassifyListByParentIdList(parentClassifyIdList []int) (list []*models.ClassifyList, err error) {
	num := len(parentClassifyIdList)
	if num <= 0 {
		return
	}
	list, err = models.GetClassifyListByParentIdList(parentClassifyIdList)
	if err != nil {
		return
	}

	// 是否还有上级
	{
		currParentClassifyIdList := make([]int, 0)
		for _, v := range list {
			if v.ParentId > 0 {
				currParentClassifyIdList = append(currParentClassifyIdList, v.ParentId)
			}
		}

		if len(currParentClassifyIdList) > 0 {
			tmpList, tmpErr := GetParentClassifyListByParentIdList(currParentClassifyIdList)
			if tmpErr != nil {
				err = tmpErr
				return
			}
			list = append(tmpList, list...)
		}
	}

	return
}

// GetClassifyListTreeRecursive
// @Description: 递归获取分类树形结构
// @author: Roc
// @datetime 2024-06-19 13:23:28
// @param list []*models.ClassifyList
// @param parentId int
// @return []*models.ClassifyList
func GetClassifyListTreeRecursive(list []*models.ClassifyList, parentId int) []*models.ClassifyList {
	res := make([]*models.ClassifyList, 0)
	for _, v := range list {
		if v.ParentId == parentId {
			v.Child = GetClassifyListTreeRecursive(list, v.Id)
			res = append(res, v)
		}
	}

	// 前端的JP需要我这么返回
	if len(res) <= 0 {
		res = nil
	}

	return res
}

// BySortAndCreateTime 用来排序,先按Sort字段升序排序,若Sort相同,则按照CreateTime字段升序排序。
type BySortAndCreateTime []*models.ClassifyList

func (a BySortAndCreateTime) Len() int {
	return len(a)
}

func (a BySortAndCreateTime) Swap(i, j int) {
	a[i], a[j] = a[j], a[i]
}

func (a BySortAndCreateTime) Less(i, j int) bool {
	if a[i].Sort == a[j].Sort {
		return a[i].CreateTime.Before(a[j].CreateTime)
	}
	return a[i].Sort < a[j].Sort
}

// SortClassifyListBySortAndCreateTime sorts the ClassifyList slice by Sort and then CreateTime in ascending order.
func SortClassifyListBySortAndCreateTime(classifyList []*models.ClassifyList) {
	sort.Sort(BySortAndCreateTime(classifyList))
}

// MarkEnableDeleteClassify 标记是否可以删除分类
func MarkEnableDeleteClassify(classifyList []*models.ClassifyList) (err error) {
	if len(classifyList) == 0 {
		return
	}
	classifyIds := make([]int, 0)
	for _, v := range classifyList {
		classifyIds = append(classifyIds, v.Id)
	}
	// 检查是否有报告
	reportList, err := models.GetExistReportClassifyIdByClassifyIds(classifyIds)
	if err != nil {
		return
	}

	// 查询该分类是否关联了审批流
	flowOb := new(report_approve.ReportApproveFlow)
	flowCond := fmt.Sprintf(` AND %s = ? AND ( %s IN (`+utils.GetOrmInReplace(len(classifyIds))+`) OR %s IN (`+utils.GetOrmInReplace(len(classifyIds))+`) OR %s IN (`+utils.GetOrmInReplace(len(classifyIds))+`))`,
		report_approve.ReportApproveFlowCols.ReportType,
		report_approve.ReportApproveFlowCols.ClassifyFirstId,
		report_approve.ReportApproveFlowCols.ClassifySecondId,
		report_approve.ReportApproveFlowCols.ClassifyThirdId,
	)
	flowPars := make([]interface{}, 0)
	flowPars = append(flowPars, report_approve.FlowReportTypeChinese, classifyIds, classifyIds, classifyIds)
	flowList, err := flowOb.GetItemsByCondition(flowCond, flowPars, []string{"classify_first_id", "classify_second_id", "classify_third_id"}, "")
	if err != nil {
		return
	}

	disableDeleteClassifyMap := make(map[int]struct{})
	// 记录关联报告的分类
	for _, v := range reportList {
		if v.ClassifyIdFirst > 0 {
			disableDeleteClassifyMap[v.ClassifyIdFirst] = struct{}{}
		}
		if v.ClassifyIdSecond > 0 {
			disableDeleteClassifyMap[v.ClassifyIdSecond] = struct{}{}
		}
		if v.ClassifyIdThird > 0 {
			disableDeleteClassifyMap[v.ClassifyIdThird] = struct{}{}
		}
	}
	// 记录关联审批流的分类
	for _, v := range flowList {
		if v.ClassifyFirstId > 0 {
			disableDeleteClassifyMap[v.ClassifyFirstId] = struct{}{}
		}
		if v.ClassifySecondId > 0 {
			disableDeleteClassifyMap[v.ClassifySecondId] = struct{}{}
		}
		if v.ClassifyThirdId > 0 {
			disableDeleteClassifyMap[v.ClassifyThirdId] = struct{}{}
		}
	}
	for _, v := range classifyList {
		if _, ok := disableDeleteClassifyMap[v.Id]; !ok {
			v.IsEnableDelete = 1
		}
	}

	return
}

// DealBug6445 处理禅道bug6445,对数据进行补偿刷新
func DealBug6445() error {
	var condition string
	var pars []interface{}
	reportList, err := models.FindReportListByCondition(condition, pars)
	if err != nil {
		return err
	}

	for _, report := range reportList {
		oldClassifyIdThird := report.ClassifyIdThird
		oldClassifyNameThird := report.ClassifyNameThird
		classifyIdList := []int{report.ClassifyIdSecond, report.ClassifyIdThird}

		// 判断当前分类id的父id是否一样,如果系统则将3级分类置为0
		classifies, err := models.GetClassifyListByIdList(classifyIdList)
		if err != nil {
			return err
		}
		if len(classifies) >= 2 {
			if classifies[0].ParentId == classifies[1].ParentId && classifies[0].ParentId != 0 {
				report.ClassifyIdThird = 0
				report.ClassifyNameThird = ""
				err := report.UpdateReport([]string{"classify_id_third", "classify_name_third"})
				if err != nil {
					return err
				}
				logs.Info("update report id: %d, classify_id_third: %d, classify_name_third: %s", report.Id, oldClassifyIdThird, oldClassifyNameThird)
			}
		}
	}
	return nil
}