package edbmonitor

import (
	"errors"
	edbmonitor "eta/eta_api/models/edb_monitor"
	"eta/eta_api/models/edb_monitor/request"
	"eta/eta_api/models/edb_monitor/response"
	"eta/eta_api/utils"
	"fmt"
	"time"
)

func GetEdbMonitorClassifyTree() (resp []*response.EdbMonitorClassifyTree, msg string, err error) {
	classifyList, err := edbmonitor.GetEdbMonitorClassifyList()
	if err != nil {
		msg = "获取分类列表失败"
		return
	}
	resp = generateClassifyTree(classifyList, 0)
	return
}

func SaveEdbMonitorClassify(req request.EdbMonitorClassifySaveReq) (msg string, err error) {
	childClassify, er := edbmonitor.GetChildEdbMonitorClassifyById(req.ParentId)
	if er != nil {
		msg = "分类信息保存失败"
		err = fmt.Errorf("get parent classify err:%w", er)
		return
	}
	var parentClassify *edbmonitor.EdbMonitorClassify
	if req.ParentId > 0 {
		parentClassify, er = edbmonitor.GetEdbMonitorClassifyById(req.ParentId)
		if er != nil {
			if utils.IsErrNoRow(er) {
				msg = "父级分类不存在"
				err = errors.New("parent classify not exist")
				return
			}
			msg = "分类信息保存失败"
			err = fmt.Errorf("get parent classify err:%w", er)
			return
		}
	}
	var rootId int
	if parentClassify != nil {
		rootId = parentClassify.RootId
		if rootId == 0 {
			rootId = parentClassify.ParentId
		}
		if rootId == 0 {
			rootId = parentClassify.ClassifyId
		}
	}

	if req.ClassifyId > 0 {
		classifyInfo, er := edbmonitor.GetEdbMonitorClassifyById(req.ClassifyId)
		if er != nil {
			if utils.IsErrNoRow(er) {
				msg = "分类不存在"
				return
			}
			msg = "分类信息保存失败"
			return
		}
		if classifyInfo.Level != req.Level {
			msg = "分类层级不能修改"
			return
		}
		var updateCols []string
		if classifyInfo.ClassifyName != req.ClassifyName {
			classifyInfo.ClassifyName = req.ClassifyName
			updateCols = append(updateCols, "classify_name")
		}
		if classifyInfo.ParentId != req.ParentId {
			classifyInfo.ParentId = req.ParentId
			updateCols = append(updateCols, "parent_id")

			maxSort, er := edbmonitor.GetEdbMonitorClassifyMaxSortByParentId(classifyInfo.ParentId)
			if er != nil {
				msg = "分类信息保存失败"
				err = fmt.Errorf("get max sort err:%w", er)
				return
			}
			classifyInfo.Sort = maxSort + 1
			updateCols = append(updateCols, "sort")
		}

		for _, v := range childClassify {
			if v.ClassifyName == req.ClassifyName {
				msg = "分类名称重复"
				err = errors.New("classify name repeat")
				return
			}
		}
		childClassifyIds, er := edbmonitor.GetChildEdbMonitorClassifyIdById(req.ClassifyId)
		if er != nil {
			msg = "分类信息保存失败"
			err = fmt.Errorf("get child classify id err:%w", er)
			return
		}

		if classifyInfo.RootId != rootId {
			classifyInfo.RootId = rootId
			updateCols = append(updateCols, "root_id")

		}
		err = classifyInfo.Update(updateCols, childClassifyIds)
		if err != nil {
			msg = "分类信息保存失败"
			return
		}
	} else {
		for _, v := range childClassify {
			if v.ClassifyName == req.ClassifyName {
				msg = "分类名称重复"
				err = errors.New("classify name repeat")
				return
			}
		}

		maxSort, er := edbmonitor.GetEdbMonitorClassifyMaxSortByParentId(req.ParentId)
		if er != nil {
			msg = "分类信息保存失败"
			err = fmt.Errorf("get max sort err:%w", er)
			return
		}

		tmp := new(edbmonitor.EdbMonitorClassify)
		tmp.ClassifyName = req.ClassifyName
		tmp.ParentId = req.ParentId
		tmp.RootId = rootId
		tmp.Level = req.Level
		tmp.Sort = maxSort + 1
		tmp.CreateTime = time.Now()
		_, er = tmp.Insert()
		if er != nil {
			msg = "分类信息保存失败"
			err = fmt.Errorf("insert classify err:%w", er)
			return
		}
	}

	return
}

func DeleteEdbMonitorClassify(req request.EdbMonitorClassifyDeleteReq) (msg string, err error) {
	classifyInfo, er := edbmonitor.GetEdbMonitorClassifyById(req.ClassifyId)
	if er != nil {
		if utils.IsErrNoRow(er) {
			msg = "分类不存在"
			return
		}
		msg = "分类信息删除失败"
		return
	}
	var classifyIds []int
	switch classifyInfo.Level {
	case 1:
		classifyList, er := edbmonitor.GetChildEdbMonitorClassifyByRootId(classifyInfo.ClassifyId)
		if er != nil {
			msg = "分类删除失败"
			err = fmt.Errorf("get child classify by root err:%w", er)
			return
		}
		classifyIds = append(classifyIds, classifyInfo.ClassifyId)
		for _, v := range classifyList {
			classifyIds = append(classifyIds, v.ClassifyId)
		}
	case 2:
		classifyList, er := edbmonitor.GetChildEdbMonitorClassifyById(classifyInfo.ClassifyId)
		if er != nil {
			msg = "分类删除失败"
			err = fmt.Errorf("get child classify err:%w", er)
			return
		}
		classifyIds = append(classifyIds, classifyInfo.ClassifyId)
		for _, v := range classifyList {
			classifyIds = append(classifyIds, v.ClassifyId)
		}
	case 3:
		classifyIds = append(classifyIds, classifyInfo.ClassifyId)
	}

	count, er := edbmonitor.GetEdbMonitorInfoCountByClassifyId(classifyIds)
	if er != nil {
		msg = "分类删除失败"
		err = fmt.Errorf("get classify info count err:%w", er)
		return
	}
	if count > 0 {
		msg = "分类下存在关联预警,不能删除"
		err = fmt.Errorf("分类下存在关联预警,不能删除")
		return
	}
	err = edbmonitor.DeleteEdbMonitorClassifyByIdList(classifyIds)
	if err != nil {
		msg = "分类删除失败"
		return
	}
	return
}

// MoveEdbMonitorClassify 移动分类
func MoveEdbMonitorClassify(req request.MoveEdbMonitorClassifyReq) (msg string, err error) {

	classifyInfo, er := edbmonitor.GetEdbMonitorClassifyById(req.ClassifyId)
	if er != nil {
		err = er
		if utils.IsErrNoRow(er) {
			msg = "分类不存在,请刷新页面"
			return
		}
		msg = "移动失败"
		return
	}

	// 校验移动的父级目录下是否有重名分类
	exists, er := edbmonitor.GetEdbMonitorClassifyByParentIdAndName(req.ParentClassifyId, classifyInfo.ClassifyName, req.ClassifyId)
	if er != nil && !utils.IsErrNoRow(er) {
		msg = "移动失败"
		err = er
		return
	}
	if exists != nil {
		msg = "移动失败,分类名称已存在"
		err = errors.New("classify name repeat")
		return
	}

	updateCol := make([]string, 0)

	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
	var parentRootId int
	if classifyInfo.ParentId != req.ParentClassifyId && req.ParentClassifyId != 0 {
		parentClassify, er := edbmonitor.GetEdbMonitorClassifyById(req.ParentClassifyId)
		if er != nil {
			err = er
			if utils.IsErrNoRow(er) {
				msg = "父级分类不存在,请刷新页面"
				return
			}
			msg = "移动失败"
			return
		}
		if parentClassify.Level > 2 {
			msg = "移动失败,不能移动到子分类"
			err = errors.New("move to child classify")
			return
		}
		if parentClassify.Level+1 != classifyInfo.Level {
			msg = "移动失败,只能移动到同一层级的分类"
			err = errors.New("move to child classify")
			return
		}
		parentRootId = parentClassify.RootId
		classifyInfo.ParentId = parentClassify.ClassifyId
		classifyInfo.Level = parentClassify.Level + 1
		updateCol = append(updateCol, "parent_id", "level")
	}
	//如果有传入 上一个兄弟节点分类id
	if req.PrevClassifyId > 0 {
		//上一个兄弟节点
		prevClassify, er := edbmonitor.GetEdbMonitorClassifyById(req.PrevClassifyId)
		if er != nil {
			msg = "移动失败"
			err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:%w", er)
			return
		}

		//如果是移动在两个兄弟节点之间
		if req.NextClassifyId > 0 {
			//下一个兄弟节点
			nextClassify, er := edbmonitor.GetEdbMonitorClassifyById(req.NextClassifyId)
			if er != nil {
				msg = "移动失败"
				err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:%w", er)
				return
			}
			//如果上一个兄弟与下一个兄弟的排序权重是一致的,那么需要将下一个兄弟(以及下个兄弟的同样排序权重)的排序权重+2,自己变成上一个兄弟的排序权重+1
			if prevClassify.Sort == nextClassify.Sort || prevClassify.Sort == classifyInfo.Sort {
				//变更兄弟节点的排序
				updateSortStr := `sort + 2`
				_ = edbmonitor.UpdateEdbMonitorClassifySortByParentId(prevClassify.ParentId, prevClassify.ClassifyId, prevClassify.Sort, updateSortStr)
			} else {
				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
				if nextClassify.Sort-prevClassify.Sort == 1 {
					//变更兄弟节点的排序
					updateSortStr := `sort + 1`
					_ = edbmonitor.UpdateEdbMonitorClassifySortByParentId(prevClassify.ParentId, 0, prevClassify.Sort, updateSortStr)
				}
			}
		}

		classifyInfo.Sort = prevClassify.Sort + 1
		updateCol = append(updateCol, "Sort")

	} else {
		firstClassify, er := edbmonitor.GetFirstEdbMonitorClassifyByParentId(classifyInfo.ParentId)
		if er != nil && !utils.IsErrNoRow(er) {
			msg = "移动失败"
			err = fmt.Errorf("获取父级分类下的排序第一条的分类信息失败,Err:%w", er)
			return
		}

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

		classifyInfo.Sort = 0 //那就是排在第一位
		updateCol = append(updateCol, "Sort")
	}
	var classifyIds []int
	if classifyInfo.Level == 2 {
		classifyIds, er = edbmonitor.GetChildEdbMonitorClassifyIdById(classifyInfo.ClassifyId)
		if er != nil {
			msg = "分类移动失败"
			err = fmt.Errorf("获取子分类id失败 err:%w", er)
			return
		}
	}

	if len(updateCol) > 0 {
		if parentRootId != 0 {
			classifyInfo.RootId = parentRootId
		} else {
			classifyInfo.RootId = req.ParentClassifyId
		}
		updateCol = append(updateCol, "root_id")
		err = classifyInfo.Update(updateCol, classifyIds)
		if err != nil {
			msg = "移动失败"
			return
		}
	}

	return
}

func generateClassifyTree(classifyList []*edbmonitor.EdbMonitorClassify, parentId int) []*response.EdbMonitorClassifyTree {
	res := make([]*response.EdbMonitorClassifyTree, 0)
	for _, v := range classifyList {
		if v.ParentId == parentId {
			tmp := new(response.EdbMonitorClassifyTree)
			tmp.ClassifyId = v.ClassifyId
			tmp.ClassifyName = v.ClassifyName
			tmp.Level = v.Level
			tmp.Children = generateClassifyTree(classifyList, v.ClassifyId)
			res = append(res, tmp)
		}
	}
	return res
}