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, List? runsOn = null); } public class AddResourceUseCase(IResourceCollection repo) : IAddResourceUseCase where T : Resource { public async Task ExecuteAsync(string name, List? runsOn = null) { name = Normalize.HardwareName(name); ThrowIfInvalid.ResourceName(name); Resource? existingResource = await repo.GetByNameAsync(name); if (existingResource != null) throw new ConflictException($"Resource '{name}' ({existingResource.Kind}) already exists."); if (runsOn != null) foreach (var parent in runsOn) { var normalizedParent = Normalize.HardwareName(parent); ThrowIfInvalid.ResourceName(normalizedParent); Resource? parentResource = await repo.GetByNameAsync(normalizedParent); if (parentResource == null) throw new NotFoundException($"Resource '{normalizedParent}' not found."); if (!Resource.CanRunOn(parentResource)) throw new InvalidOperationException( $" {Resource.GetKind()} cannot run on {parentResource.Kind} '{normalizedParent}'."); } T resource = Activator.CreateInstance(); resource.Name = name; resource.RunsOn = runsOn ?? new List(); await repo.AddAsync(resource); } }