package department

import (
	"errors"

	"bsm/full/module/base/mgt/internal/impl"
	"bsm/full/module/base/mgt/internal/libs"
	"bsm/full/module/base/mgt/internal/models"
	"bsm/full/module/base/mgt/internal/types"

	"git.apinb.com/bsm-sdk/core/errcode"
	"git.apinb.com/bsm-sdk/core/infra"
	"git.apinb.com/bsm-sdk/core/printer"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

// SetUser 将用户移入部门（可批量）
func SetUser(c *gin.Context) {
	var request types.DptUserRequest
	if err := c.ShouldBindJSON(&request); err != nil {
		infra.Response.Error(c, errcode.ErrJsonUnmarshal)
		return
	}
	if err := libs.ValidateStruct(&request); err != nil {
		infra.Response.Error(c, errcode.ErrInvalidArgument)
		return
	}

	var dpt models.MgtDepartment
	if err := impl.DBService.Select("id").Where("id = ?", request.DptId).First(&dpt).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			infra.Response.Error(c, errcode.ErrRecordNotFound)
			return
		}
		infra.Response.Error(c, errcode.ErrDB)
		return
	}

	list := make([]models.MgtLinkUserDpt, 0, len(request.UserIds))
	for _, uid := range request.UserIds {
		list = append(list, models.MgtLinkUserDpt{UserId: uid, DptId: request.DptId})
	}
	if err := impl.DBService.Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "user_id"}, {Name: "dpt_id"}},
		DoNothing: true,
	}).Create(&list).Error; err != nil {
		infra.Response.Error(c, errcode.ErrDB)
		return
	}

	printer.Info("用户移入部门成功: dptId=%d, count=%d", request.DptId, len(request.UserIds))
	infra.Response.Success(c, "")
}

// DelUser 将用户移出部门（可批量）
func DelUser(c *gin.Context) {
	var request types.DptUserRequest
	if err := c.ShouldBindJSON(&request); err != nil {
		infra.Response.Error(c, errcode.ErrJsonUnmarshal)
		return
	}
	if err := libs.ValidateStruct(&request); err != nil {
		infra.Response.Error(c, errcode.ErrInvalidArgument)
		return
	}

	result := impl.DBService.Where("dpt_id = ? and user_id in ?", request.DptId, request.UserIds).
		Delete(&models.MgtLinkUserDpt{})
	if result.Error != nil {
		infra.Response.Error(c, errcode.ErrDB)
		return
	}

	printer.Info("用户移出部门成功: dptId=%d, count=%d", request.DptId, result.RowsAffected)
	infra.Response.Success(c, "")
}

// UserFetch 获取部门下用户列表
func UserFetch(c *gin.Context) {
	var (
		request = types.FetchBase{}
		data    = make([]models.MgtDepartment, 0)
		db      = impl.DBService.Model(&models.MgtDepartment{})
	)
	if err := c.ShouldBindJSON(&request); err != nil {
		infra.Response.Error(c, errcode.ErrJsonUnmarshal)
		return
	}
	if err := libs.ValidateStruct(&request); err != nil {
		infra.Response.Error(c, errcode.ErrInvalidArgument)
		return
	}
	if request.ID == 0 {
		printer.Error("获取部门用户参数异常: 部门ID不能为空")
		infra.Response.Error(c, errcode.ErrInvalidArgument)
		return
	}
	db = db.Where("id = ?", request.ID)

	if err := db.Select("id", "identity", "name").Preload("Users", func(db *gorm.DB) *gorm.DB {
		return db.Select("id", "identity", "name")
	}).Find(&data).Error; err != nil {
		infra.Response.Error(c, errcode.ErrDB)
		return
	}
	infra.Response.Success(c, data)
}
