package services

import (
	"eta/eta_mobile/models"
	"eta/eta_mobile/models/report"
	"eta/eta_mobile/models/system"
	"eta/eta_mobile/utils"
	"fmt"
	"time"
)

// MoveReportChapter
// @Description: 移动报告章节
// @author: Roc
// @datetime 2024-06-06 09:48:52
// @param req *models.ReportChapterMoveReq
// @return err error
// @return errMsg string
func MoveReportChapter(req *models.ReportChapterMoveReq) (err error, errMsg string) {
	ob := new(models.ReportChapter)
	reportChapterId := req.ReportChapterId
	prevReportChapterId := req.PrevReportChapterId
	nextReportChapterId := req.NextReportChapterId

	//如果有传入 上一个兄弟节点分类id
	var (
		reportChapter     *models.ReportChapter
		prevReportChapter *models.ReportChapter
		nextReportChapter *models.ReportChapter

		prevSort int
		nextSort int
	)

	// 移动对象为分类， 判断权限
	reportChapter, err = ob.GetReportChapterById(reportChapterId)
	if err != nil {
		if err.Error() == utils.ErrNoRow() {
			errMsg = "当前报告章节不存在"
			err = fmt.Errorf("获取报告章节信息失败,Err:" + err.Error())
			return
		}
		errMsg = "移动失败"
		err = fmt.Errorf("获取章节信息失败,Err:" + err.Error())
		return
	} else if reportChapter.ReportChapterId == 0 {
		errMsg = "当前报告章节不存在"
		err = fmt.Errorf("获取报告章节信息失败,Err:" + err.Error())
		return
	}

	if prevReportChapterId > 0 {
		prevReportChapter, err = ob.GetReportChapterById(prevReportChapterId)
		if err != nil {
			errMsg = "移动失败"
			err = fmt.Errorf("获取上一个兄弟节点分类信息失败,Err:" + err.Error())
			return
		}
		prevSort = prevReportChapter.Sort
	}

	if nextReportChapterId > 0 {
		//下一个兄弟节点
		nextReportChapter, err = ob.GetReportChapterById(nextReportChapterId)
		if err != nil {
			errMsg = "移动失败"
			err = fmt.Errorf("获取下一个兄弟节点分类信息失败,Err:" + err.Error())
			return
		}
		nextSort = nextReportChapter.Sort
	}

	err, errMsg = moveReportChapter(reportChapter, prevReportChapter, nextReportChapter, reportChapter.ReportId, prevSort, nextSort)
	return
}

// moveReportChapter
// @Description: 移动章节分类
// @author: Roc
// @datetime 2024-06-06 09:48:46
// @param reportChapter *models.ReportChapter
// @param prevReportChapter *models.ReportChapter
// @param nextReportChapter *models.ReportChapter
// @param reportId int
// @param prevSort int
// @param nextSort int
// @return err error
// @return errMsg string
func moveReportChapter(reportChapter, prevReportChapter, nextReportChapter *models.ReportChapter, reportId int, prevSort, nextSort int) (err error, errMsg string) {
	ob := new(models.ReportChapter)
	updateCol := make([]string, 0)

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

				//变更分类
				if prevReportChapter != nil {
					_ = ob.UpdateReportChapterSortByReportId(reportId, prevReportChapter.ReportChapterId, prevReportChapter.Sort, updateSortStr)
				} else {
					_ = ob.UpdateReportChapterSortByReportId(reportId, 0, prevSort, updateSortStr)
				}

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

					//变更分类
					if prevReportChapter != nil {
						_ = ob.UpdateReportChapterSortByReportId(reportId, prevReportChapter.ReportChapterId, prevSort, updateSortStr)
					} else {
						_ = ob.UpdateReportChapterSortByReportId(reportId, 0, prevSort, updateSortStr)
					}

				}
			}
		}

		reportChapter.Sort = prevSort + 1
		reportChapter.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	} else if prevReportChapter == nil && nextReportChapter == nil {
		//处理只拖动到目录里，默认放到目录底部的情况
		var maxSort int
		maxSort, err = ob.GetMaxSortByReportId(reportId)
		if err != nil {
			errMsg = "移动失败"
			err = fmt.Errorf("查询组内排序信息失败,Err:" + err.Error())
			return
		}
		reportChapter.Sort = maxSort + 1 //那就是排在组内最后一位
		reportChapter.ModifyTime = time.Now()
		updateCol = append(updateCol, "Sort", "ModifyTime")
	} else {
		// 拖动到父级分类的第一位
		firstReportChapter, tmpErr := ob.GetFirstReportChapterByReportId(reportId)
		if tmpErr != nil && tmpErr.Error() != utils.ErrNoRow() {
			errMsg = "移动失败"
			err = fmt.Errorf("获取当前报告下，且排序数相同 的排序第一条的数据失败,Err:" + tmpErr.Error())
			return
		}

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

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

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

// CheckChapterAuthByAdminIdList
// @Description: 根据管理员id列表，判断当前用户是否有章节权限
// @author: Roc
// @datetime 2024-06-13 11:03:10
// @param sysUser *system.Admin
// @param createAdminId int
// @param grantAdminIdList []int
// @return isAuth bool
func CheckChapterAuthByAdminIdList(sysUser *system.Admin, createAdminId int, grantAdminIdList []int) (isAuth bool) {
	// 如果是自己创建的报告，那么就有权限
	if sysUser.AdminId == createAdminId {
		isAuth = true
		return
	}
	// 如果本人是超管，那么就有权限
	if utils.IsAdminRole(sysUser.RoleTypeCode) {
		isAuth = true
		return
	}
	// 如果是授权用户，那么就有权限
	if utils.IsCheckInList(grantAdminIdList, sysUser.AdminId) {
		isAuth = true
		return
	}

	return
}

// CheckChapterAuthByReportChapterInfo
// @Description: 根据报告章节信息，判断当前用户是否有章节权限
// @author: Roc
// @datetime 2024-06-13 11:10:46
// @param adminId int
// @param createAdminId int
// @param reportChapterInfo *models.ReportChapter
// @return isAuth bool
// @return err error
func CheckChapterAuthByReportChapterInfo(sysUser *system.Admin, createAdminId int, reportChapterInfo *models.ReportChapter) (isAuth bool, err error) {
	// 如果是自己创建的报告，那么就有权限
	if sysUser.AdminId == createAdminId {
		isAuth = true
		return
	}
	// 如果本人是超管，那么就有权限
	if utils.IsAdminRole(sysUser.RoleTypeCode) {
		isAuth = true
		return
	}

	chapterGrantObj := report.ReportChapterGrant{}
	item, err := chapterGrantObj.GetGrantByIdAndAdmin(reportChapterInfo.ReportChapterId, sysUser.AdminId)
	if err != nil {
		// 如果是没找到数据，那么就是无权限
		if err.Error() == utils.ErrNoRow() {
			err = nil
			return
		}
		// sql报错了
		return
	}
	// 用户id一致就有权限
	if item.AdminId == sysUser.AdminId {
		isAuth = true
	}

	return
}
