using Hl7.Fhir.Model;
using FhirPatient = Hl7.Fhir.Model.Patient;

public static class PatientMapper
{
    /// <summary>
    /// Maps a VigilCare Patient entity to a FHIR R4 Patient resource.
    ///
    /// Mapping decisions:
    /// - VigilCare stores full name as a single string; FHIR splits into family/given.
    ///   We use HumanName.Text for the full string and attempt to split on the last
    ///   space for family/given when possible.
    /// - MRN maps to Identifier with system "urn:oid:2.16.840.1.113883.19.5" (example OID).
    ///   Facilities should configure their own OID.
    /// - BloodType maps to an extension (no standard FHIR element for blood type).
    /// - AllergiesJson is NOT mapped here — allergies should use AllergyIntolerance
    ///   resources, which are out of scope for Phase 11 v1.
    /// </summary>
    public static FhirPatient ToFhir(Patient entity, string baseUrl)
    {
        var patient = new FhirPatient
        {
            Id = entity.Id.ToString(),
            Meta = new Meta
            {
                VersionId = "1",
                LastUpdated = entity.UpdatedAt,
            },
            Active = true,
        };

        patient.Identifier.Add(new Identifier
        {
            System = "urn:oid:2.16.840.1.113883.19.5",
            Value = entity.Mrn,
            Use = Identifier.IdentifierUse.Official,
            Type = new CodeableConcept("http://terminology.hl7.org/CodeSystem/v2-0203", "MR", "Medical Record Number"),
        });

        var name = new HumanName { Text = entity.FullName, Use = HumanName.NameUse.Official };
        var parts = entity.FullName.Trim().Split(' ', StringSplitOptions.RemoveEmptyEntries);
        if (parts.Length >= 2)
        {
            name.Family = parts[^1];
            name.Given = parts[..^1].ToList();
        }
        else
        {
            name.Family = entity.FullName;
        }
        patient.Name.Add(name);

        if (entity.DateOfBirth.HasValue)
        {
            patient.BirthDate = entity.DateOfBirth.Value.ToString("yyyy-MM-dd");
        }

        if (!string.IsNullOrEmpty(entity.Sex))
        {
            patient.Gender = entity.Sex.ToLowerInvariant() switch
            {
                "male" => AdministrativeGender.Male,
                "female" => AdministrativeGender.Female,
                "other" => AdministrativeGender.Other,
                _ => AdministrativeGender.Unknown,
            };
        }

        if (!string.IsNullOrEmpty(entity.EmergencyContact))
        {
            patient.Contact.Add(new FhirPatient.ContactComponent
            {
                Relationship = new List<CodeableConcept>
                {
                    new("http://terminology.hl7.org/CodeSystem/v2-0131", "C", "Emergency Contact")
                },
                Name = new HumanName { Text = entity.EmergencyContact },
            });
        }

        return patient;
    }
}
