using ColaFlow.Modules.Identity.Application.Services; using ColaFlow.Modules.Identity.Domain.Aggregates.Tenants; using ColaFlow.Modules.Identity.Domain.Aggregates.Users; using ColaFlow.Modules.Identity.Domain.Repositories; using MediatR; namespace ColaFlow.Modules.Identity.Application.Commands.RegisterTenant; public class RegisterTenantCommandHandler : IRequestHandler { private readonly ITenantRepository _tenantRepository; private readonly IUserRepository _userRepository; private readonly IJwtService _jwtService; private readonly IPasswordHasher _passwordHasher; private readonly IRefreshTokenService _refreshTokenService; private readonly IUserTenantRoleRepository _userTenantRoleRepository; public RegisterTenantCommandHandler( ITenantRepository tenantRepository, IUserRepository userRepository, IJwtService jwtService, IPasswordHasher passwordHasher, IRefreshTokenService refreshTokenService, IUserTenantRoleRepository userTenantRoleRepository) { _tenantRepository = tenantRepository; _userRepository = userRepository; _jwtService = jwtService; _passwordHasher = passwordHasher; _refreshTokenService = refreshTokenService; _userTenantRoleRepository = userTenantRoleRepository; } public async Task Handle( RegisterTenantCommand request, CancellationToken cancellationToken) { // 1. Validate slug uniqueness var slug = TenantSlug.Create(request.TenantSlug); var slugExists = await _tenantRepository.ExistsBySlugAsync(slug, cancellationToken); if (slugExists) { throw new InvalidOperationException($"Tenant slug '{request.TenantSlug}' is already taken"); } // 2. Create tenant var plan = Enum.Parse(request.SubscriptionPlan); var tenant = Tenant.Create( TenantName.Create(request.TenantName), slug, plan); await _tenantRepository.AddAsync(tenant, cancellationToken); // 3. Create admin user with hashed password var hashedPassword = _passwordHasher.HashPassword(request.AdminPassword); var adminUser = User.CreateLocal( TenantId.Create(tenant.Id), Email.Create(request.AdminEmail), hashedPassword, FullName.Create(request.AdminFullName)); await _userRepository.AddAsync(adminUser, cancellationToken); // 4. Assign TenantOwner role to admin user var tenantOwnerRole = UserTenantRole.Create( UserId.Create(adminUser.Id), TenantId.Create(tenant.Id), TenantRole.TenantOwner); await _userTenantRoleRepository.AddAsync(tenantOwnerRole, cancellationToken); // 5. Generate JWT token with role var accessToken = _jwtService.GenerateToken(adminUser, tenant, TenantRole.TenantOwner); // 6. Generate refresh token var refreshToken = await _refreshTokenService.GenerateRefreshTokenAsync( adminUser, ipAddress: null, userAgent: null, cancellationToken); // 6. Return result return new RegisterTenantResult( new Dtos.TenantDto { Id = tenant.Id, Name = tenant.Name.Value, Slug = tenant.Slug.Value, Status = tenant.Status.ToString(), Plan = tenant.Plan.ToString(), SsoEnabled = tenant.SsoConfig != null, SsoProvider = tenant.SsoConfig?.Provider.ToString(), CreatedAt = tenant.CreatedAt, UpdatedAt = tenant.UpdatedAt ?? tenant.CreatedAt }, new Dtos.UserDto { Id = adminUser.Id, TenantId = tenant.Id, Email = adminUser.Email.Value, FullName = adminUser.FullName.Value, Status = adminUser.Status.ToString(), AuthProvider = adminUser.AuthProvider.ToString(), IsEmailVerified = adminUser.EmailVerifiedAt.HasValue, CreatedAt = adminUser.CreatedAt }, accessToken, refreshToken); } }