public async Task <ConsultancyMessageDTO> SendConsultancyMessageAsync(SendMessageDTO model)
        {
            ConsultancyMessageDTO result = null;

            var strategy = _dbContext.Database.CreateExecutionStrategy();

            await strategy.ExecuteAsync(async() =>
            {
                using (var transaction = _dbContext.Database.BeginTransaction())
                {
                    var msg = new ConsultancyMessage
                    {
                        ConsultancyId   = model.ConsultancyId,
                        ServiceSupplyId = model.ServiceSupplyId,
                        PersonId        = model.PersonId,
                        CreatedAt       = DateTime.Now,
                        Content         = model.Content,
                        Status          = ConsultancyMessageStatus.NEW,
                        Sender          = model.Sender,
                        Type            = model.Type,
                    };

                    await _dbContext.ConsultancyMessages.AddAsync(msg);

                    await _dbContext.SaveChangesAsync();

                    result = new ConsultancyMessageDTO
                    {
                        Id = msg.Id,
                        SenderReceiverType = msg.Sender == ConsultancyMessageSender.CUSTOMER ? MessageSenderReceiverType.SENT : MessageSenderReceiverType.RECEIVED,
                        Message            = msg.Content,
                        Time = msg.CreatedAt.ToString("HH:mm"),
                        Type = msg.Type
                    };

                    transaction.Commit();
                }
            });

            await NotifyMessageReceiverAsync(model, result);

            return(result ?? throw new AwroNoreException(""));
        }
        private async Task NotifyMessageReceiverAsync(SendMessageDTO model, ConsultancyMessageDTO result)
        {
            try
            {
                var instanceIds    = new List <string>();
                var doctorName     = "";
                var doctorAvatar   = "";
                var customerName   = "";
                var customerAvatar = "";
                var personName     = "";
                var personAvatar   = "";
                // Receiver is doctor, so we must send notification to doctor
                var serviceSupply = await _dbContext.ServiceSupplies.FindAsync(model.ServiceSupplyId);

                if (serviceSupply != null)
                {
                    doctorName   = serviceSupply.Person.FullName;
                    doctorAvatar = serviceSupply.Person.RealAvatar;
                }

                var person = await _dbContext.Persons.FindAsync(model.PersonId);

                if (person != null)
                {
                    customerName   = person.FullName;
                    customerAvatar = person.RealAvatar;
                }

                if (model.Sender == ConsultancyMessageSender.CUSTOMER)
                {
                    personName   = customerName;
                    personAvatar = customerAvatar;
                    if (serviceSupply != null && serviceSupply.Person.FcmInstanceIds != null)
                    {
                        instanceIds = serviceSupply.Person.FcmInstanceIds.Select(x => x.InstanceId).ToList();
                    }
                }
                else
                {
                    personName   = doctorName;
                    personAvatar = doctorAvatar;
                    if (person != null && person.FcmInstanceIds != null)
                    {
                        instanceIds = person.FcmInstanceIds.Select(x => x.InstanceId).ToList();
                    }
                }

                foreach (var item in instanceIds)
                {
                    var payLoad = new ConsultancyMessageNotificationPayload
                    {
                        NotificationType = NotificationType.ConsultancyMessage,
                        ChatId           = model.ConsultancyId,
                        ServiceSupplyId  = model.ServiceSupplyId,
                        PersonId         = model.PersonId,
                        PersonName       = personName,
                        PersonAvatar     = personAvatar,
                        MessageId        = result.Id,
                        Sender           = model.Sender,
                        Content          = result.Message,
                        Type             = result.Type
                    };

                    await _notificationService.SendConsultancyMessageDeliveryNotificationAsync(item, personName, result.Message?.TruncateLongString(50), payLoad);
                }
            }
            catch
            {
            }
        }
        public async Task <ConsultancyMessageDTO> SendMultiMediaMessageAsync(SendMessageDTO model, IFormFile file)
        {
            ConsultancyMessageDTO result = null;

            var strategy = _dbContext.Database.CreateExecutionStrategy();

            await strategy.ExecuteAsync(async() =>
            {
                using (var transaction = _dbContext.Database.BeginTransaction())
                {
                    var msg = new ConsultancyMessage
                    {
                        ConsultancyId   = model.ConsultancyId,
                        ServiceSupplyId = model.ServiceSupplyId,
                        PersonId        = model.PersonId,
                        CreatedAt       = DateTime.Now,
                        Content         = "",
                        Status          = ConsultancyMessageStatus.NEW,
                        Sender          = model.Sender,
                        Type            = model.Type,
                    };

                    await _dbContext.ConsultancyMessages.AddAsync(msg);

                    await _dbContext.SaveChangesAsync();

                    if (model.Type == ConsultancyMessageType.PHOTO)
                    {
                        var(newName, thumbName, dirPath, baseUrl) = _uploadService.GenerateConsultancyMessageImageName(model.ConsultancyId, msg.Id, file);

                        var url = $"{baseUrl}/{newName}";

                        var thumbUrl = $"{baseUrl}/{thumbName}";

                        msg.Content = $"{url},{thumbUrl}";

                        _dbContext.ConsultancyMessages.Attach(msg);

                        _dbContext.Entry(msg).State = EntityState.Modified;

                        await _dbContext.SaveChangesAsync();

                        await _uploadService.UploadConsultancyMessageImageAsync(file, dirPath, newName, thumbName);
                    }
                    else if (model.Type == ConsultancyMessageType.VOICE)
                    {
                        var(newName, dirPath, baseUrl) = _uploadService.GenerateConsultancyMessageVoiceName(model.ConsultancyId, msg.Id, file);

                        var url = $"{baseUrl}/{newName}";

                        msg.Content = $"{url}";

                        _dbContext.ConsultancyMessages.Attach(msg);

                        _dbContext.Entry(msg).State = EntityState.Modified;

                        await _dbContext.SaveChangesAsync();

                        await _uploadService.UploadConsultancyMessageVoiceAsync(file, dirPath, newName);
                    }

                    result = new ConsultancyMessageDTO
                    {
                        Id = msg.Id,
                        SenderReceiverType = msg.Sender == ConsultancyMessageSender.CUSTOMER ? MessageSenderReceiverType.SENT : MessageSenderReceiverType.RECEIVED,
                        Message            = msg.Content,
                        Time = msg.CreatedAt.ToString("HH:mm"),
                        Type = msg.Type
                    };

                    transaction.Commit();
                }
            });

            await NotifyMessageReceiverAsync(model, result);

            return(result ?? throw new AwroNoreException(""));
        }