package user_role

import (
	"context"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/ent"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/ent/role"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/ent/user"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/internal/svc"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/internal/utils/entx"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/internal/utils/hander"
	"git.noahlan.cn/n-admin/n-admin-server/rpc/core/types/core"
	"git.noahlan.cn/noahlan/ntool-biz/core/nstatus/code"
	"git.noahlan.cn/noahlan/ntool-biz/core/nstatus/msg"
)

type UserBindRoleLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewUserBindRoleLogic(ctx context.Context, svcCtx *svc.ServiceContext) *UserBindRoleLogic {
	return &UserBindRoleLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// User-Role Relationship Management
func (l *UserBindRoleLogic) UserBindRole(in *core.UserRoleReq) (*core.BaseResp, error) {
	if err := entx.WithTx(l.ctx, l.svcCtx.DB, func(tx *ent.Tx) error {
		updated := tx.User.Update().Where(user.IDEQ(in.UserId))
		updateRoleIds := make([]*ent.Role, 0)
		if len(in.RoleCodes) > 0 {
			tmpDb, err := tx.Role.Query().
				Select(role.FieldID, role.FieldCode).
				Where(role.CodeIn(in.RoleCodes...)).
				All(l.ctx)
			if err != nil {
				return hander.HandleEntErr(err, in)
			}
			updateRoleIds = append(updateRoleIds, tmpDb...)
		}
		if len(in.RoleIds) > 0 {
			tmpDb, err := tx.Role.Query().
				Select(role.FieldID, role.FieldCode).
				Where(role.IDIn(in.RoleIds...)).
				All(l.ctx)
			if err != nil {
				return hander.HandleEntErr(err, in)
			}
			updateRoleIds = append(updateRoleIds, tmpDb...)
		}

		updated.ClearRoles()
		updated.AddRoles(updateRoleIds...)

		err := updated.Exec(l.ctx)
		if err != nil {
			return hander.HandleEntErr(err, in)
		}
		return nil
	}); err != nil {
		return nil, err
	}

	return &core.BaseResp{
		Code: code.StatusOK,
		Msg:  msg.UpdateSuccess,
	}, nil
}
