package _interface

import (
	"errors"
	"eta/eta_api/models"
	"eta/eta_api/utils"
	"time"
)

type SingleNodeMoveInterface interface {
	GetNodeInfoById(nodeId int) (nodeInfo *models.NodeInfo, err error)
	UpdateNodeInfoSortByParentIdAndSource(parentNodeId, nodeId, prevNodeSort int, updateSortStr string, nodeType int) (err error)
	GetNodeMaxSort(parentId, nodeType int) (maxSort int, err error)
	GetFirstNodeInfoByParentId(parentId int) (nodeInfo *models.NodeInfo, err error)
}

// MoveSingleNode 移动节点
func MoveSingleNode(sm SingleNodeMoveInterface, req models.SingleMoveNodeReq) (newNodeInfo *models.NodeInfo, updateCol []string, err error, errMsg string) {
	nodeId := req.NodeId
	parentNodeId := req.ParentNodeId
	prevNodeId := req.PrevNodeId
	nextNodeId := req.NextNodeId
	source := req.NodeType

	//首先确定移动的对象是分类还是指标
	//判断上一个节点是分类还是指标
	//判断下一个节点是分类还是指标
	//同时更新分类目录下的分类sort和指标sort
	//更新当前移动的分类或者指标sort

	var parentChartNodeInfo *models.NodeInfo
	if parentNodeId > 0 {
		parentChartNodeInfo, err = sm.GetNodeInfoById(parentNodeId)
		if err != nil {
			errMsg = "移动失败"
			err = errors.New("获取上级分类信息失败,Err:" + err.Error())
			return
		}
	}

	//如果有传入 上一个兄弟节点分类id
	var (
		//nodeInfo *models.NodeInfo
		prevNode *models.NodeInfo
		nextNode *models.NodeInfo
		prevSort int
		nextSort int
	)

	// 移动对象为分类
	nodeInfo, err := sm.GetNodeInfoById(nodeId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "当前分类不存在"
			err = errors.New("获取分类信息失败,Err:" + err.Error())
			return
		}
		errMsg = "移动失败"
		err = errors.New("获取分类信息失败,Err:" + err.Error())
		return
	}

	if prevNodeId > 0 {
		prevNode, err = sm.GetNodeInfoById(prevNodeId)
		if err != nil {
			errMsg = "移动失败"
			err = errors.New("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
			return
		}
		prevSort = prevNode.Sort
	}

	if nextNodeId > 0 {
		//下一个兄弟节点
		nextNode, err = sm.GetNodeInfoById(nextNodeId)
		if err != nil {
			errMsg = "移动失败"
			err = errors.New("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
			return
		}
		nextSort = nextNode.Sort
	}

	newNodeInfo, updateCol, err, errMsg = moveSingleNode(sm, parentChartNodeInfo, nodeInfo, prevNode, nextNode, parentNodeId, prevSort, nextSort, source)
	return
}

// moveSingleNode 移动节点
func moveSingleNode(sm SingleNodeMoveInterface, parentChartNodeInfo, nodeInfo, prevNode, nextNode *models.NodeInfo, parentNodeId, prevSort, nextSort, source int) (newNodeInfo *models.NodeInfo, updateCol []string, err error, errMsg string) {
	updateCol = make([]string, 0)
	newNodeInfo = nodeInfo
	// 移动对象为分类, 判断分类是否存在
	oldParentId := nodeInfo.ParentId
	//oldLevel := nodeInfo.Level
	if oldParentId != parentNodeId {
		// todo 更新子分类对应的level
	}
	//判断上级id是否一致,如果不一致的话,那么需要移动该分类层级
	if nodeInfo.ParentId != parentNodeId && parentNodeId != 0 {
		if nodeInfo.Level != parentChartNodeInfo.Level+1 { //禁止层级调整
			errMsg = "不支持目录层级变更"
			err = errors.New("不支持目录层级变更")
			return
		}
		newNodeInfo.ParentId = parentChartNodeInfo.NodeId
		//nodeInfo.RootId = parentChartNodeInfo.RootId
		newNodeInfo.Level = parentChartNodeInfo.Level + 1
		newNodeInfo.ModifyTime = time.Now()
		//updateCol = append(updateCol, "ParentId", "RootId", "Level", "ModifyTime")
		updateCol = append(updateCol, "ParentId", "Level", "ModifyTime")
	} else if nodeInfo.ParentId != parentNodeId && parentNodeId == 0 {
		errMsg = "不支持目录层级变更"
		err = errors.New("不支持目录层级变更")
		return
	}

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

				//变更分类
				if prevNode != nil {
					_ = sm.UpdateNodeInfoSortByParentIdAndSource(parentNodeId, prevNode.NodeId, prevNode.Sort, updateSortStr, source)
				} else {
					_ = sm.UpdateNodeInfoSortByParentIdAndSource(parentNodeId, 0, prevSort, updateSortStr, source)
				}
			} else {
				//如果下一个兄弟的排序权重正好是上个兄弟节点的下一层,那么需要再加一层了
				if nextSort-prevSort == 1 {
					//变更兄弟节点的排序
					updateSortStr := `sort + 1`

					//变更分类
					if prevNode != nil {
						_ = sm.UpdateNodeInfoSortByParentIdAndSource(parentNodeId, prevNode.NodeId, prevSort, updateSortStr, source)
					} else {
						_ = sm.UpdateNodeInfoSortByParentIdAndSource(parentNodeId, 0, prevSort, updateSortStr, source)
					}
				}
			}
		}

		newNodeInfo.Sort = prevSort + 1
		newNodeInfo.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	} else if prevNode == nil && nextNode == nil && parentNodeId > 0 {
		//处理只拖动到目录里,默认放到目录底部的情况
		var maxSort int
		maxSort, err = sm.GetNodeMaxSort(parentNodeId, source)
		if err != nil {
			errMsg = "移动失败"
			err = errors.New("查询组内排序信息失败,Err:" + err.Error())
			return
		}
		newNodeInfo.Sort = maxSort + 1 //那就是排在组内最后一位
		newNodeInfo.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	} else {
		// 拖动到父级分类的第一位
		firstClassify, tmpErr := sm.GetFirstNodeInfoByParentId(parentNodeId)
		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
			errMsg = "移动失败"
			err = errors.New("获取获取当前父级分类下的排序第一条的分类信息失败,Err:" + tmpErr.Error())
			return
		}

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

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

	// todo 更新层级
	if len(updateCol) > 0 {
		/*err = nodeInfo.Update(updateCol)
		if err != nil {
			errMsg = "移动失败"
			err = errors.New("修改失败,Err:" + err.Error())
			return
		}*/
		// todo 更新对应分类的root_id和层级
	}
	return
}