package rbac

import (
	"context"
	"sync"

	"github.com/tidbcloud/account/commons/database"

	"github.com/tidbcloud/account/internel/dao"
	"gorm.io/gorm"

	"github.com/tidbcloud/account/internel/dao/entity"
)

type RbacRoleIface interface {
	CreateRbacRole(ctx context.Context, name string, description string, scopeType entity.ScopeType, displayName string) error
	ListRbacRoles(context.Context) ([]entity.RbacRole, error)
	GetRbacRoleByID(ctx context.Context, rbacRoleID uint64) (*entity.RbacRole, error)
	GetRbacRoleByName(ctx context.Context, name string) (*entity.RbacRole, error)
	UpdateRbacRole(ctx context.Context, rbacRoleID uint64, name string, description string, scopeType entity.ScopeType, displayName string) error
	DeleteRbacRole(ctx context.Context, rbacRoleID uint64) error
}

var (
	rbacRoleInitOnce sync.Once
	rbacRoleSrv      RbacRoleIface
)

func GetRbacRoleSvc() (RbacRoleIface, error) {
	rbacRoleInitOnce.Do(func() {
		rbacRoleSrv = NewRbacRolesSvc(database.DBConn.DB, dao.GetDaoHub())

	})
	return rbacRoleSrv, nil
}

type RbacRoleSvc struct {
	db  *gorm.DB
	hub *dao.DaoHub
}

func NewRbacRolesSvc(db *gorm.DB, hub *dao.DaoHub) RbacRoleIface {
	return &RbacRoleSvc{
		db:  db,
		hub: hub,
	}
}

func (r *RbacRoleSvc) CreateRbacRole(ctx context.Context, name string, description string, scopeType entity.ScopeType, displayName string) error {

	return r.hub.Rbac.CreateRbacRole(ctx, r.db, name, description, scopeType, displayName)
}

func (r *RbacRoleSvc) GetRbacRoleByID(ctx context.Context, rbacRoleId uint64) (*entity.RbacRole, error) {

	return r.hub.Rbac.GetRbacRoleByID(ctx, r.db, rbacRoleId)

}

func (r *RbacRoleSvc) GetRbacRoleByName(ctx context.Context, name string) (*entity.RbacRole, error) {

	return r.hub.Rbac.GetRbacRoleByName(ctx, r.db, name)

}

func (r *RbacRoleSvc) ListRbacRoles(ctx context.Context) ([]entity.RbacRole, error) {

	return r.hub.Rbac.ListRbacRoles(ctx, r.db)
}

func (r *RbacRoleSvc) UpdateRbacRole(ctx context.Context, rbacRoleID uint64, name string, description string, scopeType entity.ScopeType, displayName string) error {

	return r.hub.Rbac.UpdateRbacRole(ctx, r.db, rbacRoleID, name, description, scopeType, displayName)
}

func (r *RbacRoleSvc) DeleteRbacRole(ctx context.Context, rbacRoleID uint64) error {

	return r.hub.Rbac.DeleteRbacRole(ctx, r.db, rbacRoleID)
}
