namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Hims.Domain.Configurations;
    using Hims.Domain.Entities;
    using Hims.Domain.Entities.Enums;
    using Hims.Shared.UserModels.Queue;
    using Newtonsoft.Json;

    using AvailabilityModel = Hims.Shared.UserModels.ProviderAvailability;

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

        /// <summary>
        /// The amazon s3 configuration.
        /// </summary>
        private readonly IAmazonS3Configuration configuration;

        /// <summary>
        /// the provider location service.
        /// </summary>
        private readonly IProviderLocationService providerLocationService;


        /// <summary>
        /// Initializes a new instance of the <see cref="QueueServices"/> class.
        /// </summary>
        /// <param name="unitOfWork">The unit of work.</param>
        /// <param name="configuration">The configuration.</param>
        public QueueServices(IUnitOfWork unitOfWork, IAmazonS3Configuration configuration, IProviderLocationService providerLocationService)
        {
            this.unitOfWork = unitOfWork;
            this.configuration = configuration;
            this.providerLocationService = providerLocationService;
        }

        public async Task<IEnumerable<DoctorModel>> GetDoctorsAsync(int locationId, int? providerId, List<int>? appointmentIds, bool isMetaInfoOnly)
        {
            var where = $@"a.""Status"" != 'C' AND a.""LocationId"" = {locationId} ";

            //if (appointmentIds != null && appointmentIds.Count() > 0)
            //{
            //    where += $@" AND a.""AppointmentId"" IN ({string.Join(",", appointmentIds)}) ";
            //}

            if (providerId != null)
            {
                where += $@" AND a.""ProviderId"" ={providerId} ";
            }

            if (!isMetaInfoOnly)
            {
                where += $@" AND a.""QueueStatusId"" IN (1, 2, 3, 4) ";
            }

            where += $@" AND a.""AppointmentDate"" = CURRENT_DATE";

            var query = $@"SELECT distinct p.""ProviderId"",
	                        p.""FullName"",
                            d.""DepartmentName"",
                            R.""RoomName"",
                            W.""WardName"" ,
                            F.""FloorName"",
                            p.""Specializations"",
                            --string_agg(DISTINCT Sz.""SpecializationName"", ',') as ""Specialization"",
                           (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.configuration.BucketURL}', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE NULL END) AS ""ThumbnailUrl""
                        FROM
	                        ""Appointment"" a
	                        JOIN ""Provider"" p on p.""ProviderId"" = a.""ProviderId""
	                        JOIN ""Department"" d on d.""DepartmentId"" = p.""DepartmentId""
	                        left join ""ProviderConsultationRoom"" PCR on (PCR.""ProviderId"" = p.""ProviderId"" and PCR.""LocationId"" = {locationId})
	                        left join ""Room"" R on R.""RoomId"" = PCR.""RoomId""
	                        left join ""Ward"" W on W.""WardId"" = R.""WardId""
	                        left join ""Floor"" F on F.""FloorId"" = W.""FloorId"" 
                            --left join ""Specialization"" Sz on Sz.""SpecializationId"" = ANY(p.""Specializations"") AND Sz.""Active"" IS TRUE

                        WHERE {where}
                --group by p.""ProviderId"",d.""DepartmentName"",R.""RoomName"",W.""WardName"",F.""FloorName""	";

            var doctors = await this.unitOfWork.Current.QueryAsync<DoctorModel>(query);

            //var specializations = await this.unitOfWork.Specializations.FindAllAsync();
            //foreach (var doctor in doctors)
            //{
            //    try
            //    {
            //        if (doctor.Specializations != null && doctor.Specializations.Count() > 0)
            //        {
            //            //doctor.Specialization = string.Join(",", specializations.Where(x => doctor.Specializations.Contains((int)x.SpecializationIconId)));
            //        }
            //    }
            //    catch (Exception ex)
            //    {
            //        //ignore
            //    }
            //}

            return doctors;
        }

        public async Task<MobileFetchModel> MobileFetchAsync(int patientId)
        {
            var where = $@" a.""AppointmentDate"" = CURRENT_DATE AND a.""PatientId"" = {patientId} AND a.""QueueStatusId"" NOT IN(5,6,7) AND a.""Status"" != 'C'  ";

            var query = $@"SELECT
	                        p.""ProviderId"",
	                        p.""FullName"",
	                        d.""DepartmentName"",
                            a.""AppointmentTime"",
                            a.""SpecializationId"",
                            a.""VisitTypeId"",
                            a.""TokenNumber"",
                            a.""WaitingCount"",
                            a.""LocationId"",
                            q.""Name"" ""QueueStatus"",
                            a.""QueueStatusId"",
                            (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.configuration.BucketURL}', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE NULL END) AS ""ThumbnailUrl""
                        FROM
	                        ""Appointment"" a
	                        JOIN ""Provider"" p on p.""ProviderId"" = a.""ProviderId""
	                        JOIN ""Department"" d on d.""DepartmentId"" = p.""DepartmentId""
	                        JOIN ""QueueStatus"" q on q.""QueueStatusId"" = a.""QueueStatusId""
                        WHERE {where} ORDER BY a.""AppointmentTime"" ASC LIMIT 1";

            var details = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<MobileFetchModel>(query);

            if (details != null)
            {
                //var visitTypeQuery = $@"SELECT ""VisitTypeId"" from ""VisitType"" WHERE LOWER(""VisitorName"") = 'out patient'";
                //var visitTypeId = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(visitTypeQuery);

                //var providerLocation = await this.unitOfWork.ProviderLocations.FindAllAsync(x => x.ProviderId == details.ProviderId && x.LocationId == details.LocationId);
                //if (providerLocation != null && providerLocation.Count() > 0 && !string.IsNullOrEmpty(providerLocation.First().Duration))
                //{


                //    if (visitTypeId > 0)
                //    {
                //        var duration = JsonConvert.DeserializeObject<IEnumerable<DurationModel>>(providerLocation.First().Duration).ToList();
                //        var outPatientDuration = duration.Find(x => x.TypeId == visitTypeId);
                //        details.WaitingPerPersonInMinutes = outPatientDuration != null ? outPatientDuration.Value : 0;
                //    }
                //}
                //var visitType = new List<AvailabilityModel.AvailabilityModel>();

                //AvailabilityModel.AvailabilityModel objVisit = new AvailabilityModel.AvailabilityModel();

                //visitType = (List<AvailabilityModel.AvailabilityModel>)await this.providerLocationService.GetVisitTypes(details.ProviderId, details.LocationId, details.SpecializationId, details.VisitTypeId);
                //if (visitType.Count > 0)
                //{
                //    objVisit = visitType[0];
                //    details.WaitingPerPersonInMinutes = objVisit != null ? objVisit.Duration : 0;
                //}
                //else {
                //    return details;
                //}

                //var waitingQueryWhere = $@"a.""AppointmentDate"" = CURRENT_DATE AND a.""ProviderId"" = {details.ProviderId} AND a.""QueueStatusId"" IN(3,4,7) AND a.""LocationId""={details.LocationId} and a.""Active"" is true";
                //var waitingQuery = $@"SELECT a.""TokenNumber"" FROM ""Appointment"" a
                //                        WHERE {waitingQueryWhere}";


                //var waitingDetails = await this.unitOfWork.Current.QueryAsync<int>(waitingQuery);

                //if (waitingDetails != null && waitingDetails.Count() > 0)
                //{
                //    var waitingPatients = waitingDetails.Where(x => x < details.TokenNumber && x!=0);
                //    details.PatientsWaitingCount = waitingPatients.Count();
                //}

                var currentTokenInRoomQuery = $@"SELECT a.""TokenNumber"" FROM ""Appointment"" a
                                        WHERE a.""AppointmentDate"" = CURRENT_DATE AND a.""ProviderId"" = {details.ProviderId} AND a.""QueueStatusId"" = 2";
                var currentTokenInRoom = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(currentTokenInRoomQuery);
                if (currentTokenInRoom != 0)
                {
                    details.CurrentTokenNumber = currentTokenInRoom;
                }
            }

            return details;
        }

        public async Task<int?> GetCallingCubicleId(int appointmentId)
        {
            var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);
            return appointment.CubicleId;
        }

        public async Task<QueueStatusModel> GetUserCubicle(int accountId)
        {
            var assignedQuery = $@" SELECT ""CubicleId"", ""Name"" ""CubicleName"" FROM ""Cubicle"" WHERE ""AccountId"" = {accountId} ";
            var cubicles = await this.unitOfWork.Current.QueryAsync<QueueStatusModel>(assignedQuery);

            if (cubicles == null)
            {
                return null;
            }

            var first = cubicles.First();
            return new QueueStatusModel
            {
                CubicleId = first.CubicleId,
                CubicleName = first.CubicleName
            };
        }

        public async Task<IEnumerable<QueueStatusModel>> GetFreeCubicleId(int locationId, int appointmentId)
        {

            var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);

            var assignedQuery = $@" SELECT ""CubicleId"", ""Name"" ""CubicleName"" FROM ""Cubicle"" WHERE ""ProviderId"" = {appointment.ProviderId} ";
            var cubicles = await this.unitOfWork.Current.QueryAsync<QueueStatusModel>(assignedQuery);

            if (cubicles.Count() <= 0)
            {
                return new List<QueueStatusModel>();
            }

            var assignedSubQuery = $@" SELECT ""CubicleId"" FROM ""Cubicle"" WHERE ""ProviderId"" = {appointment.ProviderId} ";
            var cubiclesIds = cubicles.Select(x => x.CubicleId).ToArray();
            var query = $@"SELECT DISTINCT a.""CubicleId"", a.""QueueStatusId"", c.""Name"" ""CubicleName"" FROM ""Appointment"" a
                        JOIN ""QueueStatus"" q on q.""QueueStatusId"" = a.""QueueStatusId""
                        JOIN ""Cubicle"" c on c.""CubicleId"" = a.""CubicleId""
                        WHERE a.""LocationId"" = {locationId} AND q.""QueueStatusId"" IN (1, 2)
                        AND a.""ProviderId"" = {appointment.ProviderId}
                        AND a.""AppointmentDate"" = CURRENT_DATE
                        AND a.""CubicleId"" IN ({string.Join(',', assignedSubQuery)}) ";
            var assignedCubicles = await this.unitOfWork.Current.QueryAsync<QueueStatusModel>(query);

            var unassigned = cubiclesIds.Where(x => assignedCubicles.Where(y => y.CubicleId == x).Count() <= 0)
                .Select(x => new QueueStatusModel
                {
                    CubicleId = x,
                    QueueStatusId = null,
                    CubicleName = cubicles.FirstOrDefault(y => y.CubicleId == x).CubicleName
                }).ToList();

            if (assignedCubicles.Any(x => x.QueueStatusId == 1))
            {
                foreach (var cubicle in assignedCubicles.Where(x => x.QueueStatusId == 1))
                {
                    unassigned.Add(new QueueStatusModel
                    {
                        CubicleId = cubicle.CubicleId,
                        QueueStatusId = 1,
                        CubicleName = cubicle.CubicleName,
                    });
                }
            }

            return unassigned;
        }

        public async Task<int> CallPatientAsync(int appointmentId, int cubicleId)
        {
            var query = $@" UPDATE ""Appointment"" SET ""QueueStatusId"" = 1, ""CubicleId"" = {cubicleId} WHERE ""AppointmentId"" = {appointmentId} AND ""QueueStatusId"" != 5";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<int> WaitPatientAsync(int appointmentId)
        {
            var waitCount = 0;
            var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);
            if (appointment != null)
            {
                waitCount = appointment.WaitingCount ?? 0;
            }
            var query = $@" UPDATE ""Appointment"" SET ""CubicleId"" = NULL, ""QueueStatusId"" = 4, ""WaitingCount"" = {waitCount + 1}, ""WaitingPriority"" = {waitCount + 1}  WHERE ""AppointmentId"" = {appointmentId} AND ""QueueStatusId"" = 1";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<int> ReducePriorityAsync(int providerId, int locationId)
        {
            var query = $@"Update ""Appointment"" SET ""WaitingPriority"" = ""WaitingPriority"" - 1  WHERE ""AppointmentDate""::DATE = CURRENT_DATE AND ""ProviderId"" = {providerId} AND ""LocationId"" = {locationId} AND ""QueueStatusId"" = 4 AND ""WaitingPriority"" > 0 ";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }


        public async Task<IEnumerable<string>> GetAndroidDeviceTokenByAppointmentId(int appointmentId)
        {
            var query = $@"SELECT DISTINCT ass.""DeviceToken"" from ""Appointment"" a
                            JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                            JOIN ""Account"" aa on ( aa.""ReferenceId"" = p.""PatientId"" AND aa.""RoleId"" = 4 )
                            JOIN ""AccountSession"" ass on (ass.""AccountId"" = aa.""AccountId"" and (ass.""DeviceType"" = 2 OR ass.""DeviceType"" = 3))
                            WHERE a.""AppointmentId"" = {appointmentId} AND ass.""DeviceToken"" IS NOT NULL";
            return await this.unitOfWork.Current.QueryAsync<string>(query);
        }

        public async Task<IEnumerable<string>> GetQueueWebTokensId(List<int> appointmentIds)
        {
            var ids = string.Join(',', appointmentIds.Select(x => x.ToString()));
            var query = $@"SELECT DISTINCT ass.""WebToken"" from ""Account"" aa
                            JOIN ""AccountSession"" ass on (ass.""AccountId"" = aa.""AccountId"" and ass.""DeviceType"" = 1)
                            WHERE aa.""RoleId"" IN (1,2) AND ass.""WebToken"" IS NOT NULL";
            return await this.unitOfWork.Current.QueryAsync<string>(query);
        }

        public async Task<IEnumerable<string>> GetPatientsAndroidDeviceTokensByProviderId(int providerId, int locationId)
        {
            var query = $@"SELECT DISTINCT ass.""DeviceToken"" from ""Appointment"" a
                            JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                            JOIN ""Account"" aa on ( aa.""ReferenceId"" = p.""PatientId"" AND aa.""RoleId"" = 4 )
                            JOIN ""AccountSession"" ass on (ass.""AccountId"" = aa.""AccountId"" and (ass.""DeviceType"" = 2 OR ass.""DeviceType"" = 3))
                            WHERE a.""AppointmentDate"" = CURRENT_DATE AND a.""QueueStatusId"" = 4 AND a.""ProviderId"" = {providerId} AND a.""LocationId"" = {locationId} 
                            AND ass.""DeviceToken"" IS NOT NULL";
            return await this.unitOfWork.Current.QueryAsync<string>(query);
        }

        public async Task<int> CheckInAsync(int appointmentId)
        {
            var record = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);
            if (record == null)
            {
                return -1;
            }
            if (record.QueueStatusId == 6 || record.QueueStatusId == 7)
            {
                return -1;
            }

            record.QueueStatusId = 2;
            //record.QueueStartDate = DateTime.Now;
            var response = await this.unitOfWork.Appointments.UpdateAsync(record);
            return response;
        }

        public async Task<int> AcceptAsync(int appointmentId)
        {
            var record = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId && x.QueueStatusId == 7);
            if (record == null)
            {
                return -1;
            }
            record.QueueStatusId = 4;
            record.QueueStartDate = DateTime.Now;
            var response = await this.unitOfWork.Appointments.UpdateAsync(record);
            return response;
        }

        public async Task<int> GetProviderIdByAppointmentId(int appointmentId)
        {
            var provider = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);
            return provider.ProviderId;
        }

        public async Task<int> GetProviderLocationIdByAppointmentId(int appointmentId)
        {
            var provider = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);
            return provider.LocationId;
        }

        public async Task<ShortAppointmentModel> GetAppointmentAsync(int appointmentId)
        {
            var query = $@"SELECT a.""QueueStatusId"",a.""ProviderId"", a.""TokenNumber"", a.""LocationId"", p.""FullName"" FROM ""Appointment"" a
                        JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                        WHERE a.""AppointmentId"" = {appointmentId}";
            return await this.unitOfWork.Current.QuerySingleAsync<ShortAppointmentModel>(query);
        }

        public async Task<IEnumerable<AppointmentStatusModel>> GetAppointmentsAsync(int providerId, int locationId)
        {
            var query = $@"SELECT A
	                        .""AppointmentId"",
	                        A.""TokenNumber"",
	                        A.""PatientId"",
	                        A.""WaitingCount"",
	                        A.""WaitingPriority"",
	                        P.""FullName"" ""PatientName"",
	                        A.""ProviderId"",
	                        A.""LocationId"",
	                        a.""QueueStatusId"",
	                        q.""Name"" ""QueueStatus"",
	                        a.""CubicleId"",
	                        c.""Name"" ""CubicleName""
                        FROM
	                        ""Appointment""
	                        A JOIN ""Patient"" P ON P.""PatientId"" = A.""PatientId""
	                        LEFT JOIN ""QueueStatus"" q ON q.""QueueStatusId"" = A.""QueueStatusId""
	                        LEFT JOIN ""Cubicle"" C ON C.""CubicleId"" = A.""CubicleId""
	                        WHERE a.""AppointmentDate""::DATE = CURRENT_DATE AND a.""ProviderId"" = {providerId} AND a.""LocationId"" = {locationId} ";
            return await this.unitOfWork.Current.QueryAsync<AppointmentStatusModel>(query);
        }

        public async Task<int> CancelAsync(int appointmentId)
        {
            var query = $@" UPDATE ""Appointment"" SET ""QueueStatusId"" = 7, ""WaitingCount"" = NULL WHERE ""AppointmentId"" = {appointmentId} AND ""QueueStatusId"" = 4";

            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<int> SaveWebTokenAsync(WebTokenModel model)
        {
            var found = await this.unitOfWork.AccountSessions.FindAllAsync(x => x.AccountId == model.Id && x.DeviceType == 1);
            if (found.Count() > 0)
            {
                var first = found.First();
                first.WebToken = model.Token;
                first.Active = true;
                var updateResponse = await this.unitOfWork.AccountSessions.UpdateAsync(first);
                return updateResponse;
            }

            return -1;
        }

        public async Task<int> CompletePatientAsync(int appointmentId)
        {
            var record = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);

            if (record == null)
            {
                return -1;
            }
            if (record.QueueStatusId == 6 || record.QueueStatusId == 7)
            {
                return -1;
            }

            var actualQueueStatusId = record.QueueStatusId;
            record.QueueStatusId = 5;
            record.QueueEndDate = DateTime.Now;
            record.IsEncounter = true;
            var response = await this.unitOfWork.Appointments.UpdateAsync(record);

            if (actualQueueStatusId != 2)
            {
                return -2;
            }
            return response;
        }

        public async Task<IEnumerable<PatientModel>> GetPatientsAsync(int locationId, List<int> providerIds, QueueReceiveModel model)
        {
            var inCondition = model.IsMetaInfoOnly == true ? null : $@" AND q.""QueueStatusId"" NOT IN (5, 6, 7)";
            var where = $@" a.""Status"" != 'C' AND a.""LocationId"" = {locationId} {inCondition} ";
            if (providerIds.Count > 0)
            {
                where += $@" AND a.""ProviderId"" IN ({string.Join(",", providerIds)}) ";
            }

            where += $@" AND a.""AppointmentDate"" = CURRENT_DATE";

            var query = $@"SELECT * FROM (SELECT
                            a.""ProviderId"",
                            a.""AppointmentTime"",
                            a.""AppointmentEndTime"",
                            a.""TokenNumber"",
                            a.""AppointmentId"",
                            a.""WaitingCount"",
                            a.""WaitingPriority"",
	                        p.""PatientId"",
	                        p.""FullName"",
                            p.""Gender"",
                            p.""UMRNo"" ""UmrNo"",
                            q.""QueueStatusId"",
                            q.""Name"" ""QueueStatus"",
                            c.""Name"" ""CubicleName"",
                            (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.configuration.BucketURL}', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE NULL END) AS ""ThumbnailUrl""
                        FROM
	                        ""Appointment"" a
	                        JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                            JOIN ""QueueStatus"" q on q.""QueueStatusId"" = a.""QueueStatusId""
                            LEFT JOIN ""Cubicle"" c on c.""CubicleId"" = a.""CubicleId""
                        WHERE {where}) A
                        LEFT JOIN LATERAL (
                          SELECT
                            to_char(aa.""Date"", 'HH24:MI') ""StartDate"",
                            aa.""IgnoreForQueue""
                          FROM ""AppointmentCheckPoints"" aa
                          WHERE
                            aa.""AppointmentId"" = A.""AppointmentId"" and ""Action"" = 'start_encounter'
                          ORDER BY aa.""AppointmentCheckPointsId"" 
                          LIMIT 1
                        ) e2 ON true
                        LEFT JOIN LATERAL (
                          SELECT
                            to_char(aa.""Date"", 'HH24:MI') ""CompleteDate"",
                            aa.""IgnoreForQueue""
                          FROM ""AppointmentCheckPoints"" aa
                          WHERE
                            aa.""AppointmentId"" = A.""AppointmentId"" and ""Action"" = 'complete_encounter'
                          ORDER BY aa.""AppointmentCheckPointsId"" 
                          LIMIT 1
                        ) e3 ON true
                    ";

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

        public async Task<IEnumerable<PatientModel>> GetPatientsForQueueAsync(int providerId, int locationId)
        {
            var where = $@"a.""LocationId"" = {locationId} AND q.""QueueStatusId"" NOT IN (5, 6, 7) AND a.""ProviderId"" = {providerId} ";
            where += $@" AND a.""AppointmentDate"" = CURRENT_DATE";

            var query = $@"SELECT
                            a.""AppointmentTime"",
                            a.""AppointmentEndTime"",
                            a.""PatientId"",
                            q.""QueueStatusId"",
                            a.""WaitingCount""
                        FROM
	                        ""Appointment"" a
	                        JOIN ""Patient"" p on p.""PatientId"" = a.""PatientId""
                            JOIN ""QueueStatus"" q on q.""QueueStatusId"" = a.""QueueStatusId""
                        WHERE {where} ";

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

        public async Task<int> UpdateExpiredPatientsAsync(int locationId, List<int> providerIds, QueueReceiveModel model)
        {
            var where = $@"""LocationId"" = {locationId} AND ""AppointmentTime""::TIME < '{model.StartTime}'::TIME AND ""QueueStatusId"" NOT IN (1, 2, 5)";
            if (providerIds.Count > 0)
            {
                where += $@" AND ""ProviderId"" IN ({string.Join(",", providerIds)}) ";
            }

            where += $@" AND ""AppointmentDate"" = CURRENT_DATE";

            var query = $@" UPDATE ""Appointment"" SET ""QueueStatusId"" = 6 WHERE {where}";

            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        public async Task<int> MoveToQueuePatientAsync(int appointmentId)
        {
            var record = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);

            if (record == null)
            {
                return -1;
            }
            if (record.QueueStatusId != 2)
            {
                return -1;
            }

            record.QueueStatusId = 4;
            record.CubicleId = null;
            var response = await this.unitOfWork.Appointments.UpdateAsync(record);
            return response;
        }
    }
}