using RackPeek.Domain.Helpers; using RackPeek.Domain.Persistence; using RackPeek.Domain.Resources; namespace RackPeek.Domain.UseCases; public interface IAddResourceUseCase : IResourceUseCase where T : Resource { Task ExecuteAsync(string name, string? runsOn = null); } public class AddResourceUseCase(IResourceCollection repo) : IAddResourceUseCase where T : Resource { public async Task ExecuteAsync(string name, string? runsOn = null) { name = Normalize.HardwareName(name); ThrowIfInvalid.ResourceName(name); var existingResource = await repo.GetByNameAsync(name); if (existingResource != null) throw new ConflictException($"Resource '{name}' ({existingResource.Kind}) already exists."); if (runsOn != null) { runsOn = Normalize.HardwareName(runsOn); ThrowIfInvalid.ResourceName(runsOn); var parentResource = await repo.GetByNameAsync(runsOn); if (parentResource == null) throw new NotFoundException($"Resource '{runsOn}' not found."); if (!Resource.CanRunOn(parentResource)) throw new InvalidOperationException( $" {Resource.GetKind()} cannot run on {parentResource.Kind} '{runsOn}'."); } var resource = Activator.CreateInstance(); resource.Name = name; resource.RunsOn = runsOn; await repo.AddAsync(resource); } }