using Hl7.Fhir.Model; using Microsoft.Extensions.Options; using Task = System.Threading.Tasks.Task; public class FhirReferenceResolver { private readonly IExternalIdentifierService _identifiers; private readonly FhirOptions _options; public FhirReferenceResolver( IExternalIdentifierService identifiers, IOptions options) { _identifiers = identifiers; _options = options.Value; } public async Task ResolvePatientReferenceAsync(ResourceReference reference) { if (reference.Identifier is not null) return await ResolveByIdentifierAsync( ExternalResourceType.Patient, reference.Identifier.System, reference.Identifier.Value, _options.PatientIdentifierSystems); if (FhirMappingHelpers.TryParseResourceReference(reference.Reference, out var type, out var id) && type == "Patient" && Guid.TryParse(id, out var guid)) { return guid; } throw new FhirMappingException( "Patient reference must include a resolvable identifier or UUID.", "required"); } public async Task ResolveEncounterReferenceAsync(ResourceReference reference) { if (reference.Identifier is not null) return await ResolveByIdentifierAsync( ExternalResourceType.Encounter, reference.Identifier.System, reference.Identifier.Value, _options.EncounterIdentifierSystems); if (FhirMappingHelpers.TryParseResourceReference(reference.Reference, out var type, out var id) && type == "Encounter" && Guid.TryParse(id, out var guid)) { return guid; } throw new FhirMappingException( "Encounter reference must include a resolvable identifier or UUID.", "required"); } public (string System, string Value)? ExtractPrimaryIdentifier( IIdentifiable> resource, string[] acceptedSystems) { foreach (var system in acceptedSystems) { var match = resource.Identifier? .FirstOrDefault(i => i.System == system && !string.IsNullOrWhiteSpace(i.Value)); if (match is not null) return (match.System!, match.Value!); } return resource.Identifier? .FirstOrDefault(i => !string.IsNullOrWhiteSpace(i.System) && !string.IsNullOrWhiteSpace(i.Value)) is { } fallback ? (fallback.System!, fallback.Value!) : null; } private async Task ResolveByIdentifierAsync( ExternalResourceType type, string? system, string? value, string[] acceptedSystems) { if (string.IsNullOrWhiteSpace(system) || string.IsNullOrWhiteSpace(value)) throw new FhirMappingException("Identifier system and value are required.", "required"); if (!acceptedSystems.Contains(system)) throw new FhirMappingException( $"Identifier system '{system}' is not configured.", "not-supported"); var internalId = await _identifiers.ResolveInternalIdAsync(type, system, value); if (internalId is null) throw new NotFoundException( $"{type} with identifier {system}|{value} not found.", "FHIR_RESOURCE_NOT_FOUND"); return internalId.Value; } }