using adas_core.Application.Exceptions;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Application.Subscriptions;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using MongoDB.Bson;

namespace adas_core.Application.Services;

public class AdmissionService(
    ILogger<AdmissionService> logger,
    ISubscribersService subscribersService,
    IAdmissionRepository admissionRepository,
    IClientMessageService clientMessageService,
    IUnitService unitService,
    IPatientService patientService,
    IPointOfCareService pointOfCareService,
    IDisplayService displayService,
    IDischargeService dischargeService,
    IPatientArchiveRepository patientArchiveRepository,
    IHttpContextAccessor httpContextAccessor,
    ILocalAuditService auditService,
    IMasterListServiceFactory masterListServiceFactory)
    : IAdmissionService
{
    // Auditory logs


    public async Task DeleteAdmissionAsync(Admission admission)
    {
        await DeleteAdmissionByIdAsync(admission.Id);
    }

    public async Task DeleteAdmissionByIdAsync(ObjectId admissionId)
    {
        var admissionAux = await admissionRepository.FindById(admissionId);
        if (admissionAux == null)
        {
            logger.LogInformation("Error deleting Admission not found, id: {AdmissionId} ", admissionId);
            return;
        }

        await admissionRepository.Delete(admissionId);

        if (admissionAux.PointOfCareId.HasValue)
        {
            var poc = await pointOfCareService.GetInfo(admissionAux.PointOfCareId.Value);
            if (poc != null && poc.AdmissionId == admissionId)
            {
                poc.AdmissionId = null;
                poc.Admission = null;
                await pointOfCareService.Update(poc);


                if (poc.Status != StatusEnum.PointOfCare.Locked && poc.Status != StatusEnum.PointOfCare.InUse)
                    await pointOfCareService.SetPointOfCareStatus(poc.Id, StatusEnum.PointOfCare.Available);
            }
        }

        logger.LogInformation("Admission id: {AdmissionId} DELETED  ", admissionId);

        SendAdmissionBroadcast(admissionAux, OperationType.DeleteAdmission);

        await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, admissionAux, null);
    }

    public async Task DeleteAdmissionsByUnitId(ObjectId unitId)
    {
        _ = await admissionRepository.DeleteAdmissionsByUnitId(unitId);
    }


    public async Task<Admission?> GetAdmissionByIdAsync(ObjectId admissionId)
    {
        var result = await admissionRepository.FindById(admissionId);
        if (result?.PointOfCareId != null)
        {
            var poc = await pointOfCareService.GetInfo(result.PointOfCareId.Value, null,false);
            result.PatientLocation = new PatientLocation(poc?.UnitName, poc?.Bed, poc?.Room);
        }

        return result;
    }

    public async Task<IEnumerable<Admission>> GetAdmissionsAsync()
    {
        var resultList = await admissionRepository.FindAll() ??
                         throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
        var admissionsAsync = resultList.ToList();
        foreach (var admission in admissionsAsync)
            if (admission.PointOfCareId != null)
            {
                var poc = await pointOfCareService.GetInfo(admission.PointOfCareId.Value, null,false);
                admission.PatientLocation = new PatientLocation(poc?.UnitName, poc?.Bed, poc?.Room);
            }

        return admissionsAsync;
    }

    public async Task<Admission?> InsertAdmission(Admission admission)
    {
        var admissionAux = await admissionRepository.FindByNhc(admission.Nhc);
        if (admissionAux != null) throw new ConflictException(HttpEnum.ErrorMessage.BadRequestDuplicateData);
        PointOfCare? pointOfCare = null;
        //Bloqueamos el pointOfCare en el caso de que lo tenga asignado
        if (admission.PointOfCareId.HasValue)
        {
            pointOfCare = await pointOfCareService.GetInfo(admission.PointOfCareId.Value) ??
                          throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);

            //pointOfCare.AdmissionId = admission.Id;
            //pointOfCare.Admission = admission;                   
            admission.PatientLocation = new PatientLocation(pointOfCare.UnitName, pointOfCare.Bed, pointOfCare.Room);
        }

        var insertedAdmission = await admissionRepository.InsertOneAsyncAndReturn(admission) ??
                                throw new ConflictException(HttpEnum.ErrorMessage.ConflictCreationFailed);

        if (pointOfCare is { AdmissionId: null })
        {
            pointOfCare.Admission = insertedAdmission;
            pointOfCare.AdmissionId = insertedAdmission.Id;
            if (pointOfCare.Status == StatusEnum.PointOfCare.Available)
                pointOfCare.Status = StatusEnum.PointOfCare.Reserved;

            await pointOfCareService.Update(pointOfCare);
        }

        SendAdmissionBroadcast(insertedAdmission, OperationType.NewAdmission);
        // Obtener información el usuario autenticado

        await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, null, insertedAdmission);

        return insertedAdmission;
    }

    public async Task UpdateAdmissionAsync(Admission admission)
    {
        var oldAdmission = await admissionRepository.FindById(admission.Id);
        if (oldAdmission == null) return;
        if (oldAdmission.PointOfCareId.HasValue)
        {
            var pocOld = await pointOfCareService.GetInfo(oldAdmission.PointOfCareId.Value, null,false);
            if (pocOld != null)
                oldAdmission.PatientLocation = new PatientLocation(pocOld.UnitName, pocOld.Bed, pocOld.Room);
        }

        if (admission.PointOfCareId.HasValue)
        {
            var poc = await pointOfCareService.GetInfo(admission.PointOfCareId.Value, null,false);
            if (poc != null) admission.PatientLocation = new PatientLocation(poc.UnitName, poc.Bed, poc.Room);
        }

        await admissionRepository.Update(admission);

        await HandlePointOfCareChange(admission, oldAdmission);
        await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldAdmission, admission);
        SendAdmissionBroadcast(admission, OperationType.UpdateAdmission);
    }

    public async Task AdmitPatient(Admission admission, bool isNew = false)
    {
        if (admission.PointOfCareId == null)
        {
            logger.LogError("PointOfCare is required. Admission: {Admission}", admission);
            return;
        }

        var unit = await unitService.FindById(admission.UnitId);
        if (unit == null)
        {
            logger.LogError("Unit {Name} not found. Unit Id: ", admission.UnitId);
            return;
        }

        var pointOfCare = await pointOfCareService.FindById(admission.PointOfCareId.Value);
        if (pointOfCare == null)
        {
            logger.LogError("Point of Care not found. Patient not created. {Admission}", admission);
            return;
        }


        Patient patient = new()
        {
            PointOfCareId = pointOfCare.Id,
            UnitId = pointOfCare.UnitId,
            PointOfCare = pointOfCare,
            UnitString = pointOfCare.UnitName,
            Bed = pointOfCare.Bed,
            Room = pointOfCare.Room,
            PatientNumber = admission.Nhc,
            AdmTime = DateTime.UtcNow,
            Person = admission.Person,
            CreationDate = DateTime.UtcNow,
            DischargeStatus = pointOfCare.Unit?.DischargeStatusList?.Options.FirstOrDefault(),
            Origin = admission.Origin,
            OriginAux = admission.OriginAux,
            Diagnosis = admission.Diagnosis,
            DiagnosisAux = admission.DiagnosisAux,
            Allergies = admission.Allergies,
            Insulation = admission.Insulation,
            LanguageBarrier = admission.LanguageBarrier,
            PassiveSitting = admission.PassiveSitting,
            Altable = new OptionList
            {
                Name = "NotAltable",
                IconDefault = "icNotAltable",
                OptionType = "NotAltable"
            },
            Visits = pointOfCare.Unit?.VisitOptionList?.Options.FirstOrDefault(),
            AccessControl = pointOfCare.Unit?.AccessControlList?.Options.FirstOrDefault(),
            Location = new PatientLocation
            (
                unit.Name,
                pointOfCare.Bed,
                pointOfCare.Room
            )
        };
        if (unit.AltableOptionListId is not null)
        {
            var list = await masterListServiceFactory.GetMasterListById(MasterListType.AltableOptionList,
                unit.AltableOptionListId.Value, LocaleEnum.Default) as AltableOptionList;
            var listOpt = list?.Options.FirstOrDefault(c => c.OptionType == "NotAltable");
            if (listOpt != null)
                patient.Altable = listOpt;
        }

        await patientService.Insert(patient);
        await SetPointOfCareStatus(pointOfCare.Id, StatusEnum.PointOfCare.InUse);

        if (!isNew)
            await DeleteAdmissionAsync(admission);
        
        if (admission.Insulation != null)
            await patientService.UpdatePatientMasterList(
                patient.Id,
                MasterListType.InsulationList,
                [admission.Insulation],
                null, null);

        if (admission.Allergies != null)
            await patientService.UpdatePatientMasterList(
                patient.Id,
                MasterListType.AllergyList,
                admission.Allergies,
                null, null);
        if (admission.Diagnosis != null)
            await patientService.UpdatePatientMasterList(
                patient.Id,
                MasterListType.DiagnosisList,
                [admission.Diagnosis],
                null, null);
        if (admission.Origin != null)
            await patientService.UpdatePatientMasterList(
                patient.Id,
                MasterListType.OriginList,
                [admission.Origin],
                null, null);
        if (admission.LanguageBarrier != null)
            await patientService.UpdatePatientMasterList(
                patient.Id,
                MasterListType.LanguageBarrierList,
                admission.LanguageBarrier,
                null, null);
        if (admission.PassiveSitting != null)
            await patientService.UpdatePatientMasterList(
                patient.Id,
                MasterListType.PassiveSittingList,
                [admission.PassiveSitting],
                null, null);
    }

    public async Task ReturnPatientToAdmissions(ObjectId patientId)
    {
        var patient = await patientService.FindById(patientId);
        if (patient == null)
        {
            logger.LogError("Error returning the patient Id: {Id} to admission", patientId);
            return;
        }

        var unit = await unitService.FindById(patient.UnitId);
        if (unit == null)
        {
            logger.LogError("Unit not found by Id. {Name}", patient.UnitId);
            return;
        }

        if (patient.PointOfCareId != null)
        {
            var poc = await pointOfCareService.FindById(patient.PointOfCareId.Value);
            Admission admission = new()
            {
                Nhc = patient.PatientNumber ?? string.Empty,
                PointOfCareId = poc?.Id,
                UnitId = unit.Id,
                Person = patient.Person ??
                         new Person(), //No debería ser null en este punto, pero así quito el warning 
                Origin = patient.Origin,
                OriginAux = patient.OriginAux,
                Diagnosis = patient.Diagnosis,
                PassiveSitting = patient.PassiveSitting,
                DiagnosisAux = patient.DiagnosisAux,
                Allergies = patient.Allergies,
                Insulation = patient.Insulation,
                LanguageBarrier = patient.LanguageBarrier,
                AdmissionDate = patient.AdmTime ?? DateTime.UtcNow,
                PatientLocation = patient.Location
            };

            await InsertAdmission(admission);
        }

        var dis = await dischargeService.GetDischargeByPatientId(patient.Id);
        if (dis != null) await dischargeService.DeleteDischargeByIdAsync(dis.Id);
        await patientService.ArchivePatient(patient);

        pointOfCareService.CheckNextAdmission(patient.PointOfCareId);
    }

    // Used for temporal beds like PUSHED
    public async Task ReturnPatientToAdmissions(ObjectId patientId, Admission adm)
    {
        var patient = await patientService.FindById(patientId);
        if (patient == null)
        {
            logger.LogError("Error returning the patient Id: {Id} to admission", patientId);
            return;
        }


        var unit = await unitService.FindById(adm.UnitId);
        if (unit == null)
        {
            logger.LogError("Unit not found by Id. {Name}", patient.UnitId);
            return;
        }

        if (adm.PointOfCareId != null)
        {
            var poc = await pointOfCareService.FindById(adm.PointOfCareId.Value);
            Admission admission = new()
            {
                Nhc = patient.PatientNumber ?? string.Empty,
                PointOfCareId = poc?.Id,
                UnitId = unit.Id,
                Person = patient.Person ??
                         new Person(), //No debería ser null en este punto, pero así quito el warning 
                Origin = patient.Origin,
                OriginAux = patient.OriginAux,
                Diagnosis = patient.Diagnosis,
                DiagnosisAux = patient.DiagnosisAux,
                Allergies = patient.Allergies,
                PassiveSitting = patient.PassiveSitting,
                Insulation = patient.Insulation,
                LanguageBarrier = patient.LanguageBarrier,
                AdmissionDate = patient.AdmTime ?? DateTime.UtcNow,
                PatientLocation = patient.Location
            };

            await InsertAdmission(admission);
        }

        var dis = await dischargeService.GetDischargeByPatientId(patient.Id);
        if (dis != null) await dischargeService.DeleteDischargeByIdAsync(dis.Id);
        await patientService.ArchivePatient(patient);

        pointOfCareService.CheckNextAdmission(patient.PointOfCareId);
    }

    public async Task<List<Admission>> GetAdmissionByLocation(PatientLocation location)
    {
        try
        {
            return await admissionRepository.FindByLocation(location);
        }
        catch (Exception e)
        {
            logger.LogError("Error getting admission by patient location {Location} exception: {Ex}", location,
                e.Message);
            return [];
        }
    }

    public async Task<List<Admission>> GetAdmissionByPointOfCareId(ObjectId pocId)
    {
        try
        {
            var result = await admissionRepository.FindByPointOfCareId(pocId);
            foreach (var admission in result)
            {
                var poc = await pointOfCareService.GetInfo(pocId, null,false);
                if (poc != null) admission.PatientLocation = new PatientLocation(poc.UnitName, poc.Bed, poc.Room);
            }

            return result;
        }
        catch (Exception e)
        {
            logger.LogError("Error getting admission by patient PocId {PocId} exception: {Ex}", pocId, e.Message);
            return [];
        }
    }

    public async Task<List<Admission>> GetAdmissionByPointOfCareIdAndLocale(ObjectId pocId, LocaleEnum locale)
    {
        var admissions = await GetAdmissionByPointOfCareId(pocId);

        // Ejecutar todas las traducciones en paralelo
        var translatedAdmissions = await Task.WhenAll(
            admissions.Select(adm => GetAdmissionWithLocale(adm, locale))
        );

        return translatedAdmissions.ToList();
    }

    public async Task<List<Admission>> GetAdmissionByUnitIdWithOutPoC(ObjectId unitId)
    {
        try
        {
            return await admissionRepository.GetAdmissionByUnitIdWithOutPoC(unitId);
        }
        catch (Exception e)
        {
            logger.LogError("Error getting admission by unitId with out PoCId {UnitId} exception: {Ex}", unitId,
                e.Message);
            return [];
        }
    }

    public async Task<long> CountAdmissionsByUnitId(ObjectId unitId)
    {
        try
        {
            return await admissionRepository.CountByUnitId(unitId);
        }
        catch (Exception e)
        {
            logger.LogError("Error getting admission by unitId with out PoCId {UnitId} exception: {Ex}", unitId,
                e.Message);
            return 0;
        }
    }

    public async Task<PatientSearch?> SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId)
    {
        var patient = await patientService.FindByPatientNumber(patientNumber);
        if (patient != null)
        {
            if (patient.PointOfCareId.HasValue)
                patient.PointOfCare = await pointOfCareService.FindById(patient.PointOfCareId.Value);
            if (patient.UnitId.HasValue)
            {
                var uni = await unitService.FindById(patient.UnitId.Value);
                if (uni != null)
                    patient.UnitString = uni.Name;
            }
        }

        var archivePatient =
            await patientArchiveRepository.SearchByPatientNumberAndDistinctUnit(patientNumber, unitId);
        var admission = await admissionRepository.SearchByPatientNumberAndDistinctUnit(patientNumber, unitId);

        var result = new PatientSearch(patient, archivePatient, admission,
            patient == null && archivePatient != null,
            patient != null || archivePatient != null || admission != null);
        return result;
    }

    public Task<Admission?> GetAdmissionByPatientNumber(string patientNumber)
    {
        return admissionRepository.FindByNhc(patientNumber);
    }

    public async Task UpdatePatientMasterListItemChange(UpdateOptionMasterListDto opt, IEnumerable<Unit> unitList,
        string typeName)
    {
        var unitIds = unitList.Select(x => x.Id).ToList();
        var oldAdmissionList = await admissionRepository.FindByUnitIds(unitIds);
        var admissionUpdatedList = await admissionRepository.UpdateMasterListOption(unitIds, opt, typeName);
        foreach (var admission in admissionUpdatedList)
        {
            var oldAdmission = oldAdmissionList.Find(adm => adm.Id == admission.Id);
            await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldAdmission!, admission);
            SendAdmissionBroadcast(admission, OperationType.UpdateAdmission);
        }
    }

    public async Task DeletePatientMasterListItem(OptionList opt, IEnumerable<Unit> unitList, string typeName)
    {
        var unitIds = unitList.Select(x => x.Id).ToList();
        var oldAdmissionList = await admissionRepository.FindByUnitIds(unitIds);
        var admissionUpdatedList = await admissionRepository.DeleteMasterListOption(unitIds, opt, typeName);
        foreach (var admission in admissionUpdatedList)
        {
            var admissionUpdated = await GetAdmissionByIdAsync(admission.Id);
            var oldAdmission = oldAdmissionList.Find(adm => adm.Id == admission.Id);
            await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldAdmission!,
                admissionUpdated);
            if (admissionUpdated != null)
                SendAdmissionBroadcast(admissionUpdated, OperationType.UpdateAdmission);
        }
    }

    public async Task SaveRequest(ApiRequest apiRequest)
    {
        try
        {
            if (apiRequest.Admission == null)
                return;

            switch (apiRequest.Type)
            {
                case "NewAdmission":
                {
                    if (string.IsNullOrEmpty(apiRequest.Admission.Nhc) ||
                        apiRequest.Admission.Origin == null ||
                        apiRequest.Admission.Diagnosis == null)
                    {
                        logger.LogDebug(
                            "Error saving admission api request. Some values are required. Admission: {Admission}",
                            apiRequest.Admission);
                        return;
                    }

                    await InsertAdmission(apiRequest.Admission);
                    break;
                }
                case "UpdateAdmission":
                {
                    if (string.IsNullOrEmpty(apiRequest.Admission.Nhc) ||
                        apiRequest.Admission.Origin == null ||
                        apiRequest.Admission.Diagnosis == null)
                    {
                        logger.LogDebug(
                            "Error updating admission api request. Some values are required. Admission: {Admission}",
                            apiRequest.Admission);
                        return;
                    }

                    await UpdateAdmissionAsync(apiRequest.Admission);
                    break;
                }
                case "DeleteAdmission":
                {
                    await DeleteAdmissionAsync(apiRequest.Admission);
                    break;
                }
            }
        }
        catch (Exception ex)
        {
            logger.LogError("Exception updating admission {Admission} . Exception: {Ex}", apiRequest.Admission,
                ex.Message);
            throw;
        }
    }

    public Task SaveRequestAsync(ApiRequest apiRequest)
    {
        return Task.FromResult(Task.Run(async () => { await SaveRequest(apiRequest); }));
    }

    private async Task HandlePointOfCareChange(Admission admission, Admission oldAdmission)
    {
        // Check if PointOfCare has changed.
        if (admission.PointOfCareId == oldAdmission.PointOfCareId) return;

        // Disable new PointOfCare if it exists.
        if (admission.PointOfCareId.HasValue)
        {
            var newPoc = await pointOfCareService.GetInfo(admission.PointOfCareId.Value);
            if (newPoc == null) return;

            var patientOnNewPoc = await patientService.FindByPointOfCareId(newPoc.Id);
            if (newPoc.AdmissionId == null && newPoc.Status != StatusEnum.PointOfCare.Locked)
            {
                newPoc.Admission = admission;
                newPoc.AdmissionId = admission.Id;
                newPoc.Status = patientOnNewPoc != null
                    ? StatusEnum.PointOfCare.InUse
                    : StatusEnum.PointOfCare.Reserved;

                await pointOfCareService.Update(newPoc);
            }

            if (newPoc.Status == StatusEnum.PointOfCare.Available)
                pointOfCareService.CheckNextAdmission(newPoc.Id);
        }

        // Enable previous PointOfCare if it exists.
        if (oldAdmission.PointOfCareId.HasValue)
        {
            var oldPoc = await pointOfCareService.GetInfo(oldAdmission.PointOfCareId.Value);
            if (oldPoc != null)
            {
                var patientOnOldPoc = await patientService.FindByPointOfCareId(oldPoc.Id);
                if (oldPoc.AdmissionId == oldAdmission.Id && oldPoc.Status != StatusEnum.PointOfCare.Locked)
                {
                    oldPoc.Admission = null;
                    oldPoc.AdmissionId = null;
                    oldPoc.Status = patientOnOldPoc != null
                        ? StatusEnum.PointOfCare.InUse
                        : StatusEnum.PointOfCare.Available;

                    await pointOfCareService.Update(oldPoc);
                }
            }

            if (oldPoc is { Status: StatusEnum.PointOfCare.Available })
                pointOfCareService.CheckNextAdmission(oldPoc.Id);
        }
    }

    private async Task SetPointOfCareStatus(ObjectId pointOfCareId, StatusEnum.PointOfCare status)
    {
        var pointOfCare = await pointOfCareService.FindById(pointOfCareId);
        if (pointOfCare == null) return;

        await pointOfCareService.SetPointOfCareStatus(pointOfCareId, status);
    }

    private async void SendAdmissionBroadcast(Admission admission, OperationType operation)
    {
        try
        {
            if (admission.PointOfCareId == null)
                await SendAdmissionByUnitId(admission, operation);
            else
                await SendAdmissionBroadcastByPoC(admission, operation);
        }
        catch (Exception ex)
        {
            logger.LogError("Exception sending admission broadcast. Operation type: {Op}. Exception: {Ex}",
                operation.ToString(), ex.Message);
        }
    }

    private async Task SendAdmissionBroadcastByPoC(Admission admission, OperationType operation)
    {
        if (!admission.PointOfCareId.HasValue)
        {
            logger.LogError("Error sending admission broadcast. PointOfCare id {Id} not found",
                admission.PointOfCareId);
            return;
        }

        var pointOfCare = await pointOfCareService.FindById(admission.PointOfCareId.Value);
        if (pointOfCare == null)
        {
            logger.LogError("Error sending admission broadcast. PointOfCare id {Id} not found",
                admission.PointOfCareId);
            return;
        }

        var pocSubscribers = subscribersService.GetSubscribers().Where(s =>
            s.LocationIds.Contains(admission.PointOfCareId.Value)).GroupBy(h => h.Locale);

        foreach (var group in pocSubscribers)
        {
            var locale = group.Key ?? LocaleEnum.Default;
            IEnumerable<WsSubscriber> subscribers = group;

            foreach (var subscriber in subscribers)
            {
                var admissionWithLocale = await GetAdmissionWithLocale(admission, locale);
                _ = clientMessageService.SendAsync(subscriber.Id, operation, admissionWithLocale);
            }
        }
    }

    private async Task SendAdmissionByUnitId(Admission admission, OperationType operation)
    {
        if (admission.UnitId == ObjectId.Empty)
        {
            logger.LogError("Error sending admission broadcast. UnitId is null or empty {Admission}", admission);
            return;
        }

        var displays = await displayService.GetByUnitId(admission.UnitId);
        var displayIds = displays.Select(c => c.Id).ToList();
        var unitSubscribers = subscribersService.GetSubscribers().Where(s =>
            s.DisplayId != null && displayIds.Contains(s.DisplayId.Value)).GroupBy(h => h.Locale);
        foreach (var group in unitSubscribers)
        {
            var locale = group.Key ?? LocaleEnum.Default;
            IEnumerable<WsSubscriber> subscribers = group;

            foreach (var subscriber in subscribers)
            {
                var admissionWithLocale = await GetAdmissionWithLocale(admission, locale);
                _ = clientMessageService.SendAsync(subscriber.Id, operation, admissionWithLocale);
            }
        }
    }

    private async Task<Admission> GetAdmissionWithLocale(Admission admission, LocaleEnum locale)
    {
        var unit = await unitService.FindById(admission.UnitId);
        if (unit == null) return admission;
        if (admission.Origin?.Name != null && unit.OriginListId.HasValue)
        {
            if (await masterListServiceFactory.GetMasterListById(MasterListType.OriginList,
                    unit.OriginListId.Value, locale) is OriginList list)
            {
                var listOrigin = list.Options.FirstOrDefault(c => c.Id == admission.Origin.Id)?.Name;
                if (listOrigin != null)
                    admission.Origin.Name = listOrigin;
            }
        }

        if (admission.Diagnosis?.Name != null && unit.DiagnosisListId.HasValue)
        {
            if (await masterListServiceFactory.GetMasterListById(MasterListType.DiagnosisList,
                    unit.DiagnosisListId.Value, locale) is DiagnosisList list)
            {
                var listDiagnosis = list.Options.FirstOrDefault(c => c.Id == admission.Diagnosis.Id)?.Name;
                if (listDiagnosis != null)
                    admission.Diagnosis.Name = listDiagnosis;
            }
        }

        if (admission.Insulation?.Name != null && unit.InsulationListId.HasValue)
        {
            if (await masterListServiceFactory.GetMasterListById(MasterListType.InsulationList,
                    unit.InsulationListId.Value, locale) is InsulationList list)
            {
                var listInsulation = list.Options.FirstOrDefault(c => c.Id == admission.Insulation.Id)?.Name;
                if (listInsulation != null)
                    admission.Insulation.Name = listInsulation;
            }
        }

        return admission;
    }
}