namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Shared.EntityModels;

    using Shared.UserModels;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels.Common;
    using Hims.Shared.UserModels.Telemedicine;


    /// <inheritdoc />
    public class WebTelemedicineServices : IWebTelemedicineService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <summary>
        /// Initializes a new instance of the <see cref="WebTelemedicineServices"/> class.
        /// </summary>
        /// <param name="unitOfWork">
        /// The unit of work.
        /// </param>
        public WebTelemedicineServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc />
        public async Task<int> CreateAsync(int appointmentId)
        {
            var data = new WebTelemedicine
            {
                AppointmentId = appointmentId,
                Count = 0,
                CreatedDate = DateTime.UtcNow,
                Status = 1
            };

            var response = await this.unitOfWork.WebTelemedicine.InsertAsync(data);
            return response;
        }

        /// <inheritdoc />
        public async Task<WebTelemedicineModel> GetAsync(int telemedicineId)
        {
            var record = await this.unitOfWork.WebTelemedicine.FindAsync(x => x.WebTelemedicineId == telemedicineId);
            var data = new WebTelemedicineModel
            {
                AppointmentId = record.AppointmentId,
                Count = record.Count,
                CreatedDate = record.CreatedDate,
                ModifiedDate = record.ModifiedDate,
                Status = record.Status,
                WebTelemedicineId = record.WebTelemedicineId
            };

            return data;
        }

        /// <inheritdoc />
        public async Task<int> GetStatusAsync(int telemedicineId)
        {
            var record = await this.unitOfWork.WebTelemedicine.FindAsync(x => x.WebTelemedicineId == telemedicineId);
            return record.Status;
        }

        /// <inheritdoc />
        public async Task<int> UpdateCountAsync(int telemedicineId)
        {
            var record = await this.unitOfWork.WebTelemedicine.FindAsync(x => x.WebTelemedicineId == telemedicineId);
            record.Count += 1;
            record.ModifiedDate = DateTime.UtcNow;

            return await this.unitOfWork.WebTelemedicine.UpdateAsync(record);
        }

        /// <inheritdoc />
        public async Task<int> UpdateStatusAsync(int telemedicineId, int status)
        {
            var record = await this.unitOfWork.WebTelemedicine.FindAsync(x => x.WebTelemedicineId == telemedicineId);
            record.Status = status;

            return await this.unitOfWork.WebTelemedicine.UpdateAsync(record);
        }

        /// <inheritdoc />
        public Task<IEnumerable<string>> FetchPatientAppointmentsAsync(int patientId)
        {
            var query = $@"SELECT ""AppointmentNo"" from ""Appointment"" WHERE ""PatientId"" = '{patientId}' AND ""AppointmentDate""::date = '{DateTime.Today:yyyy/MM/dd}'::date ";
            return this.unitOfWork.Current.QueryAsync<string>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<string>> FetchProviderAppointmentsAsync(int? providerId, int? practiceId)
        {
            var where = "1=1";
            string providerIds = string.Empty;
            if (practiceId != null && practiceId != 0)
            {
                var practiceLocation = this.unitOfWork.Locations.Find(m => m.PracticeId == practiceId && m.Active);

               
                var providerLocations = this.unitOfWork.ProviderLocations.FindAll(m => m.LocationId == practiceLocation.LocationId && m.Active);

                foreach (var id in providerLocations)
                {
                    if (string.IsNullOrEmpty(providerIds))
                    {
                        providerIds = id.ProviderId.ToString();
                    }
                    else
                    {
                        providerIds += ", " + id.ProviderId.ToString();
                    }
                }

                where += $@" and ""ProviderId"" IN ({providerIds})";
            }
            else
            {
                if (providerId != null)
                {
                    where += $@" and ""ProviderId"" IN ({providerId})";
                }
            }

            var query = $@"SELECT ""AppointmentNo"" from ""Appointment"" WHERE {where}";
            return this.unitOfWork.Current.QueryAsync<string>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetNurseOrReceptionistDeviceTokens(string appointmentNo, int roleId)
        {
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Appointment"" a
                                JOIN ""Provider"" p on p.""ProviderId"" = a.""ProviderId""
                                JOIN ""ProviderLocation"" pl on pl.""ProviderId"" = p.""ProviderId""
                                JOIN ""User"" u on u.""ProviderLocationId"" = pl.""ProviderLocationId""
                                JOIN ""Account"" ac on ac.""ReferenceId"" = u.""UserId""
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE a.""AppointmentNo"" = '{appointmentNo}' AND ac.""RoleId"" = {roleId} AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetDeviceTokensByAccount(int accountId)
        {
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""AccountId"" = {accountId} AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetDeviceTokensByAccountIds(List<int> accountIds)
        {
            var strAccountIds = string.Join(',', accountIds);
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""AccountId"" IN ({strAccountIds}) AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public async Task<int> CreateTelemedicineHistory(string appointmentNo, int accountId, int callType)
        {
            int responseId;
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                var history = await this.unitOfWork.TelemedicineHistory.FindAsync(x => x.AppointmentId == appointment.AppointmentId);
                if (history == null)
                {
                    var historyModel = new TelemedicineHistory
                    {
                        AppointmentId = appointment.AppointmentId
                    };
                    var historyId = await this.unitOfWork.TelemedicineHistory.InsertAsync(historyModel);
                    var callHistoryModel = new TelemedicineCallHistory
                    {
                        TelemedicineHistoryId = historyId,
                        CreatedBy = accountId,
                        CreatedDate = DateTime.Now,
                        Status = 1, // Call Initiated
                        InProgress = true,
                        CallType = callType
                    };
                    responseId = await this.unitOfWork.TelemedicineCallHistory.InsertAsync(callHistoryModel);
                }
                else
                {
                    var activeCallHistory = await this.unitOfWork.TelemedicineCallHistory.FindAsync(x => x.TelemedicineHistoryId == history.TelemedicineHistoryId && x.InProgress == true);
                    if (activeCallHistory == null)
                    {
                        var callHistoryModel = new TelemedicineCallHistory
                        {
                            TelemedicineHistoryId = history.TelemedicineHistoryId,
                            CreatedBy = accountId,
                            CreatedDate = DateTime.Now,
                            Status = 1, // Call Initiated
                            InProgress = true,
                            CallType = callType
                        };
                        responseId = await this.unitOfWork.TelemedicineCallHistory.InsertAsync(callHistoryModel);
                    }
                    else
                    {
                        activeCallHistory.InProgress = true;
                        activeCallHistory.ModifiedBy = accountId;
                        activeCallHistory.ModifiedDate = DateTime.Now;
                        await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(activeCallHistory);
                        responseId = activeCallHistory.TelemedicineCallHistoryId;
                    }
                }

                return responseId;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> PatientCallIntimateAsync(int telemedicineCallId, int receiverId, int callerId)
        {
            try
            {
                // 1 = Got Call
                //var activeOpponentUser = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                //                             x => x.TelemedicineCallHistoryId == telemedicineCallId &&
                //                                  x.AccountId == receiverId && x.CallerId == callerId && x.Status == 1);
                var activeOpponentUser = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                                             x => x.TelemedicineCallHistoryId == telemedicineCallId &&
                                                  x.InProgress == true);
                if (activeOpponentUser == null || !activeOpponentUser.Any())
                {
                    var userId = 0;
                    var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                        x => x.TelemedicineCallHistoryId == telemedicineCallId &&
                             x.AccountId == callerId && x.CallerId == callerId);
                    if (users == null || !users.Any())
                    {
                        var providerUser = new TelemedicineUsersHistory
                        {
                            AccountId = callerId,
                            CallerId = callerId,
                            Status = 2, // Got Call
                            Date = DateTime.Now,
                            InProgress = true,
                            TelemedicineCallHistoryId = telemedicineCallId
                        };
                        userId = await this.unitOfWork.TelemedicineUsersHistory.InsertAsync(providerUser);
                    }

                    var user = new TelemedicineUsersHistory
                    {
                        AccountId = receiverId,
                        CallerId = callerId,
                        Status = 1, // Got Call
                        Date = DateTime.Now,
                        TelemedicineCallHistoryId = telemedicineCallId
                    };
                    userId += await this.unitOfWork.TelemedicineUsersHistory.InsertAsync(user);

                    return userId;
                }

                return 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> InitiatePatientCallIntimateAsync(int telemedicineCallId, int receiverId, int callerId)
        {
            try
            {
                // 1 = Got Call
                //var activeOpponentUser = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                //                             x => x.TelemedicineCallHistoryId == telemedicineCallId &&
                //                                  x.AccountId == receiverId && x.CallerId == callerId && x.Status == 1);
                var activeOpponentUser = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                                             x => x.TelemedicineCallHistoryId == telemedicineCallId &&
                                                  x.InProgress == true);
                if (activeOpponentUser == null || !activeOpponentUser.Any())
                {
                    var user = new TelemedicineUsersHistory
                    {
                        AccountId = receiverId,
                        CallerId = callerId,
                        Status = 1, // Got Call
                        Date = DateTime.Now,
                        TelemedicineCallHistoryId = telemedicineCallId
                    };
                    var response = await this.unitOfWork.TelemedicineUsersHistory.InsertAsync(user);
                    return response;
                }

                return 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> InitializeCallAsync(int telemedicineCallId, int callerId)
        {
            try
            {
                var record =
                    await this.unitOfWork.TelemedicineCallHistory.FindAsync(x =>
                        x.TelemedicineCallHistoryId == telemedicineCallId);

                if (record == null) return 0;

                record.Status = 1;
                record.InProgress = true;
                record.ModifiedDate = DateTime.Now;
                record.ModifiedBy = callerId;

                var response = await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(record);
                return response;

            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> CallJoinAsync(int telemedicineCallId, int receiverId)
        {
            try
            {
                var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                               x => x.TelemedicineCallHistoryId == telemedicineCallId && x.AccountId == receiverId);
                var telemedicineUsersHistories = users.ToList();

                if (telemedicineUsersHistories.Any())
                {
                    foreach (var user in telemedicineUsersHistories)
                    {
                        user.Status = 2; // Call Accepted
                        user.Date = DateTime.Now;
                        user.InProgress = true;
                    }

                    var userId = await this.unitOfWork.TelemedicineUsersHistory.BulkUpdateAsync(telemedicineUsersHistories);

                    if (userId)
                    {
                        // update all call Initiated records to In Progress
                        var telemedicineCallHistory = await this.unitOfWork.TelemedicineCallHistory.FindAllAsync(x =>
                            x.TelemedicineCallHistoryId == telemedicineCallId && x.InProgress == true);
                        var telemedicineCallHistories = telemedicineCallHistory.ToList();

                        if (telemedicineCallHistories.Any())
                        {
                            foreach (var call in telemedicineCallHistories)
                            {
                                call.Status = 2; // In Progress 
                            }

                            var response = await this.unitOfWork.TelemedicineCallHistory.BulkUpdateAsync(telemedicineCallHistories);
                            return response ? 1 : 0;
                        }

                        return 1;
                    }

                    return 0;
                }
                else
                {
                    var firstUser = await this.unitOfWork.TelemedicineUsersHistory.FindAsync(
                               x => x.TelemedicineCallHistoryId == telemedicineCallId);

                    var user = new TelemedicineUsersHistory
                    {
                        AccountId = receiverId,
                        CallerId = firstUser?.CallerId ?? receiverId,
                        Status = 2, // Got Call
                        Date = DateTime.Now,
                        InProgress = true,
                        TelemedicineCallHistoryId = telemedicineCallId
                    };

                    var userId = await this.unitOfWork.TelemedicineUsersHistory.InsertAsync(user);
                    return userId;
                }
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> DoctorCallCloseAsync(int telemedicineCallId, int accountId)
        {
            try
            {
                var telemedicineCallHistory =
                    await this.unitOfWork.TelemedicineUsersHistory.FindAsync(x =>
                        x.TelemedicineCallHistoryId == telemedicineCallId && x.AccountId == accountId);
                telemedicineCallHistory.Status = 4; // Call Cancelled
                telemedicineCallHistory.InProgress = false;
                var responseId = await this.unitOfWork.TelemedicineUsersHistory.UpdateAsync(telemedicineCallHistory);

                return responseId;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> CallLogAsync(CallLog callLog)
        {
            try
            {
                var response = await this.unitOfWork.CallLog.InsertAsync(callLog);
                return response;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> CallCloseAllAsync(int telemedicineCallId)
        {
            try
            {
                if (telemedicineCallId == 0)
                {
                    return 0;
                }

                var telemedicineCallHistory =
                    await this.unitOfWork.TelemedicineCallHistory.FindAsync(x =>
                        x.TelemedicineCallHistoryId == telemedicineCallId);

                var query = $@"SELECT h.""Status""
                                --, s.""Name"", a.""FullName"", ch.""TelemedicineHistoryId"" 
                                FROM ""TelemedicineUsersHistory"" h 
                                LEFT JOIN ""TelemedicineCallHistory"" ch on ch.""TelemedicineCallHistoryId"" = h.""TelemedicineCallHistoryId""
                                LEFT JOIN ""TelemedicineUsersHistoryStatus"" s on s.""TelemedicineUsersHistoryStatus""::int = h.""Status""
                                LEFT JOIN ""Account"" a on a.""AccountId"" = h.""AccountId""
                                WHERE ch.""TelemedicineHistoryId"" IN(
                                    select ""TelemedicineHistoryId"" from ""TelemedicineCallHistory""
                                    WHERE ""TelemedicineCallHistoryId"" = {telemedicineCallId}
                                    LIMIT 1
                                )
                                 AND a.""RoleId"" = 4
                                 ORDER BY h.""TelemedicineUsersHistoryId"" DESC
                                 LIMIT 1";
                var recentStatus = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int?>(query);
                if (recentStatus == 2 || recentStatus == 4 || recentStatus == null)
                {
                    telemedicineCallHistory.Status = 3; // Call Complete

                    var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                                    x => x.TelemedicineCallHistoryId == telemedicineCallId);
                    var telemedicineUsersHistories = users.ToList();
                    if (telemedicineUsersHistories.Any())
                    {
                        foreach (var user in telemedicineUsersHistories)
                        {
                            user.InProgress = false;
                        }

                        await this.unitOfWork.TelemedicineUsersHistory.BulkUpdateAsync(telemedicineUsersHistories);
                    }
                }

                telemedicineCallHistory.InProgress = false;
                var responseId = await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(telemedicineCallHistory);
                return recentStatus == 2 || recentStatus == 4 ? responseId : -1;

                //var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                //                x => x.TelemedicineCallHistoryId == telemedicineCallId);
                //var telemedicineUsersHistories = users.ToList();
                //if (telemedicineUsersHistories.Any())
                //{
                //    foreach (var user in telemedicineUsersHistories)
                //    {
                //        user.Status = 4; // Complete
                //        user.Date = DateTime.Now;
                //    }

                //    var response = await this.unitOfWork.TelemedicineUsersHistory.BulkUpdateAsync(telemedicineUsersHistories);
                //    return response ? 1 : 0;
                //}

                // return responseId;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<string> SetTemplateAsync(int telemedicineCallId, int templateId, int accountId)
        {
            try
            {
                var activeTemplates = await this.unitOfWork.TelemedicineTemplateHistory.FindAllAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId && x.Status);
                var telemedicineTemplateHistories = activeTemplates.ToList();
                if (telemedicineTemplateHistories.Any())
                {
                    foreach (var template in telemedicineTemplateHistories)
                    {
                        template.Status = false;
                        template.ModifiedBy = accountId;
                        template.ModifiedDate = DateTime.Now;
                    }

                    await this.unitOfWork.TelemedicineTemplateHistory.BulkUpdateAsync(telemedicineTemplateHistories);
                }

                var telemedicineTemplate = new TelemedicineTemplateHistory
                {
                    CreatedBy = accountId,
                    CreatedDate = DateTime.Now,
                    Status = true,
                    TelemedicineCallHistoryId = telemedicineCallId,
                    TelemedicineTemplateId = templateId
                };
                var insertResponse = await this.unitOfWork.TelemedicineTemplateHistory.InsertAsync(telemedicineTemplate);
                return insertResponse > 0 ? (await this.unitOfWork.TelemedicineTemplate.FindAsync(x => x.TelemedicineTemplateId == templateId)).Name : null;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<string> GetTemplateAsync(int templateId)
        {
            try
            {
                return (await this.unitOfWork.TelemedicineTemplate.FindAsync(x => x.TelemedicineTemplateId == templateId)).Name;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<int> OthersCallCloseAsync(int telemedicineCallId, int receiverId)
        {
            try
            {
                var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                                x => x.TelemedicineCallHistoryId == telemedicineCallId && x.AccountId == receiverId);
                var telemedicineUsersHistories = users.ToList();

                var response = false;
                if (telemedicineUsersHistories.Any())
                {
                    foreach (var user in telemedicineUsersHistories)
                    {
                        user.Status = 4; // Complete
                        user.InProgress = false;
                        user.Date = DateTime.Now;
                    }

                    response = await this.unitOfWork.TelemedicineUsersHistory.BulkUpdateAsync(telemedicineUsersHistories);
                }

                var inProgress = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId && x.InProgress == true);
                if (!inProgress.Any())
                {
                    var telemedicine = await this.unitOfWork.TelemedicineCallHistory.FindAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId);
                    if (telemedicine != null)
                    {
                        telemedicine.InProgress = false;
                        await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(telemedicine);
                    }
                }

                return response ? 1 : 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> CallRejectAsync(int telemedicineCallId, int accountId)
        {
            try
            {
                var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(
                                x => x.TelemedicineCallHistoryId == telemedicineCallId && x.AccountId == accountId);
                var telemedicineUsersHistories = users.ToList();
                bool response = false;
                if (telemedicineUsersHistories.Any())
                {
                    foreach (var user in telemedicineUsersHistories)
                    {
                        user.Status = 3; // Rejected
                        user.Date = DateTime.Now;
                    }

                    response = await this.unitOfWork.TelemedicineUsersHistory.BulkUpdateAsync(telemedicineUsersHistories);

                }

                var inProgress = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId && x.InProgress == true);
                if (!inProgress.Any())
                {
                    var telemedicine = await this.unitOfWork.TelemedicineCallHistory.FindAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId);
                    if (telemedicine != null)
                    {
                        telemedicine.InProgress = false;
                        await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(telemedicine);
                    }
                }

                return response ? 1 : 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> CallCancelAsync(int telemedicineCallId)
        {
            try
            {
                if (telemedicineCallId == 0)
                {
                    return 0;
                }

                var telemedicineCallHistory =
                    await this.unitOfWork.TelemedicineCallHistory.FindAsync(x =>
                        x.TelemedicineCallHistoryId == telemedicineCallId);
                telemedicineCallHistory.Status = 4; // Call Cancelled
                var responseId = await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(telemedicineCallHistory);
                return responseId;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> CallCloseAllAsync(int telemedicineCallId, int accountId)
        {
            if (telemedicineCallId <= 0)
            {
                return 0;
            }

            try
            {
                var record = await this.unitOfWork.TelemedicineCallHistory.FindAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId);
                record.Status = 2;
                record.ModifiedBy = accountId;
                record.ModifiedDate = DateTime.Now;

                var responseId = await this.unitOfWork.TelemedicineCallHistory.UpdateAsync(record);
                return responseId;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<IEnumerable<AccountSessionModel>> GetJoinDeviceTokensAsync(int telemedicineCallId, int accountId)
        {
            try
            {
                var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId);

                var telemedicineUsersHistories = users.ToList();
                var receiverIds = telemedicineUsersHistories.ToList().Select(x => x.AccountId).Where(x => x != accountId);
                var callerIds = telemedicineUsersHistories.ToList().Select(x => x.CallerId).Where(x => x != accountId);

                var ids = new List<int>();
                ids.AddRange(receiverIds);
                ids.AddRange((IEnumerable<int>)callerIds);
                ids = ids.Where(x => x != accountId).ToList();

                // var ids = users.ToList().Select(x => x.CallerId).Where(x => x != accountId);
                var strAccountIds = string.Join(',', ids.ToArray());
                var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""AccountId"" IN ({strAccountIds}) AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
                var records = await this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
                return records;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<IEnumerable<AccountSessionModel>> GetProviderDeviceTokensAsync(int referenceId)
        {
            try
            {
                var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""ReferenceId"" = {referenceId} and ac.""RoleId"" = 3 AND acs.""DeviceType"" != 1 
                                AND ac.""Active"" IS TRUE
                                AND acs.""DeviceToken"" != 'string'";
                var records = await this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
                return records;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<IEnumerable<AccountSessionModel>> GetAssistantsDeviceTokensAsync(string referenceIds)
        {
            try
            {
                var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""ReferenceId"" in ({referenceIds}) and ac.""RoleId"" in ({(int)Roles.Nurse}, {(int)Roles.Receptionist}) AND acs.""DeviceType"" != 1 
                                AND ac.""Active"" IS TRUE
                                AND acs.""DeviceToken"" != 'string'";
                var records = await this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
                return records;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<IEnumerable<int>> GetAssistantIdsAsync(int providerId)
        {
            var where = $@"WHERE u.""RoleId"" in ({(int)Roles.Nurse}, {(int)Roles.Receptionist}) AND u.""Active"" IS TRUE ";
            string join = string.Empty;

            var provider = await this.unitOfWork.Providers.FindAsync(m => m.ProviderId == providerId);

            where += $@" AND pl.""ProviderId"" = {providerId} ";
            join = @" left join ""ProviderLocation"" pl on u.""ProviderLocationId"" = pl.""ProviderLocationId"" ";

            try
            {
                var query = $@"select u.""UserId"" from ""User"" u 
                               {join} {where} ";
                var userIds = await this.unitOfWork.Current.QueryAsync<int>(query);
                return userIds;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<IEnumerable<AccountSessionModel>> GetCallCloseAllDeviceTokensAsync(int telemedicineCallId, int accountId)
        {
            try
            {
                var users = await this.unitOfWork.TelemedicineUsersHistory.FindAllAsync(x => x.TelemedicineCallHistoryId == telemedicineCallId);

                // var telemedicineUsersHistories = users.Where(x => x.Status == 2 || x.Status == 1).ToList();
                var telemedicineUsersHistories = users.ToList();

                var receiverIds = telemedicineUsersHistories.ToList().Select(x => x.AccountId).Where(x => x != accountId);
                var callerIds = telemedicineUsersHistories.ToList().Select(x => x.CallerId).Where(x => x != accountId);

                var ids = new List<int>();
                ids.AddRange(receiverIds);
                ids.AddRange(callerIds);
                ids = ids.Where(x => x != accountId).ToList();

                var strAccountIds = string.Join(',', ids.ToArray());
                var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""AccountId"" IN ({strAccountIds}) AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
                var records = await this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
                return records;
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<int> GetReceiverTelemedicineId(string appointmentNo, int receiverId)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                var history = await this.unitOfWork.TelemedicineHistory.FindAsync(x => x.AppointmentId == appointment.AppointmentId);
                if (history != null)
                {
                    var query = $@"SELECT
                                        c.""TelemedicineCallHistoryId""
                                    FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
                                    --JOIN ""TelemedicineUsersHistory"" tu on tu.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
                                    WHERE h.""AppointmentId"" = '{appointment.AppointmentId}' 
                                    AND c.""InProgress"" = TRUE
                                    -- AND c.""Status"" = 1 AND ""AccountId"" = '{receiverId}'
	                                ORDER BY ""TelemedicineCallHistoryId"" DESC LIMIT 1";
                    var id = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
                    return id;
                }

                return 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<TelemedicineCallHistory> GetTelemedicineCallHistory(string appointmentNo, int receiverId)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                var history = await this.unitOfWork.TelemedicineHistory.FindAsync(x => x.AppointmentId == appointment.AppointmentId);
                if (history != null)
                {
                    var query = $@"SELECT c.* FROM ""TelemedicineCallHistory"" C 
                                    JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
                                    --JOIN ""TelemedicineUsersHistory"" tu on tu.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
                                    WHERE h.""AppointmentId"" = '{appointment.AppointmentId}' 
                                    -- AND c.""InProgress"" = TRUE
                                    -- AND c.""Status"" = 1 AND ""AccountId"" = '{receiverId}'
	                                ORDER BY ""TelemedicineCallHistoryId"" DESC LIMIT 1";
                    var teleMedicineCallHistory = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<TelemedicineCallHistory>(query);
                    return teleMedicineCallHistory;
                }

                return new TelemedicineCallHistory();
            }
            catch (Exception)
            {
                return new TelemedicineCallHistory();
            }
        }

        /// <inheritdoc />
        public async Task<int> GetCallerTelemedicineId(string appointmentNo, int callerId)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                var history = await this.unitOfWork.TelemedicineHistory.FindAsync(x => x.AppointmentId == appointment.AppointmentId);
                if (history != null)
                {
                    var query = $@"SELECT
                                        c.""TelemedicineCallHistoryId""
                                    FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
                                    JOIN ""TelemedicineUsersHistory"" tu on tu.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
                                    WHERE h.""AppointmentId"" = '{appointment.AppointmentId}' 
                                    AND c.""InProgress"" = TRUE                                    
                                    -- AND ""CallerId"" = '{callerId}'
	                                ORDER BY ""TelemedicineCallHistoryId"" DESC LIMIT 1";
                    var id = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
                    return id;
                }

                return 0;
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public Task<IEnumerable<TelemedicineUserModel>> GetNursesOrReceptionists(string appointmentNo)
        {
            var appointment = this.unitOfWork.Appointments.Find(m => m.AppointmentNo == appointmentNo);

            var and = string.Empty;

            var query = string.Empty;
            query = $@"SELECT DISTINCT ac.""AccountId"",'Dr.' || ac.""FullName""  ""FullName"", ac.""RoleId""  FROM ""Provider"" p
                                JOIN ""Account"" ac on ac.""ReferenceId"" = p.""ProviderId"" AND ac.""Active"" IS TRUE {and}								
                                WHERE ac.""RoleId"" = 3 AND ac.""ReferenceId"" IN (SELECT ""ProviderId"" FROM ""Provider"" WHERE ""ProviderId"" IN (
                                SELECT ""ProviderId"" FROM ""ProviderLocation"" WHERE ""PracticeLocationId"" IN (
                                SELECT ""PracticeLocationId"" FROM ""PracticeLocation"" WHERE ""PracticeId"" IN (
                                SELECT ""PracticeId"" FROM ""PracticeLocation"" WHERE ""PracticeLocationId"" IN (		 						
                                SELECT ""PracticeLocationId"" FROM ""ProviderLocation"" WHERE ""ProviderLocationId"" IN (		 						
                                SELECT ""ProviderLocationId"" FROM ""Appointment"" WHERE ""AppointmentNo"" = '{appointmentNo}' ))) AND ""Active"" IS TRUE	) AND ""Active"" IS TRUE)	 AND ""Active"" IS TRUE	 )";

            return this.unitOfWork.Current.QueryAsync<TelemedicineUserModel>(query);
        }

        /// <inheritdoc />
        public async Task<string> GetRoomName(string appointmentNo)
        {
            var query = $@"select p.""FirstName"", p.""MiddleName"", p.""LastName"" from ""Appointment"" a
                                JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                                WHERE a.""AppointmentNo"" = '{appointmentNo}'";
            var names = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<NameModel>(query);
            var fullName = names.FirstName.Trim() + " " +
                           (!string.IsNullOrEmpty(names.MiddleName) ? names.MiddleName.Trim() + " " : "") +
                           names.LastName.Trim();
            return fullName;
        }

        /// <inheritdoc />
        public async Task<StatusResponse> GetActiveRoomName(string appointmentNo)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                if (appointment != null)
                {
                    if (appointment.AppointmentDate.Date >= DateTime.Today)
                    {
                        var query = $@"select p.""FirstName"", p.""MiddleName"", p.""LastName"" from ""Appointment"" a
                                JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                                WHERE a.""AppointmentNo"" = '{appointmentNo}'";
                        var names = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<NameModel>(query);
                        var fullName = names.FirstName.Trim() + " " +
                                       (!string.IsNullOrEmpty(names.MiddleName) ? names.MiddleName.Trim() + " " : "") +
                                       names.LastName.Trim();

                        return new StatusResponse
                        {
                            Status = 1,
                            Message = "Appointment found and active",
                            Data = fullName
                        };
                    }

                    return new StatusResponse
                    {
                        Status = 2,
                        Message = "Appointment time expired"
                    };
                }

                return new StatusResponse
                {
                    Status = 3,
                    Message = "Appointment not found"
                };
            }
            catch (Exception ex)
            {
                return new StatusResponse
                {
                    Status = 4,
                    Message = ex.Message
                };
            }
        }

        /// <inheritdoc />
        public async Task<BasicPatientDetailsModel> GetPatientDetails(string appointmentNo)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                var patient = await this.unitOfWork.Patients.FindAsync(x => x.PatientId == appointment.PatientId);
                return new BasicPatientDetailsModel
                {
                    CountryId = patient.CountryId ?? 0,
                    Email = patient.Email,
                    Mobile = patient.Mobile,
                    FullName = patient.FullName
                };
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public async Task<BasicPatientDetailsModel> GetProviderDetails(string appointmentNo)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                var provider = await this.unitOfWork.Providers.FindAsync(x => x.ProviderId == appointment.ProviderId);
                return new BasicPatientDetailsModel
                {
                    CountryId = provider.CountryId ?? 0,
                    Email = provider.Email,
                    Mobile = provider.Mobile,
                    FullName = "Dr. " + provider.FullName
                };
            }
            catch (Exception)
            {
                return null;
            }
        }

        /// <inheritdoc />
        public Task<IEnumerable<int>> GetNoOfCalls(int appointmentId)
        {
            var query = $@"SELECT
	                                DISTINCT C.""TelemedicineCallHistoryId""
                                FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
	                                WHERE h.""AppointmentId"" = {appointmentId} ORDER BY C.""TelemedicineCallHistoryId"" DESC ";
            return this.unitOfWork.Current.QueryAsync<int>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<CallHistoryModel>> GetCallHistory(int appointmentId, int telemedicineCallHistoryId)
        {
            var query = $@"SELECT
	                                h.""AppointmentId"",
	                                C.""TelemedicineCallHistoryId"",
	                                C.""Status"",
	                                C.""CreatedDate"",
	                                C.""ModifiedDate"",
                                    r.""RoleName"",
                                    a.""FullName"",
                                    cr.""RoleName"" AS ""CallerRoleName"",
                                    ca.""FullName"" AS ""CallerFullName"",
                                    u.""Status"" as ""UserCallStatus"",
                                    u.""Date"",
                                    a.""AccountId"",
                                    h.""CallType""
                                FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
	                                LEFT JOIN ""TelemedicineUsersHistory"" u ON u.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
	                                LEFT JOIN ""Account"" A ON A.""AccountId"" = u.""AccountId"" 
	                                LEFT JOIN ""Account"" CA ON CA.""AccountId"" = u.""CallerId"" 
	                                LEFT JOIN ""Role"" r on r.""RoleId"" = a.""RoleId""
	                                LEFT JOIN ""Role"" cr on cr.""RoleId"" = ca.""RoleId""
	                                WHERE h.""AppointmentId"" = {appointmentId} AND c.""TelemedicineCallHistoryId"" = {telemedicineCallHistoryId}
                                    ORDER BY u.""TelemedicineUsersHistoryId"" DESC ";
            return this.unitOfWork.Current.QueryAsync<CallHistoryModel>(query);
        }

        /// <inheritdoc />
        public Task<TelemedicineUserModel> GetUserAccount(int accountId)
        {
            var query = $@"select ""FullName"", ""Email"" from ""Account""
                                WHERE ""AccountId"" = '{accountId}'";
            return this.unitOfWork.Current.QuerySingleOrDefaultAsync<TelemedicineUserModel>(query);
        }

        /// <inheritdoc />
        public async Task<TelemedicineDomainModel> GetActiveDomain(string appointmentNo)
        {
            var record = await this.unitOfWork.TelemedicineDomain.FindAsync(x => x.IsActive);

            var data = new TelemedicineDomainModel
            {
                Domain = record.Domain,
                IsAuthenticationRequired = record.IsAuthenticationRequired
            };

            if (!string.IsNullOrEmpty(appointmentNo))
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentNo == appointmentNo);

                var account = await this.unitOfWork.Accounts.FindAsync(m => m.ReferenceId == appointment.PatientId && m.RoleId == (int)Roles.Patient);

                data.AccountId = account != null ? account.AccountId : 0;
                data.FullName = account != null ? account.FullName : null;
            }

            return data;
        }

        /// <inheritdoc />
        public async Task<List<TelemedicineTemplateModel>> GetAllTemplates()
        {
            var records = await this.unitOfWork.TelemedicineTemplate.FindAllAsync();
            return records.Select(record => new TelemedicineTemplateModel { Id = record.TelemedicineTemplateId, Name = record.Name }).ToList();
        }

        /// <inheritdoc />
        public Task<TelemedicineAppointmentModel> GetAppointmentDetails(string appointmentNo)
        {
            var query = $@"select a.""EncounterType"", a.""AppointmentId"", 
                                p.""FullName"" AS ""PatientFullName"",
                                p.""FirstName"" AS ""PatientFirstName"",
                                pp.""FullName"" AS ""ProviderFullName"",
                                pp.""FirstName"" AS ""ProviderFirstName"",
                                patAcc.""AccountId"" AS ""PatientAccountId"",
                                proAcc.""AccountId"" AS ""ProviderAccountId""
                                FROM ""Appointment"" a
                                JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                                JOIN ""Account"" patAcc on (patAcc.""ReferenceId"" = p.""PatientId"" AND patAcc.""RoleId"" = 4)
                                JOIN ""Provider"" pp on pp.""ProviderId"" = a.""ProviderId""
                                JOIN ""Account"" proAcc on (proAcc.""ReferenceId"" = pp.""ProviderId"" AND proAcc.""RoleId"" = 3)
                                WHERE a.""AppointmentNo"" = '{appointmentNo}'";
            return this.unitOfWork.Current.QuerySingleAsync<TelemedicineAppointmentModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetDoctorDeviceTokens(string appointmentNo)
        {
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Appointment"" a
                                    JOIN ""Account"" ac on ac.""ReferenceId"" = a.""ProviderId""
                                    JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                    WHERE a.""AppointmentNo"" = '{appointmentNo}' AND ac.""RoleId"" = 3 AND acs.""DeviceType"" != 1
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string' ";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetPatientDeviceTokens(string appointmentNo)
        {
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Appointment"" a
                                    JOIN ""Account"" ac on ac.""ReferenceId"" = a.""PatientId""
                                    JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                    WHERE a.""AppointmentNo"" = '{appointmentNo}'
                                        AND ac.""RoleId"" = 4 
                                        AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string' ";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetPatientIosDeviceTokens(string appointmentNo)
        {
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Appointment"" a
                                    JOIN ""Account"" ac on ac.""ReferenceId"" = a.""PatientId""
                                    JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                    WHERE a.""AppointmentNo"" = '{appointmentNo}' AND ac.""RoleId"" = 4 AND acs.""DeviceType"" = 3 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<AccountSessionModel>> GetNurseOrReceptionistDeviceTokensAlt(int roleId, int accountId)
        {
            var query = $@"select DISTINCT acs.""DeviceToken"", acs.""DeviceType"" from ""Account"" ac
                                JOIN ""AccountSession"" acs on acs.""AccountId"" = ac.""AccountId""
                                WHERE ac.""AccountId"" = {accountId} AND ac.""RoleId"" = {roleId} AND acs.""DeviceType"" != 1 
                                        AND ac.""Active"" IS TRUE
                                        AND acs.""DeviceToken"" != 'string'";
            return this.unitOfWork.Current.QueryAsync<AccountSessionModel>(query);
        }

        /// <inheritdoc />
        public Task<int> GetPatientAccountId(string appointmentNo)
        {
            var query = $@"select ac.""AccountId"" from ""Appointment"" a
                                    JOIN ""Account"" ac on ac.""ReferenceId"" = a.""PatientId""
                                    WHERE a.""AppointmentNo"" = '{appointmentNo}' LIMIT 1 ";
            return this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
        }

        /// <inheritdoc />
        public Task<int> GetDoctorAccountId(string appointmentNo)
        {
            var query = $@"select ac.""AccountId"" from ""Appointment"" a
                                    JOIN ""Account"" ac on ac.""ReferenceId"" = a.""ProviderId""
                                    WHERE a.""AppointmentNo"" = '{appointmentNo}' LIMIT 1 ";
            return this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
        }

        /// <inheritdoc />
        public Task<IEnumerable<RoomDetails>> FetchRoomNamesAsync(List<int> appointmentIds)
        {
            var query = $@"select w.""WebTelemedicineId"", a.""AppointmentNo"" as ""RoomName"" from ""WebTelemedicine"" w
                                LEFT JOIN ""Appointment"" a on a.""AppointmentId"" = w.""AppointmentId""
                                LEFT JOIN ""Account"" ac on ac.""ReferenceId"" = a.""ProviderId""
                                WHERE w.""AppointmentId"" IN ({string.Join(',', appointmentIds)}) AND w.""Status"" <> 2 AND ac.""RoleId"" = 3 AND w.""CreatedDate"" >= NOW() - INTERVAL '2 minutes'";

            return this.unitOfWork.Current.QueryAsync<RoomDetails>(query);
        }
    }
}