using Microsoft.EntityFrameworkCore; /// /// One-shot / idempotent registration of a clinical site + ward gateway with /// caller-supplied IDs. Production cannot rely on GatewayRegistrySeeder (demo /// data is gated off); the gateway authenticates using Gateway:GatewayId / /// Gateway:SiteId from its environment, so those GUIDs must exist in the API DB. /// /// Usage: /// dotnet VigilCareClinicalAPI.dll register-gateway \ /// --site-id <guid> --gateway-id <guid> \ /// --site-code SITE-01 --site-name "General Hospital" \ /// --gateway-code GW-ICU-1 --department ICU \ /// [--address "123 Main St"] /// /// Re-running with the same IDs is a no-op success. Conflicting codes or IDs fail. /// public static class RegisterGatewayCommand { public static async Task RunAsync(IServiceProvider services, string[] args) { var siteId = RequireGuid(args, "--site-id"); var gatewayId = RequireGuid(args, "--gateway-id"); var siteCode = RequireArg(args, "--site-code").Trim(); var siteName = RequireArg(args, "--site-name").Trim(); var gatewayCode = RequireArg(args, "--gateway-code").Trim(); var department = RequireArg(args, "--department").Trim(); var address = GetArg(args, "--address")?.Trim(); using var scope = services.CreateScope(); var db = scope.ServiceProvider.GetRequiredService(); var existingGateway = await db.WardGateways .Include(g => g.Site) .FirstOrDefaultAsync(g => g.Id == gatewayId); if (existingGateway is not null) { if (existingGateway.SiteId != siteId || !string.Equals(existingGateway.GatewayCode, gatewayCode, StringComparison.Ordinal) || !string.Equals(existingGateway.Department, department, StringComparison.Ordinal)) { Console.Error.WriteLine( $"Gateway id {gatewayId} already exists with different site/code/department. Aborting."); return 1; } Console.WriteLine( $"Gateway '{existingGateway.GatewayCode}' (id={gatewayId}) already registered — nothing to do."); return 0; } var existingSite = await db.ClinicalSites.FirstOrDefaultAsync(s => s.Id == siteId); if (existingSite is null) { var codeTaken = await db.ClinicalSites.AnyAsync(s => s.SiteCode == siteCode); if (codeTaken) { Console.Error.WriteLine($"Site code '{siteCode}' is already registered under a different id."); return 1; } var site = new ClinicalSite(siteCode, siteName, address); db.Entry(site).Property(nameof(ClinicalSite.Id)).CurrentValue = siteId; db.ClinicalSites.Add(site); Console.WriteLine($"Created site '{siteCode}' (id={siteId})."); } else if (!string.Equals(existingSite.SiteCode, siteCode, StringComparison.Ordinal)) { Console.Error.WriteLine( $"Site id {siteId} already exists as code '{existingSite.SiteCode}', " + $"not '{siteCode}'. Aborting."); return 1; } var duplicateCode = await db.WardGateways.AnyAsync(g => g.SiteId == siteId && g.GatewayCode == gatewayCode); if (duplicateCode) { Console.Error.WriteLine( $"Gateway code '{gatewayCode}' already exists for site {siteId} under a different id."); return 1; } var gateway = new WardGateway(siteId, gatewayCode, department); db.Entry(gateway).Property(nameof(WardGateway.Id)).CurrentValue = gatewayId; db.WardGateways.Add(gateway); await db.SaveChangesAsync(); Console.WriteLine($"Registered gateway '{gatewayCode}' (id={gatewayId}) on site {siteId}."); return 0; } private static Guid RequireGuid(string[] args, string name) { var raw = RequireArg(args, name); if (!Guid.TryParse(raw, out var id) || id == Guid.Empty) throw new ArgumentException($"{name} must be a non-empty GUID."); return id; } private static string RequireArg(string[] args, string name) { var value = GetArg(args, name); if (string.IsNullOrWhiteSpace(value)) throw new ArgumentException($"Missing required argument: {name}"); return value; } private static string? GetArg(string[] args, string name) { for (var i = 0; i < args.Length - 1; i++) { if (string.Equals(args[i], name, StringComparison.OrdinalIgnoreCase)) { var value = args[i + 1]; if (string.IsNullOrWhiteSpace(value) || value.StartsWith("--", StringComparison.Ordinal)) return null; return value; } } return null; } }