package role

import (
	"github.com/veypi/vbase/cfg"
	"github.com/veypi/vbase/models"
	"github.com/veypi/vigo"
	"gorm.io/gorm"
)

type GetUsersReq struct {
	RoleID   string `src:"path@id" desc:"Role ID"`
	Page     int    `src:"query" default:"1" desc:"Page number"`
	PageSize int    `src:"query" default:"50" desc:"Page size"`
}

type UsersResponse struct {
	Items []models.User `json:"items"`
	Total int64         `json:"total"`
}

// getUsers 获取角色下的用户列表（分页）
func getUsers(x *vigo.X, req *GetUsersReq) (*UsersResponse, error) {
	var role models.Role
	if err := cfg.DB().First(&role, "id = ?", req.RoleID).Error; err != nil {
		return nil, vigo.ErrNotFound
	}

	var total int64
	cfg.DB().Model(&models.UserRole{}).Where("role_id = ?", req.RoleID).Count(&total)

	var users []models.User
	offset := (req.Page - 1) * req.PageSize
	cfg.DB().Debug().
		Joins("JOIN vb_user_roles ON vb_user_roles.user_id = vb_users.id").
		Where("vb_user_roles.role_id = ?", req.RoleID).
		Offset(offset).Limit(req.PageSize).
		Find(&users)

	return &UsersResponse{Items: users, Total: total}, nil
}

type UpdateUsersReq struct {
	RoleID  string   `src:"path@id" desc:"Role ID"`
	UserIDs []string `json:"user_ids" src:"json" desc:"List of User IDs"`
}

// updateUsers 批量设置角色的用户
func updateUsers(x *vigo.X, req *UpdateUsersReq) error {
	var role models.Role
	if err := cfg.DB().First(&role, "id = ?", req.RoleID).Error; err != nil {
		return vigo.ErrNotFound
	}

	if role.IsSystem {
		return vigo.NewError("cannot modify users of system role").WithCode(40300)
	}

	return cfg.DB().Transaction(func(tx *gorm.DB) error {
		// 删除不在新列表中的关联
		if err := tx.Where("role_id = ? AND user_id NOT IN ?", req.RoleID, req.UserIDs).
			Delete(&models.UserRole{}).Error; err != nil {
			return err
		}

		// 添加新关联（跳过已存在的）
		for _, uid := range req.UserIDs {
			var count int64
			tx.Model(&models.UserRole{}).
				Where("role_id = ? AND user_id = ?", req.RoleID, uid).
				Count(&count)
			if count == 0 {
				if err := tx.Create(&models.UserRole{
					RoleID: req.RoleID,
					UserID: uid,
				}).Error; err != nil {
					return err
				}
			}
		}
		return nil
	})
}
