namespace Hims.Api.Controllers
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using AutoMapper;
    using Domain.Configurations;
    using Domain.Helpers;
    using Domain.Services;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.SignalR;

    using Models.Appointment;
    using Npgsql;
    using Senders;
    using Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.Library.Enums;
    using Shared.UserModels.Filters;
    using Utilities;

    using Hims.Api.Hubs;
    using Hims.Api.Models;
    using Hims.Shared.UserModels.Common;
    using Newtonsoft.Json;
    using Hims.Api.Helper;
    using System.Web;
    using Hims.Shared.UserModels.PayU;
    using Hims.Domain.Entities;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Domain.Entities.Enums;
    using Dapper;
    using Hangfire;
    using FireSharp.Interfaces;
    using FireSharp;
    using FireSharp.Config;
    using Hims.Shared.UserModels;
    using Hims.Api.Models.Patient;
    using System.IO;
    using Microsoft.AspNetCore.Http;
    using Hims.Shared.UserModels.WebNotification;
    using System.Net;
    using System.Collections;
    using Hims.Shared.UserModels.Slots;
    using Newtonsoft.Json.Serialization;
    using FireSharp.Response;

    /// <inheritdoc />
    [Route("api/appointments")]
    [Consumes("application/json")]
    [Produces("application/json")]
    public class AppointmentsController : BaseController
    {
        /// <summary>
        /// The appointment services.
        /// </summary>
        private readonly IAppointmentService appointmentsServices;

        /// <summary>
        /// The web notification service
        /// </summary>
        private readonly IWebNotificationService webNotificationService;

        /// <summary>
        /// The account session services.
        /// </summary>
        private readonly IAccountSessionService accountSessionServices;

        /// <summary>
        /// the patient service
        /// </summary>
        private readonly IPatientService patientServices;

        /// <summary>
        /// The push notification helper.
        /// </summary>
        private readonly IPushNotificationHelper pushNotificationHelper;

        /// <summary>
        /// The appointment log services.
        /// </summary>
        private readonly IAppointmentLogService appointmentLogServices;

        /// <summary>
        /// The Web Telemedicine Service.
        /// </summary>
        private readonly IWebTelemedicineService webTelemedicineService;

        /// <summary>
        /// The doctor device details services.
        /// </summary>
        private readonly IDoctorDeviceDetailsService doctorDeviceServices;

        /// <summary>
        /// The patient device details services.
        /// </summary>
        private readonly IPatientDeviceDetailsService patientDeviceServices;

        /// <summary>
        /// The patient device details services.
        /// </summary>
        private readonly IVideoCallHistoryService videoHistoryServices;

        /// <summary>
        /// The application configuration.
        /// </summary>
        private readonly IApplicationConfiguration applicationConfiguration;

        /// <summary>
        /// The AES helper.
        /// </summary>
        private readonly IAESHelper aesHelper;

        /// <summary>
        /// The SMS sender.
        /// </summary>
        private readonly ISMSSender smsSender;

        /// <summary>
        /// The mapper.
        /// </summary>
        private readonly IMapper mapper;

        /// <summary>
        /// The email sender.
        /// </summary>
        private readonly IEmailSender emailSender;

        /// <summary>
        /// The amazon s 3 configuration.
        /// </summary>
        private readonly IAmazonS3Configuration amazonS3Configuration;

        /// <summary>
        /// The hub context.
        /// </summary>
        private readonly IHubContext<CommunicationHub> hubContext;

        /// <summary>
        /// The pay u configuration.
        /// </summary>
        private readonly IPayUConfiguration payUConfiguration;

        /// <summary>
        /// The timeline service.
        /// </summary>
        private readonly ITimelineService timelineService;

        /// <summary>
        /// The auditlog services.
        /// </summary>
        private readonly IAuditLogService auditLogServices;

        /// <summary>
        /// The provider bank account services.
        /// </summary>
        private readonly IProviderBankAccountService providerBankAccountServices;

        /// <summary>
        /// The document helper.
        /// </summary>
        private readonly IDocumentHelper documentHelper;

        /// <summary>
        /// The url shortner helper.
        /// </summary>
        private readonly IURLShortnerHelper uRLShortnerHelper;

        /// <summary>
        /// The patient medication service
        /// </summary>
        private readonly IPatientEncounterService patientEncounterService;

        /// <summary>
        /// the provider service.
        /// </summary>
        private readonly IProviderService providerService;

        private readonly ISettingService settingService;

        /// <summary>
        /// The salucro configuration.
        /// </summary>
        private readonly ISalucroConfiguration salucroConfiguration;

        /// <summary>
        /// The appointment transaction service.
        /// </summary>
        private readonly IAppointmentTransactionService appointmentTransactionService;

        /// <summary>
        /// The wallet service.
        /// </summary>
        private readonly IWalletService walletService;

        /// <summary>
        /// The payU service.
        /// </summary>
        private readonly IPayUService payUService;

        /// <summary>
        /// The salucro helper.
        /// </summary>
        private readonly ISalucroHelper salucroHelper;

        /// <summary>
        /// The payU helper.
        /// </summary>
        private readonly IPayUHelper payUHelper;

        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <summary>
        /// The appointment log services.
        /// </summary>
        private readonly IPaymentInitiationLogService paymentInitiationLogService;

        private readonly AppointmentHelper appointmentHelper;

        private readonly IFirebaseClient client;

        /// <summary>
        /// The running environment.
        /// </summary>
        private readonly IRunningEnvironment runningEnvironment;

        /// <summary>
        /// The FTP upload helper.
        /// </summary>
        private readonly IFtpUploadHelper ftpUploadHelper;

        /// <summary>
        /// The patient document services.
        /// </summary>
        private readonly IPatientDocumentService patientDocumentServices;

        /// <summary>
        /// The patient insurance services.
        /// </summary>
        private readonly IPatientInsuranceService patientInsuranceServices;

        /// <summary>
        /// The patient emergency services.
        /// </summary>
        private readonly IPatientEmergencyService patientEmergencyServices;

        /// <summary>
        /// The scan service.
        /// </summary>
        private readonly IScanLogService scanLogService;
        /// <summary>
        /// The scan service.
        /// </summary>
        private readonly IContactDetailsService contactDetailsService;

        /// <summary>
        /// The whats application SMS sender
        /// </summary>
        private readonly IWhatsAppSMSSender whatsAppSMSSender;
        private readonly IAdmissionService admissionsServices;

        private readonly ICallHistoryDataService callOutDataService;

        /// <inheritdoc />
        public AppointmentsController(
            IAppointmentService appointmentsServices,
            IWebNotificationService webNotificationService,
            IApplicationConfiguration applicationConfiguration, IPatientService patientServices,
            IAESHelper aesHelper,
            IAppointmentLogService appointmentLogServices,
            IMapper mapper,
            ISMSSender smsSender,
            IDoctorDeviceDetailsService doctorDeviceServices,
            IPatientDeviceDetailsService patientDeviceServices,
            IVideoCallHistoryService videoHistoryServices,
            IPushNotificationHelper pushNotificationHelper,
            IAccountSessionService accountSessionServices,
            IWebTelemedicineService webTelemedicineService,
            IHubContext<CommunicationHub> hubContext,
            IEmailSender emailSender,
            IPayUConfiguration payUConfiguration,
            ITimelineService timelineService,
            IAuditLogService auditLogServices, IDocumentHelper documentHelper,
            IProviderBankAccountService providerBankAccountServices, IURLShortnerHelper uRLShortnerHelper,
            IAmazonS3Configuration amazonS3Configuration,
            IPatientEncounterService patientEncounterService,
            IProviderService providerService,
            ISettingService settingService,
            ISalucroConfiguration salucroConfiguration,
            IAppointmentTransactionService appointmentTransactionService,
            IWalletService walletService,
            IPayUService payUService,
            ISalucroHelper salucroHelper,
            IPayUHelper payUHelper,
            IUnitOfWork unitOfWork,
            IPaymentInitiationLogService paymentInitiationLogService,
            IRunningEnvironment runningEnvironment,
            IFtpUploadHelper ftpUploadHelper,
            IPatientDocumentService patientDocumentServices,
            IPatientInsuranceService patientInsuranceServices,
            IPatientEmergencyService patientEmergencyServices,
            IScanLogService scanLogService,
            IWhatsAppSMSSender whatsAppSMSSender,
            IAdmissionService admissionsServices,
            IContactDetailsService contactDetailsService,
            ICallHistoryDataService callOutDataService)
        {
            this.appointmentsServices = appointmentsServices;
            this.webNotificationService = webNotificationService;
            this.applicationConfiguration = applicationConfiguration;
            this.patientServices = patientServices;
            this.aesHelper = aesHelper;
            this.appointmentLogServices = appointmentLogServices;
            this.mapper = mapper;
            this.smsSender = smsSender;
            this.doctorDeviceServices = doctorDeviceServices;
            this.patientDeviceServices = patientDeviceServices;
            this.videoHistoryServices = videoHistoryServices;
            this.pushNotificationHelper = pushNotificationHelper;
            this.accountSessionServices = accountSessionServices;
            this.webTelemedicineService = webTelemedicineService;
            this.hubContext = hubContext;
            this.emailSender = emailSender;
            this.payUConfiguration = payUConfiguration;
            this.timelineService = timelineService;
            this.auditLogServices = auditLogServices;
            this.documentHelper = documentHelper;
            this.providerBankAccountServices = providerBankAccountServices;
            this.uRLShortnerHelper = uRLShortnerHelper;
            this.amazonS3Configuration = amazonS3Configuration;
            this.patientEncounterService = patientEncounterService;
            this.providerService = providerService;
            this.settingService = settingService;
            this.salucroConfiguration = salucroConfiguration;
            this.appointmentTransactionService = appointmentTransactionService;
            this.walletService = walletService;
            this.payUService = payUService;
            this.salucroHelper = salucroHelper;
            this.payUHelper = payUHelper;
            this.unitOfWork = unitOfWork;
            this.paymentInitiationLogService = paymentInitiationLogService;
            this.runningEnvironment = runningEnvironment;
            this.ftpUploadHelper = ftpUploadHelper;
            this.patientDocumentServices = patientDocumentServices;
            this.patientInsuranceServices = patientInsuranceServices;
            this.patientEmergencyServices = patientEmergencyServices;
            this.scanLogService = scanLogService;
            this.contactDetailsService = contactDetailsService;
            this.callOutDataService = callOutDataService;
            appointmentHelper = AppointmentHelper.GetInstance(auditLogServices, appointmentsServices, settingService, pushNotificationHelper, smsSender, emailSender, accountSessionServices, whatsAppSMSSender, unitOfWork);
            this.whatsAppSMSSender = whatsAppSMSSender;
            this.admissionsServices = admissionsServices;

            this.client = client = new FirebaseClient(new FirebaseConfig
            {
                AuthSecret = this.applicationConfiguration.FirebaseAuthKey,
                BasePath = this.applicationConfiguration.FirebaseDatabase,
            });

        }


        [HttpPost]
        [Authorize]
        [Route("get-raw")]
        public async Task<ActionResult> GetRawAsync([FromBody] EncryptedIdRequest model)
        {
            var id = model.Id ?? 0;
            model = (EncryptedIdRequest)EmptyFilter.Handler(model);
            if (!string.IsNullOrEmpty(model.EncryptedId))
            {
                id = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedId));
            }
            var data = await this.appointmentsServices.GetRawAsync(id);
            //data.EncryptedProviderId = this.aesHelper.Encode(data.ProviderId.ToString());
            //data.EncryptedPatientId= this.aesHelper.Encode(data.PatientId.ToString());
            return this.Success(data);
        }




        [HttpPost]
        [Authorize]
        [Route("get-latest")]
        public async Task<ActionResult> GetLatestAsync([FromBody] EncryptedIdRequest model)
        {
            var id = model.Id ?? 0;
            var response = await this.appointmentsServices.GetLatestIdAsync(id);          
            return this.Success(new GenericResponse
            {
                Status = response > 0 ? GenericStatus.Success : GenericStatus.Info,
                Data = response

            });
        }


        [HttpPost]
        [Authorize]
        [Route("get-appointments-count")]
        public async Task<ActionResult> GetAppointmentsCountAsync([FromBody] EncryptedIdRequest model)
        {
            var id = model.Id ?? 0;         
            var todayAppointmentCount = await this.appointmentsServices.GetAppointmentCountForTodayAsync(id);
            return this.Success(new GenericResponse
            {
                Status = todayAppointmentCount > 0 ? GenericStatus.Success : GenericStatus.Info,
                Data = todayAppointmentCount

            });
        }

        /// <summary>
        /// The fetch appointments.
        /// </summary>
        /// <param name="model">
        /// The appointment filter model.
        /// </param>
        /// <returns>
        /// The list of appointments.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of appointments.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch")]
        [ProducesResponseType(typeof(List<AppointmentModel>), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchAsync([FromBody] AppointmentFilterModel model)
        {
            model = (AppointmentFilterModel)EmptyFilter.Handler(model);

            if (!string.IsNullOrEmpty(model.EncryptedPatientId))
            {
                model.PatientId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedPatientId));
            }

            if (!string.IsNullOrEmpty(model.EncryptedProviderId))
            {
                model.ProviderId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedProviderId));
            }

            var appointments = await this.appointmentsServices.FetchAsync(model);

            var appointmentModels = appointments.ToList();
            if (!string.IsNullOrEmpty(model.EncryptedPatientId) && appointmentModels.ToArray().Length == 0)
            {
                appointments = new List<AppointmentModel> { new AppointmentModel { PatientId = Convert.ToInt32(model.PatientId) } };
                return this.Success(appointments);
            }

            if (!string.IsNullOrEmpty(model.EncryptedProviderId) && appointmentModels.ToArray().Length == 0)
            {
                appointments = new List<AppointmentModel> { new AppointmentModel { ProviderId = Convert.ToInt32(model.ProviderId) } };
                return this.Success(appointments);
            }
            foreach (var item in appointmentModels)
            {
                var domain = await this.webTelemedicineService.GetActiveDomain(item.AppointmentNo);
                var roomName = item.AppointmentNo + "-" + item.PatientName?.Trim().Replace(' ', '-');
                item.RoomName = roomName;
                item.Domain = domain.Domain;

                if (model.ProviderId > 0)
                {
                    if (item.PatientCallStatus == 1)
                    {
                        item.CallStatusText = "No Answer";
                    }
                    else
                    {
                        if (item.CallStatus == 1)
                        {
                            item.CallStatusText = "Missed Call";
                        }
                        else
                        {
                            item.CallStatusText = item.VideoCallStatus == 2 ? "Call Complete" : item.VideoCallStatus == 1 ? string.Empty : "Call not started";
                        }
                    }
                }
                else
                {
                    if (item.CallStatus == 1)
                    {
                        item.CallStatusText = "Missed Call";
                    }
                    else
                    {
                        item.CallStatusText = item.VideoCallStatus == 2 ? "Call Complete" : item.VideoCallStatus == 1 ? string.Empty : "Call not started";
                    }
                }

                item.EncryptedAppointmentId = this.aesHelper.Encode(item.AppointmentId.ToString());
                item.EncryptedPatientId = this.aesHelper.Encode(item.PatientId.ToString());
                item.EncryptedProviderId = this.aesHelper.Encode(item.ProviderId.ToString());
                item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
            }

            return this.Success(appointments);
        }


        /// <summary>
        /// The fetch appointments.
        /// </summary>
        /// <param name="model">
        /// The appointment filter model.
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The list of appointments.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of appointments.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch-new")]
        [ProducesResponseType(typeof(List<AppointmentNewModel>), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchNewAsync([FromBody] AppointmentFilterModel model, [FromHeader] LocationHeader location)
        {
            model = (AppointmentFilterModel)EmptyFilter.Handler(model);

            if (!string.IsNullOrEmpty(model.EncryptedPatientId))
            {
                model.PatientId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedPatientId));
            }

            if (!string.IsNullOrEmpty(model.EncryptedProviderId))
            {
                model.ProviderId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedProviderId));
            }

            var appointments = await this.appointmentsServices.FetchNewAsync(model);

            var appointmentModels = appointments.ToList();
            if (!string.IsNullOrEmpty(model.EncryptedPatientId) && appointmentModels.ToArray().Length == 0)
            {
                appointments = new List<AppointmentNewModel> { new AppointmentNewModel { PatientId = Convert.ToInt32(model.PatientId) } };
                return this.Success(appointments);
            }

            if (!string.IsNullOrEmpty(model.EncryptedProviderId) && appointmentModels.ToArray().Length == 0)
            {
                appointments = new List<AppointmentNewModel> { new AppointmentNewModel { ProviderId = Convert.ToInt32(model.ProviderId) } };
                return this.Success(appointments);
            }

            var domain = await this.webTelemedicineService.GetActiveDomain(null);

            foreach (var item in appointmentModels)
            {
                var roomName = item.AppointmentNo + "-" + item.PatientName?.Trim().Replace(' ', '-').Replace("--", "-");
                item.RoomName = roomName;
                item.Domain = domain.Domain;


                var getPatientMedication = (await this.patientEncounterService.FetchPatientMedication(new Shared.UserModels.PatientMedication.PatientMedicationHeaderModel { AppointmentId = item.AppointmentId })).ToList();
                if (getPatientMedication.Count > 0)
                {
                    item.IsPrescription = true;
                }
                else
                {
                    item.IsPrescription = false;
                }


                if (item.CallType != null)
                {
                    item.CallTypeName = item.CallType == 1 ? "Video" : "Audio";
                }

                if (item.CallStatus != null)
                {
                    item.CallStatusName = item.CallStatus == 1 ? item.ReceiverCallStatus == 2 ? "Call Complete" : item.ReceiverCallStatus == 3 ? "Rejected Call" : "Missed Call" : item.CallStatus == 2 ? "Join" : item.CallStatus == 3 ? "Call Complete" : item.CallStatus == 4 ? "Cancelled" : string.Empty;
                }

                // SUPPORT CALL CONCEPT
                var prefix = "VS Support ";
                if (item.CallerRoleId == 5 || item.CallerRoleId == 2)
                {
                    if (item.CallStatus != null)
                    {
                        item.CallStatusName = item.CallStatus == 1 ? item.ReceiverCallStatus == 2 ? prefix + "Call Complete" : item.ReceiverCallStatus == 3 ? prefix + "Rejected Call" : prefix + "Missed Call" : item.CallStatus == 2 ? prefix + "Join" : item.CallStatus == 3 ? prefix + "Call Complete" : item.CallStatus == 4 ? prefix + "Cancelled" : string.Empty;
                    }
                }

                // New Implementation 13th May 2021
                if (item.InProgress == true)
                {
                    item.CallStatus = 2;
                    item.CallStatusName = "Join";
                }

                // SUPPORT CALL CONCEPT
                if (item.CallerRoleId == 5 || item.CallerRoleId == 2)
                {
                    if (item.InProgress == true)
                    {
                        item.CallStatus = 2;
                        item.CallStatusName = prefix + "Join";
                    }
                }

                // This case happen when Doctor or Nurse call to Doctor or nurse with no patient in the call and call has been ended
                if (item.InProgress == false && item.CallStatus == 2)
                {
                    item.CallStatus = 1;
                    // SUPPORT CALL CONCEPT
                    if (item.CallerRoleId == 5 || item.CallerRoleId == 2)
                    {
                        item.CallStatusName = prefix + "Missed Call";
                    }
                    else
                    {
                        item.CallStatusName = "Missed Call";
                    }
                }

                item.EncryptedAppointmentId = this.aesHelper.Encode(item.AppointmentId.ToString());
                item.EncryptedPatientId = this.aesHelper.Encode(item.PatientId.ToString());
                item.EncryptedProviderId = this.aesHelper.Encode(item.ProviderId.ToString());

                item.PreviousAppointmentTimeString = item.FollowUpForAppointmentId != null ? Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add((TimeSpan)item.AppointmentPreviousTime).ToString("hh:mm tt") : null;
                item.PreviousAdmissionDischargeTimeString = item.FollowUpForAdmissionId != null ? Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add((TimeSpan)item.AdmissionDischargeTime).ToString("hh:mm tt") : null;

                item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
            }

            return this.Success(appointments);
        }

        /// <summary>
        /// The fetch all async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("fetch-all")]
        [ProducesResponseType(typeof(List<AppointmentModel>), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchAllAsync([FromBody] AppointmentFilterModel model, [FromHeader] LocationHeader header)
        {
            var appointments = new List<AppointmentModel>();
            model = (AppointmentFilterModel)EmptyFilter.Handler(model); //
            model.LocationId = !string.IsNullOrEmpty(header.LocationId) ? int.Parse(header.LocationId) : (int?)null;
            if (!string.IsNullOrEmpty(model.EncryptedPatientId))
            {
                model.PatientId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedPatientId));
            }
            if (!string.IsNullOrEmpty(model.EncryptedProviderId))
            {
                model.ProviderId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedProviderId));
            }
            appointments = (List<AppointmentModel>)await this.appointmentsServices.FetchAllAsync(model);
            var appointmentModels = appointments.ToList();
            if (!string.IsNullOrEmpty(model.EncryptedPatientId) && appointmentModels.ToArray().Length == 0)
            {
                appointments = new List<AppointmentModel> { new AppointmentModel { PatientId = Convert.ToInt32(model.PatientId) } };
                return this.Success(appointments);
            }
            if (!string.IsNullOrEmpty(model.EncryptedProviderId) && appointmentModels.ToArray().Length == 0)
            {
                appointments = new List<AppointmentModel> { new AppointmentModel { ProviderId = Convert.ToInt32(model.ProviderId) } };
                return this.Success(appointments);
            }
            var domain = await this.webTelemedicineService.GetActiveDomain(null);
            foreach (var item in appointmentModels)
            {
                var roomName = item.AppointmentNo + "-" + item.PatientName?.Trim().Replace(' ', '-').Replace("--", "-");
                item.RoomName = roomName;
                item.Domain = domain.Domain;


                var getPatientMedication = (await this.patientEncounterService.FetchPatientMedication(new Shared.UserModels.PatientMedication.PatientMedicationHeaderModel { AppointmentId = item.AppointmentId })).ToList();
                if (getPatientMedication.Count > 0)
                {
                    item.IsPrescription = true;
                }
                else
                {
                    item.IsPrescription = false;
                }


                if (item.CallType != null)
                {
                    item.CallTypeName = item.CallType == 1 ? "Video" : "Audio";
                }

                if (item.CallStatus != null)
                {
                    item.CallStatusName = item.CallStatus == 1 ? item.ReceiverCallStatus == 2 ? "Call Complete" : item.ReceiverCallStatus == 3 ? "Rejected Call" : "Missed Call" : item.CallStatus == 2 ? "Join" : item.CallStatus == 3 ? "Call Complete" : item.CallStatus == 4 ? "Cancelled" : string.Empty;
                }

                // SUPPORT CALL CONCEPT
                var prefix = "VS Support ";
                if (item.CallerRoleId == 5 || item.CallerRoleId == 2)
                {
                    if (item.CallStatus != null)
                    {
                        item.CallStatusName = item.CallStatus == 1 ? item.ReceiverCallStatus == 2 ? prefix + "Call Complete" : item.ReceiverCallStatus == 3 ? prefix + "Rejected Call" : prefix + "Missed Call" : item.CallStatus == 2 ? prefix + "Join" : item.CallStatus == 3 ? prefix + "Call Complete" : item.CallStatus == 4 ? prefix + "Cancelled" : string.Empty;
                    }
                }

                // New Implementation 13th May 2021
                if (item.InProgress == true)
                {
                    item.CallStatus = 2;
                    item.CallStatusName = "Join";
                }

                // SUPPORT CALL CONCEPT
                if (item.CallerRoleId == 5 || item.CallerRoleId == 2)
                {
                    if (item.InProgress == true)
                    {
                        item.CallStatus = 2;
                        item.CallStatusName = prefix + "Join";
                    }
                }

                // This case happen when Doctor or Nurse call to Doctor or nurse with no patient in the call and call has been ended
                if (item.InProgress == false && item.CallStatus == 2)
                {
                    item.CallStatus = 1;
                    // SUPPORT CALL CONCEPT
                    if (item.CallerRoleId == 5 || item.CallerRoleId == 2)
                    {
                        item.CallStatusName = prefix + "Missed Call";
                    }
                    else
                    {
                        item.CallStatusName = "Missed Call";
                    }
                }

                item.EncryptedProviderId = this.aesHelper.Encode(item.ProviderId.ToString());
                item.EncryptedAppointmentId = this.aesHelper.Encode(item.AppointmentId.ToString());
                item.EncryptedPatientId = this.aesHelper.Encode(item.PatientId.ToString());
                item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
                item.PreviousAppointmentTimeString = item.FollowUpForAppointmentId != null ? Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add((TimeSpan)item.AppointmentPreviousTime).ToString("hh:mm tt") : null;
                item.PreviousAdmissionDischargeTimeString = item.FollowUpForAdmissionId != null ? Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add((TimeSpan)item.AdmissionDischargeTime).ToString("hh:mm tt") : null;

            }


            return this.Success(appointments);

        }

        /// <summary>
        /// The quick schedule, add patient and book appointment.
        /// </summary>
        /// <param name="request">
        /// The add request model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Patient Added and booked appointment successfully.
        /// - 409 - Appointment has already exist with us.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("quick-schedule")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(typeof(string), 409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> QuickScheduleAsync([FromForm] QuickScheduleRequest request, [FromHeader] LocationHeader header)
        {
            request.LoginLocationId = int.Parse(header.LocationId);
            var files = this.Request.Form.Files;
            request.Files = files;
            var checkSameDateAptWithSameDoc = await this.CheckSameDateAppointmentWithSameDoctorAsync(request);
            if (checkSameDateAptWithSameDoc.Status == GenericStatus.Warning)
            {
                return this.Success(checkSameDateAptWithSameDoc);
            }
            var subResponse = await this.AddAppointmentAsync(request);
            if (subResponse.Status == GenericStatus.Error)
            {
                return this.Success(subResponse);
            }

            if (subResponse.Status == GenericStatus.Success && request.PaymentStatus == false)
            {
                try
                {
                    var appointment = await this.appointmentsServices.FindAppointmentAsync(Convert.ToInt32(subResponse.Data), false);
                    if (appointment == null)
                    {
                        return this.Success(new GenericResponse
                        {
                            Status = GenericStatus.Success,
                            Data = subResponse.Data
                        });
                    }

                    var findvisitType = await this.unitOfWork.Visitors.FindAsync(m => m.VisitTypeId == request.VisitTypeId);

                    if (findvisitType == null)
                    {
                        return this.Success(new GenericResponse
                        {
                            Status = GenericStatus.Success,
                            Data = subResponse.Data
                        });
                    }

                    var url = "app/appointment-schedule";
                    var roles = (await this.webNotificationService.GetAllRoles()).ToList();
                    var getRolesToNotify = roles.Where(r => r.RoleName.ToLower().Contains("front"));
                    var getAdmins = roles.Where(r => r.RoleName.ToLower().Contains("admin"));
                    var finalRoleModel = new List<RoleModel>();
                    finalRoleModel.AddRange(getRolesToNotify.ToList());
                    finalRoleModel.AddRange(getAdmins.ToList());
                    var notification = new WebNotificationModel
                    {
                        AllowedAccounts = string.Empty,
                        AllowedRoles = string.Join(",", finalRoleModel.Select(r => r.RoleId)),
                        CreatedDate = appointment.AppointmentDate,
                        IsRead = false,
                        Message = $@"{appointment.ProviderName} Booked an Appointment",
                        RedirectionLink = url,
                        WebNotificationLogTypeId = (int)WebNotificationLogType.View,
                        WebNotificationPriorityId = (int)WebNotificationPriority.High,
                        PatientId = appointment.PatientId,
                        ReferenceId = Convert.ToInt32(subResponse.Data),
                        //ModulesMasterId = request.PatientId > 0 ? (int)ModulesMasterType.ReviewPatients : (int)ModulesMasterType.NewPatients
                        ModulesMasterId = findvisitType.VisitorName.ToLower().Trim() == "New Patient".ToLower().Trim() ? (int)ModulesMasterType.NewPatients
                                            : findvisitType.VisitorName.ToLower().Trim() == "Emergency".ToLower().Trim() ? (int)ModulesMasterType.Emergency
                                            : findvisitType.VisitorName.ToLower().Trim() == "WALK IN".ToLower().Trim() ? (int)ModulesMasterType.WalkIn
                                            : (int)ModulesMasterType.ReviewPatients
                    };
                    await this.webNotificationService.InsertAsync(notification);
                }
                catch (Exception e)
                {
                    // ignore
                }

            }

            return this.Success(new GenericResponse
            {
                Status = GenericStatus.Success,
                Data = subResponse.Data
            });
        }

        /// <summary>
        /// Adds the asynchronous helper.
        /// </summary>
        /// <param name="request">The model.</param>
        /// <returns></returns>
        public async Task<GenericResponse> CheckSameDateAppointmentWithSameDoctorAsync(QuickScheduleRequest request)
        {
            request = (QuickScheduleRequest)EmptyFilter.Handler(request);

            if (request.AppointmentId == 0)
            {
                var findCheckAptWithSameDoc = await this.unitOfWork.Appointments.FindAsync(m => m.ProviderId == request.ProviderId && m.AppointmentDate == request.AppointmentDate && m.PatientId == request.PatientId && m.Active == true && m.Status != "C");

                if (findCheckAptWithSameDoc != null)
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Warning,
                        Message = $@"This Appointment has already been exists with us today at {findCheckAptWithSameDoc?.AppointmentDate.Add(findCheckAptWithSameDoc.AppointmentTime).ToString("hh:mm tt")} ."
                    };
                }
                else
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Success
                    };
                }
            }
            else
            {
                return new GenericResponse
                {
                    Status = GenericStatus.Success
                };
            }
        }

        /// <summary>
        /// Adds the asynchronous helper.
        /// </summary>
        /// <param name="request">The model.</param>
        /// <returns></returns>
        public async Task<GenericResponse> AddAppointmentAsync(QuickScheduleRequest request)
        {
            request = (QuickScheduleRequest)EmptyFilter.Handler(request);
            request.RelativeDetails = request.RelativeDetails != null && request.RelativeDetails.Count > 0 ? request.RelativeDetails : request.Relative != null ? JsonConvert.DeserializeObject<List<PatientFamilyModel>>(request.Relative) : request.RelativeDetails;
            var patientId = request.PatientId;
            if (request.PatientId == 0)
            {
                var patientModel = new PatientModel
                {
                    FirstName = request.FirstName,
                    LastName = request.LastName,
                    FatherOrHusband = request.FatherOrHusband,
                    Mobile = request.Mobile,
                    Age = request.Age,
                    CountryId = request.CountryId,
                    Email = request.Email,
                    CreatedBy = request.CreatedBy,
                    Gender = request.Gender,
                    AadharNo = request.AadharNo,
                    DateOfBirth = request.DateOfBirth,
                    AddressLine2 = request.AddressLine2,
                    Base64ProfileImage = request.Base64ProfileImage,
                    City = request.City,
                    ProfileImageUrl = request.ProfileImageUrl,
                    Salutation = request.Salutation,
                    State = request.State,
                    StreetAddress = request.StreetAddress,
                    ThumbnailUrl = request.ThumbnailUrl,
                    Zipcode = request.Zipcode,
                    //ReferredBy = request.ReferredBy,
                    PatientReferredById = request.PatientReferredById,
                    ReferredByName = request.ReferredByName,
                    RoleId = request.LogFrom,
                    CreatedByName = request.CreatedByName,
                    HWCPatientId = request.HWCPatientId,
                    //  PayType = request.PaymentType,
                    LocationId = request.LocationId,
                    Education = request.Education,
                    Occupation = request.Occupation,
                    MaritalStatus = request.MaritalStatus,
                    Religion = request.Religion,
                    Nationality = request.Nationality,
                    IdProofId = request.IdProofId,
                    IdProofValue = request.IdProofValue,
                    PayTypeId = request.PaymentStatus == true ? request.PayTypeId : null,
                    BloodGroup = request.BloodGroup,
                    PaymentStatus = request.PaymentStatus,//we have to add in patient table  for both type of patient (unidentify/identify)
                                                          //Amount=request.Amount,// registration fee  // is this amt req+app ? no --->app so commented----
                                                          //
                                                          //Amount = (decimal)request.Charges, // reg amt to insert in patient table 
                    PaymentNumber = request.PaymentNumber,
                    UMRNo = request.PaymentStatus == false ? request.Mobile : await this.patientServices.GetLatestUMRNo(),
                    TempPatient = request.PaymentStatus != true ? true : false,
                    HowDidYouKnowId = request.HowDidYouKnowId,
                    EducationId = request.EducationId,
                    OccupationId = request.OccupationId,
                    BirthMark1 = request.BirthMark1,
                    BirthMark2 = request.BirthMark2,
                    Transaction = request.Transaction,
                    TransactionId = request.TransactionId,
                    SalucroStatusCode = request.SalucroStatusCode,
                    SalucroTransactionId = request.SalucroTransactionId,
                    RelationType = request.RelationType,
                    OccupationDetail = request.OccupationDetail,
                    //IsNewPatient=request.IsNewPatient
                    SaveRelativeAsPatient = request.SaveRelativeAsPatient,
                    InsuranceId = request.InsuranceId,
                    ReferredByNameId = request.ReferredByNameId,
                    Amount = request.Charges,
                    Total = (double)request.PatientTotal,
                    DiscountInPercentage = request.PatientDiscountInPercentage,
                    DiscountInRupees = request.PatientDiscountInRupees
                };
                if (!request.IsUnidentified)
                {

                    patientModel.Email = string.IsNullOrEmpty(patientModel.Email) ? null : patientModel.Email;
                    patientModel.FullName = CoreFilter.FullName(patientModel.FirstName, patientModel.MiddleName, patientModel.LastName);
                    PatientFamilyModel pfModel = new PatientFamilyModel();
                    pfModel.FullName = request.RelationName;
                    pfModel.Education = request.RealtiveEducation;
                    // pfModel.DOB = Convert.ToDateTime(request.RelativeDateOfBirth);
                    pfModel.ContactNo = request.RelativeMobile;
                    pfModel.RelativeGender = request.RelativeGender;
                    pfModel.Relation = request.Relation;
                    pfModel.CreatedBy = request.CreatedBy;
                    pfModel.CreatedDate = DateTime.UtcNow.AddMinutes(330);
                    pfModel.Occupation = request.RelativeOccupation;

                    var (accountId, newPatientId, guid) = await this.patientServices.AddAsync(patientModel, request.EmergencyContacts ?? new List<PatientEmergencyModel>(), request.Insurances ?? new List<PatientInsuranceModel>(), pfModel, request.RelativeDetails ?? new List<PatientFamilyModel>());

                    //var (newPatientId, guid) = await this.patientServices.AddPatientAsync(patientModel, pfModel);
                    patientId = newPatientId;

                    //string inputData = request.Details;
                    //if (!string.IsNullOrEmpty(inputData))
                    //{
                    //    var contactdetails = new ContactDetails
                    //    {
                    //        Details = request.Details,
                    //        CreatedBy = request.CreatedBy,
                    //        CreatedDate = DateTime.UtcNow,
                    //        PatientId = patientId,
                    //        IsActive = true
                    //    };

                    //    var contactDetails = await this.contactDetailsService.AddAsync(contactdetails);
                    //}
                    //if (patientId != 0)
                    //{
                    //    DateTime utcNow = DateTime.UtcNow.AddMinutes(330);
                    //    var callhistory = new CallHistory
                    //    {
                    //        CallEnd = utcNow.ToString("hh:mm tt"),
                    //        ModifiedBy = request.CreatedBy,
                    //    };

                    //    var contactDetails = await this.callOutDataService.UpdateAsync(callhistory);
                    //}
                    if (accountId == 0 && newPatientId != 0)
                    {
                        return new GenericResponse
                        {
                            Data = newPatientId,
                            Status = GenericStatus.Success,
                            Message = "Potential Lead Added Succesfully."
                        };
                    }
                    switch (patientId)
                    {
                        case -2:
                            //return this.Conflict("Given email address has already been exists with us.");
                            return new GenericResponse
                            {
                                Status = GenericStatus.Warning,
                                Message = "Given email address has already been exists with us."
                            };
                        case -1:
                            //return this.Conflict("Given mobile number has already been exists with us.");
                            return new GenericResponse
                            {
                                Status = GenericStatus.Warning,
                                Message = "Given mobile number has already been exists with us."
                            };
                        case 0:
                            //return this.ServerError();
                            return new GenericResponse
                            {
                                Status = GenericStatus.Error,
                                Message = "Internal Server Error."
                            };
                    }

                    //(patientModel.ProfileImageUrl, patientModel.ThumbnailUrl) = await this.documentHelper.UploadAsync(patientModel.Base64ProfileImage, (Guid)guid, "Profile", "profile_" + DateTime.UtcNow.Ticks);
                    //if (!string.IsNullOrEmpty(patientModel.ProfileImageUrl))
                    //{
                    //    await this.patientServices.UpdateImageUrlsAsync(patientModel, (Guid)guid);
                    //}

                    if (!string.IsNullOrEmpty(patientModel.Base64ProfileImage))
                    {
                        var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/{guid}/ProfileImage";

                        try
                        {
                            await this.ftpUploadHelper.CreateDirectory(filePath);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                        var dbPath = $@"{patientModel.FullName}_{DateTime.UtcNow.Ticks}.jpg";
                        filePath += $@"/{dbPath}";

                        try
                        {
                            var uploadResponse = await this.ftpUploadHelper.UploadProfileImageAsync(patientModel.Base64ProfileImage, filePath);
                            if (uploadResponse > 0)
                            {
                                patientModel.ProfileImageUrl = $@"ProfileImage/{dbPath}";
                                patientModel.ThumbnailUrl = $@"ProfileImage/{dbPath}";
                                await this.patientServices.UpdateImageUrlsAsync(patientModel, (Guid)guid);
                            }
                        }
                        catch (Exception e)
                        {
                            patientModel.ProfileImageUrl = null;
                            patientModel.ThumbnailUrl = null;
                        }
                    }
                    if (request.FilePaths != null && request.FilePaths.Count > 0)
                    {
                        var patientDocuments = new List<PatientDocumentModel>();
                        var index = 0;
                        foreach (var path in request.FilePaths)
                        {
                            var tokens = path.Split("/");
                            var fileName = tokens[tokens.Length - 1];
                            var type = fileName.Split("_")[fileName.Split("_").Length - 2];
                            var contentType = "";
                            switch (type)
                            {
                                case "imeg":
                                    contentType = "image/jpeg";
                                    break;
                                case "impeg":
                                    contentType = "image/pjpeg";
                                    break;
                                case "imng":
                                    contentType = "image/png";
                                    break;
                                case "imif":
                                    contentType = "image/gif";
                                    break;
                                case "apdf":
                                    contentType = "application/pdf";
                                    break;
                                default:
                                    contentType = type;
                                    break;
                            }
                            var size = fileName.Split("_")[fileName.Split("_").Length - 3];
                            var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/{guid}/{request.DocumentType}";
                            await this.ftpUploadHelper.CreateDirectory(filePath);
                            request.DocumentName = index == 0 ? request.DocumentName : $"{request.DocumentName}_{index}";
                            var dbPath = $@"{request.DocumentName}_{DateTime.UtcNow.Ticks}{Path.GetExtension(fileName)}";
                            filePath += $@"/{dbPath}";

                            try
                            {
                                var response = await this.ftpUploadHelper.Rename(path, filePath);
                                if (response)
                                {
                                    var model = new PatientDocumentModel
                                    {
                                        DocumentType = request.DocumentType,
                                        Description = request.Description,
                                        DocumentName = index == 0 ? request.DocumentName : $"{request.DocumentName}_{index}",
                                        UploadedBy = request.CreatedBy,
                                        PatientId = (int)patientId,
                                        ContentType = contentType,
                                        Size = float.Parse(size)
                                    };
                                    model.ThumbnailUrl = this.documentHelper.GetThumbnail(contentType);
                                    model.DocumentUrl = dbPath;
                                    patientDocuments.Add(model);
                                }
                            }
                            catch (Exception ex)
                            {
                                throw;
                            }
                            index++;
                        }
                        await this.patientDocumentServices.AddAsync(patientDocuments);

                        //delete temp folder 
                        //var fileTokens = new ArrayList(request.FilePaths[0].Split("/"));

                        //fileTokens.RemoveAt(fileTokens.Count - 1);
                        //fileTokens.RemoveAt(fileTokens.Count - 1);

                        //var fileJoinedStringResult = string.Join("/", fileTokens.ToArray());

                        //await this.ftpUploadHelper.DeleteDirectory(fileJoinedStringResult);
                    }
                    if (request.Files != null && request.Files.Count > 0)
                    {
                        var patientDocuments = new List<PatientDocumentModel>();
                        var index = 0;
                        foreach (var file in request.Files)
                        {
                            var model = new PatientDocumentModel
                            {
                                DocumentType = request.DocumentType,
                                Description = request.Description,
                                DocumentName = index == 0 ? request.DocumentName : $"{request.DocumentName}_{index}",
                                UploadedBy = request.CreatedBy,
                                PatientId = (int)patientId,
                                ContentType = file.ContentType,
                                Size = file.Length
                            };

                            var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/{guid}/{request.DocumentType}";

                            try
                            {
                                await this.ftpUploadHelper.CreateDirectory(filePath);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                            }
                            request.DocumentName = index == 0 ? request.DocumentName : $"{request.DocumentName}_{index}";
                            var dbPath = $@"{request.DocumentName}_{DateTime.UtcNow.Ticks}{Path.GetExtension(file.FileName)}";
                            filePath += $@"/{dbPath}";

                            var uploadResponse = await this.ftpUploadHelper.UploadFromFileAsync(filePath, file);
                            if (uploadResponse <= 0)
                            {
                                return new GenericResponse
                                {
                                    Status = GenericStatus.Error,
                                    Message = "Unable to upload the document"
                                };
                            }
                            model.ThumbnailUrl = this.documentHelper.GetThumbnail(file.ContentType);
                            model.DocumentUrl = dbPath;
                            patientDocuments.Add(model);
                            index++;
                        }
                        await this.patientDocumentServices.AddAsync(patientDocuments);
                    }

                    var encryptedAccountId = this.aesHelper.Encode(accountId.ToString());
                    var createPasswordLink = this.applicationConfiguration.CreatePasswordLink + encryptedAccountId;
                    //var shortnerUrl = await this.uRLShortnerHelper.MakeShorterUrl(createPasswordLink);
                    var shortnerUrl = createPasswordLink; // for performance

                    if (!string.IsNullOrEmpty(patientModel.Email))
                    {
                        var response = await this.emailSender.SendWelcomeMailAsync(patientModel.Email, patientModel.FullName, null, createPasswordLink);
                        //return response ? this.Success(patientId) : this.Success(this.MailServerError());

                        //return response ? this.Success("User details has been added successfully.") : this.Success(this.MailServerError());
                    }
                    else if (!string.IsNullOrEmpty(patientModel.Mobile))
                    {
                        var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                        var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                        if ((bool)WhatsAppMessage[0].Active)
                        {
                            bool ret = await this.whatsAppSMSSender.SendRegisteredMessage(patientModel.Mobile, patientModel.FullName);
                        }
                        var smsSent = await this.smsSender.SendWelcomeMessageAsync(patientModel.Mobile, patientModel.FullName, null, shortnerUrl, Convert.ToInt32(patientModel.CountryId));
                        //return smsSent ? this.Success("Patient has been added successfully.") : this.Success(this.SMSServerError());
                    }
                }

                else if (request.IsUnidentified)
                {
                    var (newPatientId, guid) = await this.patientServices.AddUnidentifiedPatientAsync(patientModel);
                    patientId = newPatientId;
                }
                var auditLogModel = new AuditLogModel
                {
                    AccountId = patientModel.CreatedBy,
                    LogTypeId = (int)LogTypes.Patient,
                    LogFrom = (short)patientModel.RoleId,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription = $@"{patientModel.CreatedByName} <b>Added</b> Patient:<b> {(request.IsUnidentified ? "unidentified" : patientModel.FullName)}</b> <br> Successfully on {DateTime.UtcNow.AddMinutes(330).ToString("MM/dd/yyyy, hh:mm tt")} ",
                    LocationId = Convert.ToInt32(request.LocationId)
                };
                await this.auditLogServices.LogAsync(auditLogModel);
            }

            else if (request.UpdatePatient != false && request.PatientId > 0)
            {
                var patientModel = new PatientModel
                {
                    PatientId = request.PatientId,
                    FirstName = request.FirstName,
                    LastName = request.LastName,
                    FatherOrHusband = request.FatherOrHusband,
                    Mobile = request.Mobile,
                    Age = request.Age,
                    CountryId = request.CountryId,
                    Email = request.Email,
                    CreatedBy = request.CreatedBy,
                    Gender = request.Gender,
                    AadharNo = request.AadharNo,
                    DateOfBirth = request.DateOfBirth,
                    AddressLine2 = request.AddressLine2,
                    Base64ProfileImage = request.Base64ProfileImage,
                    City = request.City,
                    ProfileImageUrl = request.ProfileImageUrl,
                    Salutation = request.Salutation,
                    State = request.State,
                    StreetAddress = request.StreetAddress,
                    ThumbnailUrl = request.ThumbnailUrl,
                    Zipcode = request.Zipcode,
                    //ReferredBy = request.ReferredBy,
                    PatientReferredById = request.PatientReferredById,
                    ReferredByName = request.ReferredByName,
                    RoleId = request.LogFrom,
                    CreatedByName = request.CreatedByName,
                    HWCPatientId = request.HWCPatientId,
                    //  PayType = request.PaymentType,
                    LocationId = request.LocationId,
                    Education = request.Education,
                    Occupation = request.Occupation,
                    MaritalStatus = request.MaritalStatus,
                    Religion = request.Religion,
                    Nationality = request.Nationality,
                    IdProofId = request.IdProofId,
                    IdProofValue = request.IdProofValue,
                    PayTypeId = request.PaymentStatus == true ? request.PayTypeId : null,
                    BloodGroup = request.BloodGroup,
                    //PaymentStatus = request.PaymentStatus,//we have to add in patient table  for both type of patient (unidentify/identify)
                    //Amount=request.Amount,// registration fee  // is this amt req+app ? no --->app so commented----
                    //
                    //Amount = (decimal)request.Charges, // reg amt to insert in patient table 
                    PaymentNumber = request.PaymentNumber,
                    UMRNo = request.PaymentStatus == false ? request.Mobile : await this.patientServices.GetLatestUMRNo(),
                    TempPatient = request.PaymentStatus != true ? true : false,
                    HowDidYouKnowId = request.HowDidYouKnowId,
                    EducationId = request.EducationId,
                    OccupationId = request.OccupationId,
                    BirthMark1 = request.BirthMark1,
                    BirthMark2 = request.BirthMark2,
                    Transaction = request.Transaction,
                    TransactionId = request.TransactionId,
                    SalucroStatusCode = request.SalucroStatusCode,
                    SalucroTransactionId = request.SalucroTransactionId,
                    RelationType = request.RelationType,
                    OccupationDetail = request.OccupationDetail,
                    //IsNewPatient=request.IsNewPatient
                    SaveRelativeAsPatient = request.SaveRelativeAsPatient,
                    InsuranceId = request.InsuranceId,
                    ReferredByNameId = request.ReferredByNameId,
                    LoginLocationId = request.LoginLocationId,

                };

                if (!request.IsUnidentified)
                {

                    patientModel.Email = string.IsNullOrEmpty(patientModel.Email) ? null : patientModel.Email;
                    patientModel.FullName = CoreFilter.FullName(patientModel.FirstName, patientModel.MiddleName, patientModel.LastName);
                    //patientModel.Amount = request.Charges;
                    patientModel.PatientTotal = request.PatientTotal;
                    patientModel.Total = (double)request.PatientTotal;
                    patientModel.DiscountInRupees = request.PatientDiscountInRupees;
                    patientModel.DiscountInPercentage = request.PatientDiscountInPercentage;
                    patientModel.Amount = request.Charges;
                    PatientFamilyModel pfModel = new PatientFamilyModel();
                    pfModel.FullName = request.RelationName;
                    pfModel.Education = request.RealtiveEducation;
                    // pfModel.DOB = Convert.ToDateTime(request.RelativeDateOfBirth);
                    pfModel.ContactNo = request.RelativeMobile;
                    pfModel.RelativeGender = request.RelativeGender;
                    pfModel.Relation = request.Relation;
                    pfModel.CreatedBy = request.CreatedBy;
                    pfModel.CreatedDate = DateTime.UtcNow.AddMinutes(330);
                    pfModel.Occupation = request.RelativeOccupation;

                    patientId = await this.patientServices.UpdateAsync(patientModel, request.EmergencyContacts ?? new List<PatientEmergencyModel>(), request.Insurances ?? new List<PatientInsuranceModel>(), pfModel, request.RelativeDetails ?? new List<PatientFamilyModel>());

                    //var (newPatientId, guid) = await this.patientServices.AddPatientAsync(patientModel, pfModel);
                    if (patientId > 0)
                    {
                        patientId = request.PatientId;
                    }

                    switch (patientId)
                    {
                        case -2:
                            //return this.Conflict("Given email address has already been exists with us.");
                            return new GenericResponse
                            {
                                Status = GenericStatus.Warning,
                                Message = "Given email address has already been exists with us."
                            };
                        case -1:
                            //return this.Conflict("Given mobile number has already been exists with us.");
                            return new GenericResponse
                            {
                                Status = GenericStatus.Warning,
                                Message = "Given mobile number has already been exists with us."
                            };
                        case 0:
                            //return this.ServerError();
                            return new GenericResponse
                            {
                                Status = GenericStatus.Error,
                                Message = "Internal Server Error."
                            };
                    }

                }

            }

            var bookAppointmentModel = new BookAppointmentRequest
            {
                AppointmentId = request.AppointmentId,
                AppointmentDate = request.AppointmentDate,
                AppointmentTime = request.AppointmentTime,
                Amount = request.Amount, // is this amt only for appointment -- yes
                DepartmentId = request.DepartmentId,
                CouponId = request.CouponId,
                CreatedBy = request.CreatedBy,
                Discount = request.AppointmentDiscountInRupees,
                LogFrom = request.LogFrom,
                PatientFamilyId = request.PatientFamilyId,
                PatientId = (int)patientId,
                PatientType = request.PatientType,
                PaymentNumber = request.PaymentNumber,
                //  PaymentType = request.PaymentType,
                ProviderId = request.ProviderId,
                //ProviderLocationId = request.ProviderLocationId,
                VisitType = request.VisitType,
                ChargeType = request.ChargeType,
                TotalAmount = request.TotalAmount,
                WalletAmount = request.WalletAmount,
                FollowUpForAppointmentId = request.FollowUpForAppointmentId,
                FollowUpForAdmissionId = request.FollowUpForAdmissionId,
                CreatedByName = request.CreatedByName,
                PaymentStatus = request.PaymentStatus,
                VisitTypeId = request.VisitTypeId,
                ChargeTypesId = request.ChargeTypesId,
                LocationId = request.LocationId,
                AppointmentTypeId = request.AppointmentTypeId,
                PayTypeId = request.PayTypeId,
                TokenNumber = request.TokenNumber,
                SpecializationId = request.SpecializationId,
                AppointmentEndTime = request.AppointmentEndTime,
                ProviderAvailabilityId = request.ProviderAvailabilityId,
                ConsultationTypeId = request.ConsultationTypeId,
                PatientRegistrationAmount = request.Charges,
                SalucroStatusCode = request.SalucroStatusCode,
                SalucroTransactionId = request.SalucroTransactionId,
                Transaction = request.Transaction,
                TransactionId = request.TransactionId,
                IsSalucroAppointment = request.IsSalucroAppointment,
                DoctorSpecializationChargeModuleDetailsId = request.DoctorSpecializationChargeModuleDetailsId,
                OtherRemarks = request.OtherRemarks,
                AuthorityId = request.AuthorityId,
                ReasonId = request.ReasonId,
                Remarks = request.Remarks,
                Active = true,
                Total = request.AppointmentTotal,
                TypeOfPayment = request.TypeOfPayment,
                DiscountInPercentage = request.AppointmentDiscountInPercentage,
                AfterDiscount = request.AfterDiscount,
                PatientDiscountInPercentage = request.PatientDiscountInPercentage,
                PatientDiscountInRupees = request.PatientDiscountInRupees,
                PatientTotal = request.PatientTotal,
                IsHealthCard = request.IsHealthCard,
                SessionId = request.SessionId
            };

            var result = await this.AddAsyncHelper(bookAppointmentModel);
            var patientData = await this.unitOfWork.Patients.FindAsync(x => x.PatientId == bookAppointmentModel.PatientId);
            if (request.Charges != null && request.Charges != 0)
            {
                var patientUpdateQuery = $@" UPDATE ""Patient"" SET  ""AppointmentId""={result.Data} WHERE ""PatientId""= {patientId}";
                await this.unitOfWork.Current.ExecuteAsync(patientUpdateQuery);

            }

            return result;
        }

        //private async Task<string> GetLatestUMRNo()
        //{
        //    // Ex: UMR20010005
        //    var umrNo = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<string>($@"SELECT ""UMRNo"" FROM ""Patient"" where ""UMRNo"" LIKE 'UMR%' ORDER BY ""UMRNo"" DESC");
        //    return CoreFilter.GetTransactionId(umrNo, "UMR");
        //}

        /// <summary>
        /// The book appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("pay-add-appointment")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> BookAsync([FromBody] BookAppointmentRequest model)
        {
            model = (BookAppointmentRequest)EmptyFilter.Handler(model);

            var appointmentLogModel = this.mapper.Map<AppointmentLogModel>(model);
            appointmentLogModel.AppointmentTime = TimeSpan.Parse(model.AppointmentTime);
            appointmentLogModel.PatientRegistrationCharges = model.Charges;
            var appointmentLogId = await this.appointmentLogServices.AddAsync(appointmentLogModel);
            switch (appointmentLogId)
            {
                case -1:
                    return this.Conflict("Given appointment has already been exists with us.");
                case 0:
                    return this.ServerError();
                default:

                    var appointmentLog = await this.appointmentLogServices.FindAsync(appointmentLogId);
                    if (appointmentLog != null)
                    {
                        var auditLogModel = new AuditLogModel
                        {
                            AccountId = model.CreatedBy,
                            LogTypeId = (int)LogTypes.AppointmentLogs,
                            LogFrom = model.LogFrom,
                            LogDate = DateTime.UtcNow.AddMinutes(330),
                            LogDescription = $@"For Patient: <b>{appointmentLog?.PatientFirstName}</b>, the <b>{(appointmentLog.FollowUpForAppointmentId != null ? "Follow Up" : "New")}</b> Appointment has been booked<br>
                            with Doctor: <b>Dr.{appointmentLog?.ProviderName}</b> on <b>{appointmentLog?.AppointmentDate.ToString("MM/dd/yyyy")} {appointmentLog?.AppointmentDate.Add(appointmentLog.AppointmentTime).ToString("hh:mm tt")}</b>",
                            LocationId = model.LocationId

                        };
                        await this.auditLogServices.LogAsync(auditLogModel);
                    }


                    /*send a flag from angular whether it is payu or salucro*/
                    //return this.Success(this.applicationConfiguration.PaymentLink + this.aesHelper.Encode(appointmentLogId.ToString()));
                    //return this.Success(this.applicationConfiguration.SalucroPaymentLink + "?id=" + this.aesHelper.Encode(appointmentLogId.ToString()) + "&mode=payment");
                    return this.Success(new GenericResponse
                    {
                        Status = GenericStatus.Success,
                        Data = this.applicationConfiguration.SalucroPaymentLink + "?id=" + this.aesHelper.Encode(appointmentLogId.ToString()) + "&mode=payment"
                    });
            }
        }

        /// <summary>
        /// To fetch list of patients.
        /// </summary>
        /// <param name="model">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of patients.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch-existing-patients")]
        [ProducesResponseType(200, Type = typeof(List<PatientModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchExistingPatientsAsync([FromBody] PatientModel model)
        {
            model = (PatientModel)EmptyFilter.Handler(model);


            var existingPatients = await this.patientServices.FetchExistingPatientsAsync(model);
            foreach (var patient in existingPatients)
            {
                patient.EncryptedPatientId = this.aesHelper.Encode(patient.PatientId.ToString());
            }
            return this.Success(existingPatients);
        }

        /// <summary>
        /// To check follow up available for patient with selected doctor.
        /// </summary>
        /// <param name="model">
        /// The appointment request model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns follow up details.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("check-follow-up")]
        [ProducesResponseType(200, Type = typeof(AppointmentModel))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> CheckFollowUpForPatientAsync([FromBody] AppointmentModel model)
        {
            var recentAppointment = await this.patientServices.CheckForFollowUpForPatientAsync(model);
            return this.Success(recentAppointment);
        }

        /// <summary>
        /// The add appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 400 - Appointment time is required.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("add")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(400)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> AddAsync([FromForm] BookAppointmentRequest model)
        {
            //model.Total = model.Amount;
            var response = await this.AddAsyncHelper(model);
            return this.Success(response);
        }

        /// <summary>
        /// Adds the asynchronous helper.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        [NonAction]
        public async Task<GenericResponse> AddAsyncHelper(BookAppointmentRequest model)
        {
            try
            {
                model = (BookAppointmentRequest)EmptyFilter.Handler(model);
                if (model.LocationId == 0)
                {
                    // model.LocationId = int.Parse(header.LocationId);
                    return new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = "Model Id is NUll"
                    };
                }
                var appointmentModel = this.mapper.Map<AppointmentModel>(model);
                appointmentModel.AppointmentTime = TimeSpan.Parse(model.AppointmentTime);
                appointmentModel.AppointmentEndTime = TimeSpan.Parse(model.AppointmentEndTime);

                var appointmentId = 0;
                try
                {

                    appointmentModel.PatientRegistrationAmount = model.PatientRegistrationAmount != null ? (decimal)model.PatientRegistrationAmount : 0;
                    appointmentId = await this.appointmentsServices.AddAsync(appointmentModel);
                    if (appointmentId == 1)
                    {
                        appointmentId = (int)model.AppointmentId;
                    }

                    try
                    {
                        var data = new
                        {
                            statusId = 7
                        };
                        await this.client.UpdateAsync("appointments/" + appointmentId, data);
                    }
                    catch (Exception)
                    {
                        /* Ignore as of now but later log into error logs*/
                    }
                }
                catch (Exception exception)
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = JsonConvert.SerializeObject(exception)
                    };
                }
                var appointmentHangfireMapModel = new AppointmentHangfireMapModel()
                {
                    AppointmentId = appointmentId,
                    AppointmentDate = model.AppointmentDate,
                    AppointmentTime = TimeSpan.Parse(model.AppointmentTime),
                    Status = "B",
                };
                var aHMapId = 0;
                try
                {
                    aHMapId = await this.appointmentsServices.AddAppointmentHangfireAsync(appointmentHangfireMapModel);
                }
                catch (Exception exception)
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = JsonConvert.SerializeObject(exception)
                    };
                }
                if (aHMapId == 0)
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = "Appointment Sms and Email Log not added."
                    };
                }

                if (appointmentId == 0)
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Error,
                        Message = "Appointment not added."
                    };
                }

                var appointment = await this.appointmentsServices.FindAsync(appointmentId);

                if (appointment != null)
                {
                    var timespan = new TimeSpan(appointment.AppointmentTime.Hours, appointment.AppointmentTime.Minutes, appointment.AppointmentTime.Seconds);
                    var time = DateTime.Today.Add(timespan);
                    var displayTime = time.ToString("hh:mm tt");
                    // Sending Message
                    if (appointment.PaymentStatus == true)
                    {
                        BackgroundJob.Enqueue(() => this.smsSender.SendPaymentMessageAsync(appointment, displayTime));
                    }
                    //email and Appointment Message.
                    BackgroundJob.Enqueue(() => this.AppointmentActions(appointment, "Book", true));

                }
                else
                {
                    return new GenericResponse
                    {
                        Status = GenericStatus.Warning,
                        Message = "Appointment has been added successfully! but it seems there is an error after booking!"
                    };
                }

                //if (appointment != null && appointment.PaymentStatus != false)
                //{
                //    try
                //    {
                //        var res = await this.appointmentsServices.FindReceiptByAppointmentId(appointmentId);

                //        var auditLogModel = new AuditLogModel
                //        {
                //            AccountId = model.CreatedBy,
                //            LogTypeId = (int)LogTypes.Services,
                //            LogFrom = model.LogFrom,
                //            LogDate = DateTime.UtcNow.AddMinutes(330),
                //            LogDescription = $@"{model.CreatedByName} Generated <b>Receipt</b> with <br>
                //                       ReceiptNo.:<b>RN-{res.ToString().PadLeft(6, '0')}</b> for the Patient:<b> {appointment.PatientName}</b>"
                //        };
                //        await this.auditLogServices.LogAsync(auditLogModel);
                //    }
                //    catch (Exception e) { }
                //}

                switch (appointmentId)
                {
                    case -1:
                        return new GenericResponse
                        {
                            Status = GenericStatus.Warning,
                            Message = "Given appointment has already been exists with us."
                        };
                    case 0:
                        return new GenericResponse
                        {
                            Status = GenericStatus.Error,
                            Message = "Internal Server Error"
                        };
                    default:
                        await this.timelineService.LogAsync(new TimelineModel
                        {
                            PatientId = appointmentModel.PatientId,
                            AppointmentId = appointmentId,
                            TimelineActionId = TimelineAction.AppointmentAdded,
                            CreatedBy = appointmentModel.CreatedBy,
                            Description = $"Appointment has been added"
                        });


                        var auditLogModel = new AuditLogModel
                        {
                            AccountId = model.CreatedBy,
                            LogTypeId = (int)LogTypes.Appointments,
                            LogFrom = model.LogFrom,
                            LogDate = DateTime.UtcNow.AddMinutes(330),
                            LogDescription = $@"For Patient: <b>{appointment?.PatientName}</b>, the <b>{((appointment.FollowUpForAppointmentId != null || appointment.FollowUpForAdmissionId != null) ? "Follow Up" : "New")}</b> Appointment has been booked<br>
                         with Doctor: <b>Dr.{appointment?.ProviderName}</b> on <b>{appointment?.AppointmentDate.ToString("MM/dd/yyyy")} {appointment?.AppointmentDate.Add(appointment.AppointmentTime).ToString("hh:mm tt")}</b>",
                            LocationId = Convert.ToInt32(model.LocationId)
                        };

                        await this.auditLogServices.LogAsync(auditLogModel);

                        var communicationModel = new CommunicationMessageAlt
                        {
                            Type = 1,
                            GroupName = "QueueManagement"
                        };
                        await this.hubContext.Clients.Group("QueueManagement").SendAsync("CommunicationGroup", communicationModel).ConfigureAwait(false);

                        //var communicationModelRefresh = new CommunicationMessageAlt
                        //{
                        //    Type = 1,
                        //    GroupName = "AppointmentRefresh"
                        //};
                        //await this.hubContext.Clients.Group("AppointmentRefresh").SendAsync("CommunicationGroup", communicationModel).ConfigureAwait(false);

                        return new GenericResponse
                        {
                            Status = GenericStatus.Success,
                            Message = "Appointment has been added successfully.",
                            Data = appointmentId
                        };
                }

            }
            catch (Exception e)
            {
                return new GenericResponse
                {
                    Status = GenericStatus.Error,
                    Message = e.Message
                };
            }
        }


        /// <summary>
        /// The reschedule appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment rescheduled successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("reschedule")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> RescheduleAppointmentAsync([FromBody] RescheduleAppointmentRequest model, [FromHeader] LocationHeader header)
        {
            model = (RescheduleAppointmentRequest)EmptyFilter.Handler(model);
            model.LocationId = int.Parse(header.LocationId);
            var appointmentTime = TimeSpan.Parse(model.AppointmentTime);
            var appointmentEndTime = TimeSpan.Parse(model.AppointmentEndTime);
            var tokenNumber = model.TokenNumber == 0 ? 0 : model.TokenNumber;
            //var response = await this.appointmentsServices.RescheduleAsync(model.AppointmentId, model.AppointmentDate, appointmentTime, model.AppointmentNotes, Convert.ToInt32(model.ModifiedBy), model.ProviderId, model.ProviderLocationId, model.DepartmentId, model.LocationId, model.TokenNumber, model.SpecializationId);

            var response = await this.appointmentsServices.RescheduleAsync(model.AppointmentId, model.AppointmentDate, appointmentTime, appointmentEndTime, model.AppointmentNotes, Convert.ToInt32(model.ModifiedBy), model.ProviderId, model.ProviderAvailabilityId, model.ConsultationTypeId, model.DepartmentId, model.LocationId, model.TokenNumber, model.SpecializationId);
            if (response == 0)
            {
                return this.ServerError();
            }
            try
            {
                var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);


                //var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);
                var appointmentHangfireMapModel = new AppointmentHangfireMapModel()
                {
                    AppointmentId = model.AppointmentId,
                    AppointmentDate = model.AppointmentDate,
                    AppointmentTime = appointmentTime,
                    Status = "R",
                };
                var aHMapId = 0;

                aHMapId = await this.appointmentsServices.AddAppointmentHangfireAsync(appointmentHangfireMapModel);

                if (appointment != null)
                {
                    var timespan = new TimeSpan(appointment.AppointmentTime.Hours, appointment.AppointmentTime.Minutes, appointment.AppointmentTime.Seconds);
                    var time = DateTime.Today.Add(timespan);
                    var displayTime = time.ToString("hh:mm tt");
                    var messageType = "has been rescheduled successfully";
                    // Sending Message
                    await this.smsSender.SendAppointmentMessageAsync(appointment, messageType, displayTime);
                    var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                    var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                    if ((bool)WhatsAppMessage[0].Active)
                    {
                        var LocationQuery = $@"select l.""LocationId"",l.""Name"",l.""PracticeId"",p.""FullName"" as ""PracticeName"" from ""Location"" l
                           join ""Practice"" p on p.""PracticeId"" = l.""PracticeId"" where ""LocationId"" = {appointment.LocationId} limit 1";

                        var Location = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LocationModel>(LocationQuery);
                        bool ret = await this.whatsAppSMSSender.SendWhatsAppMessageAsync(appointment, displayTime, messageType, Location.Name);
                    }

                    //email and Message.
                    BackgroundJob.Enqueue(() => this.AppointmentActions(appointment, "ReSchedule", true));


                }
                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription = $@"Patient: <b>{appointment?.PatientName}</b>, Appointment on <b>{appointment?.AppointmentDate.ToString("MM/dd/yyyy")} {appointment?.AppointmentDate.Add(appointment.AppointmentTime).ToString("hh:mm tt")}</b><br>
                has been <b>Reschedule</b> with Doctor: <b>Dr.{appointment?.ProviderName}.</b>",
                    LocationId = model.LocationId
                };

                await this.auditLogServices.LogAsync(auditLogModel);
            }
            catch (Exception e)
            {
                e.Message.ToString();
            }
            return this.Success("Appointment has been Rescheduled successfully.");
        }

        /// <summary>
        /// The reschedule appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment rescheduled successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("confirm-appointment")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> ConfirmAppointmentAsync([FromBody] ConfirmAppointmentRequest model)
        {
            var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);

            if (appointment != null)
            {
                await this.AppointmentActions(appointment, "Confirm", false);
            }

            return this.Success("Appointment has been confirmed successfully.");
        }

        /// <summary>
        /// The reschedule appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment rescheduled successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("delay-appointment")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> DelayAppointmentAsync([FromBody] ConfirmAppointmentRequest model)
        {
            var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);
            appointment.Delay = model.Delay;

            if (appointment != null)
            {
                await this.AppointmentActions(appointment, "Delay", false);
            }

            return this.Success("Appointment has been delayed successfully.");
        }

        /// <summary>
        /// The cancel appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment canceled successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPut]
        [Authorize]
        [Route("cancel")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> CancelAsync([FromBody] AppointmentModel model, [FromHeader] LocationHeader header)
        {
            model = (AppointmentModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);

            var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);
            appointment.CancelType = model.CancelType;
            var aptTxn = await this.appointmentTransactionService.FetchAsync(model.AppointmentId);
            //if (aptTxn != null)
            //{
            //    appointment.Total = (decimal)aptTxn.SettledAmount;
            //}

            var reciepts = await this.unitOfWork.Receipt.FindAllAsync(x => x.RespectiveId == model.AppointmentId && x.ReceiptTypeId == ReceiptType.Cash && x.ReceiptAreaTypeId == ReceiptAreaType.Appointment);
            var receiptsTotal = 0.0;
            if (reciepts.Count() > 0)
            {
                foreach (var item in reciepts)
                {
                    receiptsTotal += item.Cost;
                }
            }
            appointment.Total = (decimal)receiptsTotal;

            if (model.IsWeb == true && appointment.IsSalucroAppointment && appointment.CancelType == "CAppC")
            {
                return this.Success(this.applicationConfiguration.SalucroPaymentLink + "?id=" + this.aesHelper.Encode(model.AppointmentId.ToString()) + "&mode=refund" + "&modifiedBy=" + model.ModifiedBy + "&reason=" + model.Reason);
            }

            var message = "Appointment cancelled successfully";

            if (appointment != null)
            {
                if (appointment.Total > 0)
                {
                    //var transaction = await this.appointmentTransactionService.FetchAsync(model.AppointmentId);
                    if (aptTxn != null && (model.IsWeb == false || model.IsPatientApp == true))
                    {
                        var paymode = "payment-refund";
                        var patient_name = appointment.PatientName;
                        var account_number = appointment.UMRNo;
                        var processing_id = await this.appointmentTransactionService.GetATransactionId();
                        /****amount in check sum preparation should be in type float or double not decimal bcoz salucro people are using php, so it won't support decimal type and it fails check sum validation****/
                        var hashString = processing_id + "|" + this.salucroConfiguration.MId + "|" + this.salucroConfiguration.User + "|" + this.salucroConfiguration.Key + "|" + this.salucroConfiguration.UserName + "|" + paymode + "|" + patient_name + "|" + account_number + "|" + (double)appointment.Total + "|" + aptTxn.TransactionId + "|" + this.salucroConfiguration.SecretKey;
                        var check_sum_hash = Convert.ToBase64String(HttpUtility.UrlEncodeToBytes(Encoding.ASCII.GetBytes(PaymentHelper.GenerateCheckSumHash(hashString))));

                        if (aptTxn.SalucroTransactionId != null)
                        {
                            var salucroResponse = await this.salucroHelper.RefundAsync(processing_id, paymode, patient_name, account_number, appointment.Total, appointment.PatientEmail, aptTxn.TransactionId, check_sum_hash);

                            dynamic item = JsonConvert.DeserializeObject(salucroResponse.Content);
                            int statusCode = item["status_code"];
                            string salucroTransactionId = item["transaction_id"];
                            string transactionId = item["processing_id"];
                            if (!salucroResponse.IsSuccessful || statusCode != 1200)
                            {
                                message = "Failed to initiate refund";
                                return this.Success(message);
                            }

                            message = "Appointment cancelled successfully and refund initiated";
                            var result = await appointmentHelper.CancelAppointmentAsync(appointment, null, salucroResponse.Content, transactionId, statusCode, salucroTransactionId, model.ModifiedBy, model.Reason);
                            if (result)
                            {
                                return this.Success(message);
                            }
                            else
                            {
                                return this.ServerError("Failed to Cancel");
                            }

                        }
                        else if (aptTxn.PaymentId > 0)
                        {
                            var refund = new RefundModel
                            {
                                PaymentId = aptTxn.PaymentId,
                                RefundAmount = (long)appointment.Total,
                                AppointmentTransactionId = aptTxn.AppointmentTransactionId,
                                CreatedBy = (int)model.ModifiedBy
                            };
                            var payuResponse = await this.payUHelper.RefundAsync(refund.PaymentId, refund.RefundAmount);
                            var item = JsonConvert.DeserializeObject<PayURefundModel>(payuResponse.Content);
                            if (!payuResponse.IsSuccessful || !(item.Status >= 0))
                            {
                                message = "Failed to return bank amount";
                                return this.Success(message);
                            }

                            refund.RefundStatus = item.Message;
                            if (item.Result != null)
                            {
                                refund.RefundTransactionId = (int)item.Result;
                            }

                            await this.payUService.AddRefundAsync(refund);
                            message = "Appointment cancelled successfully and refund initiated";
                            var response = await appointmentHelper.CancelAppointmentAsync(appointment, null, null, null, null, null, model.ModifiedBy, model.Reason);
                            if (response)
                            {
                                return this.Success(message);
                            }
                            else
                            {
                                return this.ServerError("Failed to Cancel");
                            }
                        }
                    }
                }
                var res = await appointmentHelper.CancelAppointmentAsync(appointment, null, null, null, null, null, model.ModifiedBy, model.Reason); //add reson
                if (res)
                {
                    return this.Success(message);
                }
                else
                {
                    return this.ServerError("Failed to Cancel");
                }
            }
            return this.Success(message);
        }

        /// <summary>
        /// The update patient type for appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment updated successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPut]
        [Authorize]
        [Route("update-patient-type")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> UpdatePatientTypeAsync([FromBody] AppointmentModel model, [FromHeader] LocationHeader header)
        {
            model = (AppointmentModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);
            var response = await this.appointmentsServices.UpdatePatientTypeAsync(model.AppointmentId, Convert.ToInt32(model.ModifiedBy), model.PatientType, Convert.ToInt32(model.VisitTypeId));
            if (response > 0)
            {
                var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);

                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow,
                    LogDescription = $"For Patient:{appointment.PatientName} Appointment Type for ({appointment.AppointmentNo}) has been <b>Updated</b> successfully,<br> with Doctor: {appointment.ProviderName}.",
                    LocationId = model.LocationId
                };
                await this.auditLogServices.LogAsync(auditLogModel);
            }
            return this.Success("Appointment has been updated successfully.");
        }

        /// <summary>
        /// The update payment status for appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment payment updated successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("update-payment-status")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> UpdatePaymentStatusAsync([FromForm] PatientPaymentModel model, [FromHeader] LocationHeader header)
        {
            model = (PatientPaymentModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);

            var response = await this.appointmentsServices.UpdatePaymentStatusAsync(model);
            if (model.WebType == "admin")
            {
                PatientModel patient = new PatientModel();
                patient.Salutation = model.Salutation;
                patient.PatientId = model.PatientId;
                patient.FirstName = model.FirstName;
                patient.MiddleName = model.MiddleName;
                patient.LastName = model.LastName;
                patient.DateOfBirth = model.DateOfBirth;
                patient.Age = model.Age;
                patient.Gender = model.Gender;
                patient.MaritalStatus = model.MaritalStatus;
                patient.Email = model.Email;
                patient.Mobile = model.Mobile;
                patient.StreetAddress = model.StreetAddress;
                patient.AddressLine2 = model.AddressLine2;
                patient.City = model.City;
                patient.State = model.State;
                patient.ModifiedBy = model.ModifiedBy;
                patient.ModifiedDate = DateTime.UtcNow;
                patient.AadharNo = patient.AadharNo;
                patient.PatientReferredById = model.PatientReferredById;
                patient.ReferredByName = model.ReferredByName;
                patient.HWCPatientId = model.HWCPatientId;
                patient.Occupation = model.Occupation;
                patient.Nationality = model.Nationality;
                patient.Religion = model.Religion;
                patient.IdProofId = model.IdProofId;
                patient.IdProofValue = model.IdProofValue;
                patient.PayTypeId = model.PayTypeId;
                patient.EducationId = model.EducationId;
                patient.OccupationId = model.OccupationId;
                patient.OccupationDetail = model.OccupationDetail;
                patient.HWCPatientId = model.HWCPatientId;
                patient.Nationality = model.Nationality;
                patient.CountryId = model.CountryId;
                patient.PaymentNumber = model.PaymentNumber;
                patient.PaymentStatus = model.PaymentStatus;
                patient.InsuranceId = model.InsuranceCompanyId;
                patient.FullName = CoreFilter.FullName(model.FirstName, model.MiddleName, model.LastName);

                PatientFamilyModel pfModel = new PatientFamilyModel();
                pfModel.FullName = model.RelationName;
                pfModel.PatientFamilyId = await this.patientServices.FetchPatientFamilyIdAsync(model.PatientId);
                pfModel.Education = model.RealtiveEducation;
                pfModel.ContactNo = model.RelativeMobile;
                pfModel.RelativeGender = model.RelativeGender;
                pfModel.Relation = model.Relation;
                pfModel.CreatedBy = model.CreatedBy;
                pfModel.CreatedDate = DateTime.UtcNow.AddMinutes(330);
                pfModel.Occupation = model.RelativeOccupation;

                var patientData = await this.patientServices.UpdatePatientDetailsAsync(patient, pfModel);
            }
            if (response > 0)
            {
                var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);
                if (appointment.PaymentStatus == true)
                {
                    var timespan = new TimeSpan(appointment.AppointmentTime.Hours, appointment.AppointmentTime.Minutes, appointment.AppointmentTime.Seconds);
                    var time = DateTime.Today.Add(timespan);
                    var displayTime = time.ToString("hh:mm tt");
                    await this.smsSender.SendPaymentMessageAsync(appointment, displayTime);
                }
                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow,
                    LogDescription = $"For Patient: {appointment.PatientName}, Payment status for ({appointment.AppointmentNo}) has been <b>Updated</b> successfully,<br> with Doctor: {appointment.ProviderName}.",
                    LocationId = model.LocationId
                };
                await this.auditLogServices.LogAsync(auditLogModel);
            }
            var genericResponse = new GenericResponse()
            {
                Message = "Appointment has been updated successfully."
            };
            return this.Success(genericResponse);




        }

        /// <summary>
        /// update payment  the asynchronous helper.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        public async Task<GenericResponse> UpdatePaymentHelper(PatientPaymentModel model)
        {
            model = (PatientPaymentModel)EmptyFilter.Handler(model);
            //var processing_id = PaymentHelper.GenerateTransactionId();
            //model.TransactionId = processing_id;
            var response = await this.appointmentsServices.UpdatePaymentStatusAsync(model);
            if (response > 0)
            {
                var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);
                if (appointment.PaymentStatus == true)
                {
                    var timespan = new TimeSpan(appointment.AppointmentTime.Hours, appointment.AppointmentTime.Minutes, appointment.AppointmentTime.Seconds);
                    var time = DateTime.Today.Add(timespan);
                    var displayTime = time.ToString("hh:mm tt");
                    await this.smsSender.SendPaymentMessageAsync(appointment, displayTime);
                }
                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow,
                    LogDescription = $"For Patient: {appointment.PatientName}, Payment status for ({appointment.AppointmentNo}) has been <b>Updated</b> successfully,<br> with Doctor: {appointment.ProviderName}.",
                    LocationId = model.LocationId
                };
                await this.auditLogServices.LogAsync(auditLogModel);

            }
            return new GenericResponse
            {
                Data = response
            };

        }

        /// <summary>
        /// Add Symptoms to appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Symptoms added to Appointment successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("add-symptoms")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> AddSymptomsAsync([FromBody] AppointmentModel model, [FromHeader] LocationHeader header)
        {
            model.LocationId = Convert.ToInt32(header.LocationId);
            var response = await this.appointmentsServices.AddSymptomsAsync(model.AppointmentId, model.AppointmentNotes, model.CreatedBy, model.IsAdmission);
            if (response == 0)
            {
                return this.ServerError();
            }
            var auditLogModel = new AuditLogModel
            {
                AccountId = model.CreatedBy,
                LogTypeId = (int)LogTypes.Appointments,
                LogFrom = model.LogFrom,
                LogDate = DateTime.UtcNow,
                LogDescription = "Symptoms added to Appointment successfully.",
                LocationId = model.LocationId
            };
            await this.auditLogServices.LogAsync(auditLogModel);
            return this.Success("Symptoms added to Appointment successfully.");
        }

        /// <summary>
        /// Update Relation in appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Relation updated to Appointment successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("update-patient-familyid")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> UpdateRelationIdAsync([FromBody] AppointmentModel model)
        {
            var response = await this.appointmentsServices.UpdateRelationIdAsync(model.AppointmentId, model.CreatedBy, model.PatientFamilyId);
            if (response == 0)
            {
                return this.ServerError();
            }

            return this.Success("Patient Family added to Appointment successfully.");
        }

        /// <summary>
        /// The delete appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment deleted successfully.
        /// - 409 - Appointment can not be deleted.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpDelete]
        [Authorize]
        [Route("delete")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> DeleteAsync([FromBody] AppointmentModel model)
        {
            try
            {
                model = (AppointmentModel)EmptyFilter.Handler(model);
                var response = await this.appointmentsServices.DeleteAsync(model.AppointmentId);
                if (response == 0)
                {
                    return this.ServerError();
                }

                return this.Success("Appointment has been deleted successfully.");
            }
            catch (NpgsqlException exception)
            {
                if (exception.Message.Contains("violates foreign key constraint"))
                {
                    return this.Conflict("Appointment can't be deleted. Please contact administrator.");
                }

                return this.ServerError();
            }
        }

        /// <summary>
        /// To find appointment
        /// </summary>
        /// <param name="model" >
        /// The appointment find request Model.
        /// </param>
        /// <returns>
        /// The appointment model.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - appointment model.
        /// - 400 - Sorry! We don't have a appointment in the system.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Route("find")]
        [ProducesResponseType(typeof(AppointmentModel), 200)]
        [ProducesResponseType(typeof(string), 400)]
        [ProducesResponseType(500)]
        [AllowAnonymous]

        public async Task<ActionResult> FindAsync([FromBody] FindAppointmentRequest model)
        {
            model = (FindAppointmentRequest)EmptyFilter.Handler(model);
            var appointmentId = model.AppointmentId <= 0 ? Convert.ToInt32(this.aesHelper.Decode(model.EncryptedAppointmentId)) : model.AppointmentId;

            var appointment = await this.appointmentsServices.FindAsync(appointmentId);
            if (appointment == null || appointment.AppointmentId == 0)
            {
                return this.BadRequest("Sorry! We don't have a appointment in the system.");
            }

            appointment.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(appointment.AppointmentTime).ToString("hh:mm tt");
            return this.Success(appointment);
        }

        /// <summary>
        /// To find appointment async
        /// </summary>
        /// <param name="model" >
        /// The appointment find request Model.
        /// </param>
        /// <returns>
        /// The appointment model.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - appointment model.
        /// - 400 - Sorry! We don't have a appointment in the system.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [AllowAnonymous]
        [Route("find-appointment")]
        [ProducesResponseType(typeof(AppointmentModel), 200)]
        [ProducesResponseType(typeof(string), 400)]
        [ProducesResponseType(500)]

        public async Task<ActionResult> FindAppointmentAsync([FromBody] FindAppointmentRequest model)
        {
            model = (FindAppointmentRequest)EmptyFilter.Handler(model);
            int appointmentId;
            if (string.IsNullOrEmpty(model.EncryptedAppointmentId))
            {
                appointmentId = model.AppointmentId;
            }
            else
            {
                appointmentId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedAppointmentId));
            }
            var appointment = await this.appointmentsServices.FindAppointmentAsync(appointmentId, model.IsAdmission);
            if (appointment == null)
            {
                var token = model.IsAdmission ? "Admission" : "Appointment";
                return this.BadRequest($"Sorry! We don't have a {token} in the system.");
            }

            appointment.EncryptedAppointmentId = model.EncryptedAppointmentId;
            appointment.EncryptedPatientId = this.aesHelper.Encode(appointment.PatientId.ToString());
            appointment.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(appointment.AppointmentTime).ToString("hh:mm tt");

            //if (!string.IsNullOrEmpty(appointment.PatientThumbnailUrl))
            //{
            //    appointment.PatientThumbnailUrl = await this.documentHelper.FetchImageBase64(appointment.PatientId, appointment.PatientThumbnailUrl);
            //}

            return this.Success(appointment);
        }

        /// <summary>
        /// To fetch appointment symptoms async
        /// </summary>
        /// <param name="model" >
        /// The appointment find request Model.
        /// </param>
        /// <returns>
        /// The appointment symptom model.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - appointment model.
        /// - 400 - Sorry! We don't have a appointment in the system.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-appointment-symptoms")]
        [ProducesResponseType(typeof(AppointmentSymptomModel), 200)]
        [ProducesResponseType(typeof(string), 400)]
        [ProducesResponseType(500)]

        public async Task<ActionResult> FetchAppointmentSymptomsAsync([FromBody] FindAppointmentRequest model)
        {
            model = (FindAppointmentRequest)EmptyFilter.Handler(model);

            var appointmentId = model.AppointmentId;

            var appointmentSymptoms = await this.appointmentsServices.FetchAppointmentSymptomsAsync(appointmentId, model.IsAdmission);

            return this.Success(appointmentSymptoms);
        }

        /// <summary>
        /// The not book appointment
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("doctor-device-create")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> DoctorDeviceInsert([FromBody] DoctorDeviceDetailsModel model)
        {
            var response = await this.doctorDeviceServices.InsertAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// The not book appointment
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("patient-device-create")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> PatientDeviceInsert([FromBody] PatientDeviceDetailsModel model)
        {
            var response = await this.patientDeviceServices.InsertAsync(model);
            return this.Success(response);
        }

        /// <summary>
        /// The not book appointment
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("video-call-history")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> VideoCallInsert([FromBody] DoctorDeviceDetailsModel model)
        {
            var response = await this.videoHistoryServices.InsertAsync(model.AppointmentId ?? 0);
            return this.Success(response);
        }

        /// <summary>
        /// The encounter async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <param name="encounterType">
        /// The encounter type.
        /// </param>
        /// <param name="isAdmission"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPut]
        [Authorize]
        [Route("encounter-update")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> UpdateEncounterTypeAsync([FromBody] int appointmentId, int encounterType, bool isAdmission)
        {
            var response = await this.appointmentsServices.UpdateEncounterTypeAsync(appointmentId, encounterType, isAdmission);
            return response == 0 ? this.ServerError() : this.Success("Appointment Encounter updated successfully.");
        }



        [HttpPost]
        [AllowAnonymous]
        [Route("sendSms")]
        public async Task<bool> sendAppointmentBookingMessage([FromBody] AppointmentModel appointment)
        {
            //TimeSpan timespan = new TimeSpan(
            //        appointment.AppointmentTime.Hours,
            //        appointment.AppointmentTime.Minutes,
            //        appointment.AppointmentTime.Seconds);
            //DateTime time = DateTime.Today.Add(timespan);
            //string displayTime = time.ToString("hh:mm tt");
            string displayTime2 = appointment.AppointmentTimeString;
            var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
            var WhatsAppMessage = WhatsAppMessageSetting.ToList();
            if ((bool)WhatsAppMessage[0].Active)
            {
                var LocationQuery = $@"select l.""LocationId"",l.""Name"",l.""PracticeId"",p.""FullName"" as ""PracticeName"" from ""Location"" l
                           join ""Practice"" p on p.""PracticeId"" = l.""PracticeId"" where ""LocationId"" = {appointment.LocationId} limit 1";

                var Location = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LocationModel>(LocationQuery);
                bool ret = await this.whatsAppSMSSender.SendWhatsAppMessageAsync(appointment, displayTime2, "Book", Location.Name);
            }
            return await this.smsSender.SendAppointmentMessageAsync(appointment, "Book", displayTime2);
        }

        /// <summary> The appointment actions.</summary>
        /// <param name="appointment"> The appointment.</param>
        /// <param name="type"> The type.</param>
        /// <param name="toProvider"></param>
        /// <returns>The <see cref="Task"/>.</returns>
        [NonAction]
        public async Task<bool> AppointmentActions(AppointmentModel appointment, string type, bool toProvider = true)
        {
            if (appointment != null)
            {
                TimeSpan timespan = new TimeSpan(
                    appointment.AppointmentTime.Hours,
                    appointment.AppointmentTime.Minutes,
                    appointment.AppointmentTime.Seconds);
                DateTime time = DateTime.Today.Add(timespan);
                string displayTime = time.ToString("hh:mm tt");

                var prevDisplayTime = string.Empty;
                if (type == "ReSchedule" && appointment.AppointmentPreviousDate != null && appointment.AppointmentPreviousTime != null)
                {
                    TimeSpan prevTimespan = new TimeSpan(
                    appointment.AppointmentPreviousTime?.Hours ?? 0,
                    appointment.AppointmentPreviousTime?.Minutes ?? 0,
                    appointment.AppointmentPreviousTime?.Seconds ?? 0);
                    DateTime prevTime = DateTime.Today.Add(prevTimespan);
                    prevDisplayTime = prevTime.ToString("hh:mm tt");
                }

                string messageType = null;

                switch (type)
                {
                    case "Book":
                        messageType = "booked";
                        break;
                    case "ReSchedule":
                        messageType = "has been rescheduled successfully";
                        break;
                    case "Cancel":
                        messageType = "has been cancelled";
                        break;
                    case "Confirm":
                        messageType = "confirmed";
                        break;
                    case "Delay":
                        messageType = "delayed";
                        break;
                }
                var patientMessage = (type == "Confirm"
                            ? ("Your appointment with DR. " + appointment.ProviderName.ToUpper() + " will be started soon")
                            : type == "Delay"
                            ? ("Your appointment with DR. " + appointment.ProviderName.ToUpper() + " has been delayed by " + appointment.Delay)
                            : (appointment.PatientName + " patient " + messageType + " an Appointment with you on Date:" + appointment.AppointmentDate.ToString("dd MMMM yyyy") + " Time: " + displayTime + " "));

                var providerMessage = (type == "Confirm"
                            ? ("Your appointment with DR. " + appointment.ProviderName.ToUpper() + " will be started soon")
                            : type == "Delay"
                            ? ("Your appointment with DR. " + appointment.ProviderName.ToUpper() + " has been delayed by " + appointment.Delay)
                            : ("Appointment " + messageType + " with DR. " + appointment.ProviderName.ToUpper() + " on Date:" + appointment.AppointmentDate.ToString("dd MMMM yyyy") + " Time: " + displayTime + " "));
                bool isSMSSettingEnabled = await this.settingService.CheckSmsEnabled();
                if (isSMSSettingEnabled == false)
                {
                    // SMS to Doctor and Patient

                    await this.smsSender.SendAppointmentMessageAsync(appointment, messageType, displayTime);
                    // end
                }
                var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                if ((bool)WhatsAppMessage[0].Active)
                {
                    var LocationQuery = $@"select l.""LocationId"",l.""Name"",l.""PracticeId"",p.""FullName"" as ""PracticeName"" from ""Location"" l
                           join ""Practice"" p on p.""PracticeId"" = l.""PracticeId"" where ""LocationId"" = {appointment.LocationId} limit 1";

                    var Location = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LocationModel>(LocationQuery);
                    bool ret = await this.whatsAppSMSSender.SendWhatsAppMessageAsync(appointment, displayTime, messageType, Location.Name);
                }

                // Sending push notifications to Doctor and Patient
                if (appointment.EnableMobileNotifications == true && toProvider)
                {
                    var accountSessionProviderModel = await this.accountSessionServices.FetchDeviceTokenAsync(appointment.ProviderId, Roles.Provider);
                    var sessionProviderModel = accountSessionProviderModel as AccountSessionModel[] ?? accountSessionProviderModel.ToArray();
                    if (sessionProviderModel.Any())
                    {
                        var deviceTokenForProviderAndroid = sessionProviderModel.Where(d => d.DeviceType == 2).Select(s => s.DeviceToken).ToList();
                        var deviceTokenForProviderIOS = sessionProviderModel.Where(d => d.DeviceType == 3).Select(s => s.DeviceToken).ToList();

                        if (deviceTokenForProviderAndroid.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                patientMessage,
                                (type == "Confirm" ? "Confirmed" : type == "Delay" ? "Delayed" : "Appointment"),
                                deviceTokenForProviderAndroid,
                                new List<string>(),
                                appointment.ProviderName,
                                (appointment.AppointmentDate.ToString("MM/dd/yyyy") + " " + displayTime),
                                (appointment.AppointmentPreviousDate != null ? (appointment.AppointmentPreviousDate?.ToString("MM/dd/yyyy") + " " + prevDisplayTime) : null));
                        }

                        if (deviceTokenForProviderIOS.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                patientMessage,
                                (type == "Confirm" ? "Confirmed" : type == "Delay" ? "Delayed" : "Appointment"),
                                new List<string>(),
                                deviceTokenForProviderIOS,
                                appointment.ProviderName,
                                (appointment.AppointmentDate.ToString("MM/dd/yyyy") + " " + displayTime),
                                (appointment.AppointmentPreviousDate != null ? (appointment.AppointmentPreviousDate?.ToString("MM/dd/yyyy") + " " + prevDisplayTime) : null));
                        }
                    }
                }

                var accountSessionPatientModel = await this.accountSessionServices.FetchDeviceTokenAsync(appointment.PatientId, Roles.Patient);
                var accountSessionModels = accountSessionPatientModel as AccountSessionModel[] ?? accountSessionPatientModel.ToArray();
                if (accountSessionModels.Any())
                {
                    var deviceTokenForProviderAndroid = accountSessionModels.Where(d => d.DeviceType == 2).Select(s => s.DeviceToken).ToList();
                    var deviceTokenForProviderIOS = accountSessionModels.Where(d => d.DeviceType == 3).Select(s => s.DeviceToken).ToList();
                    if (appointment.ProviderName != null)
                    {
                        if (deviceTokenForProviderAndroid.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                providerMessage,
                                (type == "Confirm" ? "Confirmed" : type == "Delay" ? "Delayed" : "Appointment"),
                                deviceTokenForProviderAndroid,
                                new List<string>(),
                                appointment.ProviderName,
                                (appointment.AppointmentDate.ToString("MM/dd/yyyy") + " " + displayTime),
                                (appointment.AppointmentPreviousDate != null ? (appointment.AppointmentPreviousDate?.ToString("MM/dd/yyyy") + " " + prevDisplayTime) : null));
                        }
                        if (deviceTokenForProviderIOS.Any())
                        {
                            await this.pushNotificationHelper.SendAltAsync(
                                "Hims",
                                providerMessage,
                                (type == "Confirm" ? "Confirmed" : type == "Delay" ? "Delayed" : "Appointment"),
                                new List<string>(),
                                deviceTokenForProviderIOS,
                                appointment.ProviderName,
                                (appointment.AppointmentDate.ToString("MM/dd/yyyy") + " " + displayTime),
                                (appointment.AppointmentPreviousDate != null ? (appointment.AppointmentPreviousDate?.ToString("MM/dd/yyyy") + " " + prevDisplayTime) : null));
                        }
                    }
                }

                // end

                bool isEmailSettingEnabled = await this.settingService.CheckEmailEnabled();
                if (isEmailSettingEnabled == false)
                {
                    if (!string.IsNullOrEmpty(appointment.PatientEmail))
                    {
                        await this.emailSender.SendBookAppointmentMailAsync(
                            appointment.PatientEmail,
                            appointment.PatientName,
                            "Patient",
                            appointment.ProviderName,
                            appointment.AppointmentDate.ToString("dd MMMM yyyy") + ", " + displayTime,
                            messageType);
                    }

                    if (!string.IsNullOrEmpty(appointment.ProviderEmail) && appointment.EnableEmailAlerts == true)
                    {
                        await this.emailSender.SendBookAppointmentMailAsync(
                            appointment.ProviderEmail,
                            appointment.PatientName,
                            "Doctor",
                            appointment.ProviderName,
                            appointment.AppointmentDate.ToString("dd MMMM yyyy") + ", " + displayTime,
                            messageType);
                    }
                }
            }

            return true;
        }

        /// <summary>
        /// The book async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="location"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("payment")]
        [ProducesResponseType(typeof(PaymentDetailsModel), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> BookAppointmentAsync([FromBody] BookAppointmentRequest model, [FromHeader] LocationHeader location)
        {
            try
            {

                model = (BookAppointmentRequest)EmptyFilter.Handler(model);
                if (model.LocationId == 0 && !string.IsNullOrEmpty(location.LocationId))
                {
                    model.LocationId = int.Parse(location.LocationId);
                }
                var appointmentLogModel = this.mapper.Map<AppointmentLogModel>(model);
                appointmentLogModel.AppointmentTime = TimeSpan.Parse(model.AppointmentTime);
                appointmentLogModel.AppointmentEndTime = TimeSpan.Parse(model.AppointmentEndTime);
                appointmentLogModel.AppointmentNotes = model.Symptoms;
                var providerBankAccountModel = await this.providerBankAccountServices.FindAsync(model.ProviderId);
                if (providerBankAccountModel != null)
                {
                    appointmentLogModel.Percentage = providerBankAccountModel.Percentage;
                }

                var appointmentLogId = await this.appointmentLogServices.AddAsync(appointmentLogModel);

                var appointmentLog = await this.appointmentLogServices.FindAsync(appointmentLogId);
                if (appointmentLog == null || appointmentLog.AppointmentLogId == 0)
                {
                    return this.ServerError();
                }

                var productInfo = $"Appointment with Dr.{appointmentLog.ProviderName}";

                var transactionId = await this.appointmentTransactionService.GetATransactionId();

                var hashString = "";
                var hashValue = "";
                var paymentDetails = new PaymentDetailsModel();
                if (model.PaymentGateway == "PayU")
                {
                    hashString = this.payUConfiguration.Key + "|" + transactionId + "|" + appointmentLog.Total + "|" + productInfo + "|" + appointmentLog.PatientFirstName + "|" + appointmentLog.PatientEmail + "|" + appointmentLog.AppointmentLogId + "||||||||||" + this.payUConfiguration.Salt;

                    hashValue = PaymentHelper.GenerateHash(hashString);

                    paymentDetails.Hashvalue = hashValue;
                    paymentDetails.TransactionId = transactionId;
                    paymentDetails.SuccessLink = this.payUConfiguration.SuccessLink;
                    paymentDetails.FailureLink = this.payUConfiguration.FailureLink;
                    paymentDetails.ProductInfo = productInfo;
                    paymentDetails.AppointmentLogId = appointmentLogId;

                }
                {
                    hashString = this.salucroConfiguration.User + "|" + this.salucroConfiguration.Key + "|" + transactionId + "|" + this.salucroConfiguration.MId + "|" + this.salucroConfiguration.SecretKey;

                    hashValue = Convert.ToBase64String(HttpUtility.UrlEncodeToBytes(Encoding.ASCII.GetBytes(PaymentHelper.GenerateCheckSumHash(hashString))));

                    paymentDetails.Hashvalue = hashValue;
                    paymentDetails.TransactionId = transactionId;
                    paymentDetails.SuccessLink = this.salucroConfiguration.ResponseURL;
                    paymentDetails.FailureLink = this.salucroConfiguration.MobileReturnURL;
                    paymentDetails.ProductInfo = productInfo;
                    paymentDetails.AppointmentLogId = appointmentLogId;
                }

                return this.Success(paymentDetails);
            }
            catch
            {
                return this.ServerError();
            }
        }

        /// <summary>
        /// The fetch support appointment log async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("fetch-support-appointment")]
        public async Task<ActionResult> FetchSupportAppointmentLogAsync([FromBody] AppointmentSupportLogModel model)
        {
            model = (AppointmentSupportLogModel)EmptyFilter.Handler(model);

            var res = await this.appointmentsServices.FetchSupportLogAsync(model);
            foreach (var item in res)
            {
                item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
            }

            return this.Success(res);
        }

        /// <summary>
        /// The update support appointment log async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("update-support-appointment-log")]
        public async Task<ActionResult> UpdateSupportAppointmentLogAsync([FromBody] AppointmentSupportLogModel model, [FromHeader] LocationHeader header)
        {
            model = (AppointmentSupportLogModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);
            var res = await this.appointmentsServices.UpdateLog(model);
            var auditLogModel = new AuditLogModel
            {
                AccountId = model.modifiedBy,
                LogTypeId = (int)LogTypes.AppointmentLogs,
                LogFrom = (int)AccountType.Administrator,
                LogDate = DateTime.UtcNow,
                LogDescription = $"Details has been updated successfully.",
                LocationId = model.LocationId
            };
            await this.auditLogServices.LogAsync(auditLogModel);
            return this.Success(res);
        }

        /// <summary>
        /// The add support appointment assignee async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("update-support-assignee")]
        public async Task<ActionResult> AddSupportAppointmentAssigneeAsync([FromBody] AppointmentSupportLogModel model, [FromHeader] LocationHeader header)
        {
            model = (AppointmentSupportLogModel)EmptyFilter.Handler(model);
            model.LocationId = Convert.ToInt32(header.LocationId);
            var res = await this.appointmentsServices.AssignAppointmentToSupport(model);
            var auditLogModel = new AuditLogModel
            {
                AccountId = model.modifiedBy,
                LogTypeId = (int)LogTypes.AppointmentLogs,
                LogFrom = (int)AccountType.Administrator,
                LogDate = DateTime.UtcNow,
                LogDescription = $"{model.AssigneeName} has been assigned successfully.",
                LocationId = model.LocationId
            };
            await this.auditLogServices.LogAsync(auditLogModel);

            return this.Success(res);
        }

        /// <summary>
        /// The fetch appointment log count async.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpGet]
        [Authorize]
        [Route("fetch-log-count")]
        public async Task<ActionResult> FetchAppointmentLogCountAsync()
        {
            var response = await this.appointmentsServices.FetchAppointmentLogCount();
            return this.Success(response);
        }

        /// <summary>
        /// To fetch list of patients.
        /// </summary>
        /// <param name="searchParam">
        /// The search parameter.
        /// </param>
        /// <param name="providerId">
        /// The provider Id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of patients.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-patients")]
        [ProducesResponseType(200, Type = typeof(List<PatientModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchPatientsAsync([FromBody] PatientModel model)
        {

            var existingPatients = await this.patientServices.FetchPatientsAsync(model);

            foreach (var item in existingPatients.ToList())
            {
                item.EncryptedPatientId = this.aesHelper.Encode(item.PatientId.ToString());

                if (!string.IsNullOrEmpty(item.PatientThumbnailUrl))
                {
                    item.PatientThumbnailUrl = this.amazonS3Configuration.BucketURL + item.PatientThumbnailUrl;
                }

                if (!string.IsNullOrEmpty(item.ProviderThumbnailUrl))
                {
                    item.ProviderThumbnailUrl = this.amazonS3Configuration.BucketURL + item.ProviderThumbnailUrl;
                }
            }

            return this.Success(existingPatients);

        }

        /// <summary>
        /// To fetch list of patients.
        /// </summary>
        /// <param name="model">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of patients.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch-doctor-specialization")]
        [ProducesResponseType(200, Type = typeof(List<ProviderSpecializationModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchDoctorSpecializationAsync([FromBody] ProviderSpecializationModel model)
        {
            model = (ProviderSpecializationModel)EmptyFilter.Handler(model);
            //model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var existingPatients = await this.providerService.FetchDoctorSpecializationAsync(model);
            return this.Success(existingPatients);
        }

        /// <summary>
        /// The fetch salucro pending transactions async.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [AllowAnonymous]
        [Route("status-check")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchSalucroPendingTransactionsAsync()
        {
            var transactions = await this.appointmentsServices.FetchPendingSalucroTransactions();
            foreach (var item in transactions)
            {
                //status check progress update
                await this.appointmentsServices.UpdateSalucroStatusCheckProgress(item.AppointmentId, true);

                var hashString = item.TransactionId + "|" + this.salucroConfiguration.MId + "|" + this.salucroConfiguration.User + "|" + this.salucroConfiguration.Key + "|" + this.salucroConfiguration.SecretKey;
                var check_sum_hash = Convert.ToBase64String(HttpUtility.UrlEncodeToBytes(Encoding.ASCII.GetBytes(PaymentHelper.GenerateCheckSumHash(hashString))));
                var salucroResponse = await this.salucroHelper.StatusCheckAsync(item.TransactionId, check_sum_hash);

                //status check progress update
                if (salucroResponse.StatusCode.ToString().ToLower().Equals("ok"))
                {
                    await this.appointmentsServices.UpdateSalucroStatusCheckProgress(item.AppointmentId, false);
                }

                dynamic result = JsonConvert.DeserializeObject(salucroResponse.Content);

                if (result.status_code == 1200)
                {
                    var res = await this.appointmentsServices.UpadateSalucroPaymentStatusAsync(item.AppointmentId);
                    if (res != 1)
                    {
                        return this.ServerError();
                    }
                }
            }
            return this.Success("Status Check Completed");
        }


        /// <summary>
        /// The fetch all async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>       
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Route("fetch-for-invoice")]
        [ProducesResponseType(typeof(List<AppointmentModel>), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchForInvoice([FromBody] AppointmentFilterModel model)
        {
            // model = (AppointmentFilterModel)EmptyFilter.Handler(model);        
            if (!string.IsNullOrEmpty(model.EncryptedAppointmentId))
            {
                model.AppointmentId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedAppointmentId));
            }
            var appointments = await this.appointmentsServices.FetchForInvoiceAsync((int)model.AppointmentId, model.Status);
            if (appointments != null)
            {

                //  if (item.AppointmentTime!=)
                DateTime d1 = DateTime.Today + appointments.AppointmentTime;
                appointments.AppointmentTimeString = d1.ToString("hh:mm tt");
                //item.TotAmt = Int64.Parse(item.TotalAmount);
                // int t = Convert.ToInt32(item.TotalAmount.ToString());

            }
            return this.Success(appointments);

        }

        /// <summary>
        /// The fetch all async.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>       
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        [HttpPost]
        [Authorize]
        [Route("appointment-cancel-amount-refunding")]
        [ProducesResponseType(typeof(List<AppointmentModel>), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> RefundAppointmentAmount([FromBody] AppointmentModel model)
        {
            var response = await this.appointmentsServices.RefundAppointmentCancelAmountAsync(model);

            if (response > 0)
            {
                model.Status = "Cancel";
                var appointmentCancelReceipt = await this.appointmentsServices.FetchForInvoiceAsync((int)model.AppointmentId, model.Status);
                return this.Success(appointmentCancelReceipt);
            }
            return this.Success();
        }

        /// <summary>
        /// The book appointment.
        /// </summary>
        /// <param name="request"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("initiate-payment")]
        [Consumes("multipart/form-data")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> InitiatePaymentAsync([FromForm] PaymentRequest request)
        {
            dynamic json = JsonConvert.DeserializeObject(request.Json);

            //var quickScheduleRequest = new QuickScheduleRequest
            //{
            //    PatientId = json["patientId"],
            //    ProviderId = json["providerId"],
            //    AppointmentDate = json["appointmentDate"],
            //    AppointmentId = json["appointmentId"]
            //};
            //var checkSameDateAptWithSameDoc = await this.CheckSameDateAppointmentWithSameDoctorAsync(quickScheduleRequest);
            //if (checkSameDateAptWithSameDoc.Status == GenericStatus.Warning)
            //{
            //    return this.Success(checkSameDateAptWithSameDoc);
            //}

            int createdBy = json["createdBy"];
            short logFrom = json["logFrom"];
            int locationId = json["locationId"];

            var paymentInitiationLogModel = new PaymentInitiationLogModel
            {
                TableData = request.Json,
                PaymentModuleId = (int)request.Type,
                Mode = request.Mode,
                CreatedBy = createdBy
            };
            var paymentInitiationLogId = await this.paymentInitiationLogService.AddAsync(paymentInitiationLogModel);
            var listFiles = new List<String>();
            if (paymentInitiationLogId > 0)
            {
                var files = this.Request.Form.Files;
                if (files.Count > 0)
                {
                    string documentType = json["documentType"];
                    string documentName = json["documentName"];
                    var index = 0;
                    foreach (var file in files)
                    {
                        var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/Temp/{paymentInitiationLogId}/{documentType}";

                        try
                        {
                            await this.ftpUploadHelper.CreateDirectory(filePath);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.Message);
                        }
                        documentName = index == 0 ? documentName : $"{documentName}_{index}";
                        var contentType = "";
                        switch (file.ContentType)
                        {
                            case "image/jpeg":
                                contentType = "imeg";
                                break;
                            case "image/pjpeg":
                                contentType = "impeg";
                                break;
                            case "image/png":
                                contentType = "imng";
                                break;
                            case "image/gif":
                                contentType = "imif";
                                break;
                            case "application/pdf":
                                contentType = "apdf";
                                break;
                            default:
                                contentType = file.ContentType;
                                break;
                        }
                        var dbPath = $@"{documentName}_{file.Length}_{contentType}_{DateTime.UtcNow.Ticks}{Path.GetExtension(file.FileName)}";
                        filePath += $@"/{dbPath}";

                        var uploadResponse = await this.ftpUploadHelper.UploadFromFileAsync(filePath, file);
                        if (uploadResponse <= 0)
                        {
                            return this.Success(new GenericResponse
                            {
                                Status = GenericStatus.Error,
                                Data = "Unable to upload to FTP"
                            });
                        }

                        listFiles.Add(filePath);
                        index++;
                    }
                    json.Add("paths", string.Join("$$", listFiles));
                    var finalJson = JsonConvert.SerializeObject(json);
                    var res = await this.unitOfWork.PaymentInitiationLog.FindAsync(m => m.PaymentInitiationLogId == paymentInitiationLogId);
                    res.TableData = finalJson;
                    await this.unitOfWork.PaymentInitiationLog.UpdateAsync(res);
                }

                var auditLogModel = new AuditLogModel
                {
                    AccountId = createdBy,
                    LogTypeId = (int)LogTypes.PaymentInitiationLog,
                    LogFrom = logFrom,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription = $@"Payment Initiation Log Added for module '{request.Type} {request.Mode}'",
                    LocationId = locationId
                };
                await this.auditLogServices.LogAsync(auditLogModel);

                if (request.Type.ToString() == "ScanAppointment")
                {
                    var scanLogModel = new ScanLogModel
                    {
                        AccountId = createdBy,
                        ScanLogTypeId = (int)ScanLogTypes.PaymentInitiationLog,
                        LogFrom = logFrom,
                        LogDate = DateTime.UtcNow.AddMinutes(330),
                        LocationId = locationId,
                        LogDescription = $" Payment Initiation Log Added for module <b>{request.Type} {request.Mode}</b> for the patient: <b>{json.FullNameForLog}</b>",
                    };
                    await this.scanLogService.LogAsync(scanLogModel);
                }
            }

            if (request.IsMobile == true)
            {
                var transactionId = await this.appointmentTransactionService.GetATransactionId();
                var hashString = this.salucroConfiguration.User + "|" + this.salucroConfiguration.Key + "|" + transactionId + "|" + this.salucroConfiguration.MId + "|" + this.salucroConfiguration.SecretKey;

                var hashValue = Convert.ToBase64String(HttpUtility.UrlEncodeToBytes(Encoding.ASCII.GetBytes(PaymentHelper.GenerateCheckSumHash(hashString))));
                var paymentDetails = new PaymentDetailsModel();
                paymentDetails.Hashvalue = hashValue;
                paymentDetails.TransactionId = transactionId;
                paymentDetails.SuccessLink = this.salucroConfiguration.ResponseURL;
                paymentDetails.FailureLink = this.salucroConfiguration.MobileReturnURL;
                paymentDetails.ProductInfo = "";
                paymentDetails.AppointmentLogId = paymentInitiationLogId;
                return this.Success(JsonConvert.SerializeObject(paymentDetails));
            }
            else if (request.IsWebPatient == true)
            {
                return this.Success(new GenericResponse
                {
                    Status = GenericStatus.Success,
                    Data = this.applicationConfiguration.SalucroPatientPaymentLink + "?id=" + this.aesHelper.Encode(paymentInitiationLogId.ToString())
                });
            }
            return this.Success(new GenericResponse
            {
                Status = GenericStatus.Success,
                Data = this.applicationConfiguration.SalucroPaymentLink + "?id=" + this.aesHelper.Encode(paymentInitiationLogId.ToString()) + "&mode=" + request.Mode
            });
        }

        /// <summary>
        /// The find the patient appointment with date.
        /// </summary>
        /// <param name="model"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment added successfully.
        /// - 409 - Appointment already exist.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("find-patient-appointmentDate")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FindPatientAppointmentDateAsync([FromBody] PatientAppointmentFilterModel model)
        {
            model = (PatientAppointmentFilterModel)EmptyFilter.Handler(model);
            var appointment = await this.appointmentsServices.FindPatientAppointmentAsync(model);
            if (appointment != null)
            {
                foreach (var item in appointment)
                {
                    item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
                }
            }
            return this.Success(appointment);
        }


        /// <summary>
        /// To fetch list of patients.
        /// </summary>
        /// <param name="model">
        /// The patient model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of patients.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("fetch-doctor-specialization-op")]
        [ProducesResponseType(200, Type = typeof(List<ProviderSpecializationModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchDoctorSpecializationOpAsync([FromBody] ProviderSpecializationModel model)
        {
            model = (ProviderSpecializationModel)EmptyFilter.Handler(model);
            //model.LocationId = !string.IsNullOrEmpty(location.LocationId) ? int.Parse(location.LocationId) : (int?)null;
            var existingPatients = await this.providerService.FetchDoctorSpecializationOpAsync(model);

            return this.Success(existingPatients);
        }


        /// <summary>
        /// To fetch list of patients.
        /// </summary>
        /// <param name="searchParam">
        /// The search parameter.
        /// </param>
        /// <param name="providerId">
        /// The provider Id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Returns list of patients.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [AllowAnonymous]
        [Route("fetch-appointment-schedule-patients")]
        [ProducesResponseType(200, Type = typeof(List<PatientModel>))]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchAppointmentSchedulePatientsAsync([FromBody] PatientModel model)
        {
            if (!string.IsNullOrEmpty(model.EncryptedAppointmentId))
            {
                model.AppointmentId = Convert.ToInt32(this.aesHelper.Decode(model.EncryptedAppointmentId));
            }

            var existingPatients = await this.patientServices.FetchAppointmentSchedulePatientsAsync(model);

            if (existingPatients.ToList().Count > 0)
            {

                foreach (var item in existingPatients.ToList())
                {

                    if (item.PatientId > 0)
                    {
                        if (item.ReferredByNameId != null && item.ReferredByName == null)
                        {
                            var referredByType = await this.unitOfWork.ReferenceTypes.FindAsync(x => x.PatientReferredById == item.PatientReferredById);
                            if (referredByType.Name == "Referral")
                            {
                                var referredByDetails = await this.unitOfWork.ReferralDoctor.FindAsync(x => x.ReferralDoctorId == item.ReferredByNameId);
                                item.ReferredByName = referredByDetails.FullName;
                            }
                            else
                            {
                                var referredByDetails = await this.unitOfWork.Providers.FindAsync(x => x.ProviderId == item.ReferredByNameId);
                                item.ReferredByName = referredByDetails.FullName;
                            }
                        }
                    }

                    if (item.PatientId > 0)
                    {
                        item.EncryptedPatientId = this.aesHelper.Encode(item.PatientId.ToString());
                    }
                    if (item.AppointmentTime != null)
                    {
                        item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
                    }

                }
            }

            if (!string.IsNullOrEmpty(model.EncryptedAppointmentId) && existingPatients.ToList().Count > 0 && existingPatients.ToList()[0].PatientId > 0)
            {

                var patientProfile = new PatientProfileModel
                {
                    Patient = existingPatients.ToList()[0],
                    Insurances = await this.patientInsuranceServices.FetchAsync(existingPatients.ToList()[0].PatientId),
                    EmergencyContacts = await this.patientEmergencyServices.FetchAsync(existingPatients.ToList()[0].PatientId),
                    RelativeDetails = await this.patientServices.FetchPatientFamilyAsync(existingPatients.ToList()[0].PatientId)
                };
                return this.Success(patientProfile);
            }

            return this.Success(existingPatients);

        }

        [HttpGet]
        [Authorize]
        [Route("get-payment-data")]
        public async Task<ActionResult> FetchPaymentInitiationData(string id, int appointmentId, int type)
        {
            return Success(await this.FetchPaymentInitiationHelper(id, appointmentId, type));
        }

        [NonAction]
        private async Task<object> FetchPaymentInitiationHelper(string id, int appointmentId, int type)
        {
            if (!string.IsNullOrEmpty(id))
            {
                var logId = Convert.ToInt32(this.aesHelper.Decode(id));
                var data = await this.unitOfWork.PaymentInitiationLog.FindAsync(x => x.PaymentInitiationLogId == logId);
                var otherTransactions = await this.appointmentsServices.FetchTransactionDataAsync(logId);
                return new
                {
                    tableData = data.TableData,
                    otherTransactions
                };
            }
            else
            {
                var otherTransactions = await this.appointmentsServices.FetchTransactionAsync(appointmentId, type);
                dynamic data = "";
                switch (type)
                {
                    case 2:
                        data = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == appointmentId);
                        data.Total = data.Amount - data.Discount;
                        break;
                    case 3:
                        data = await this.unitOfWork.PharmacySaleHeaders.FindAsync(x => x.PharmacySaleHeaderId == appointmentId);
                        var pharmaBill = await this.unitOfWork.MasterBill.FindAsync(x => x.ModuleId == appointmentId && x.ReceiptAreaTypeId == 1);
                        data.OverallNetAmount = data.OverallNetAmount - pharmaBill.RemovedAmount;
                        break;
                    case 4:
                        data = await this.unitOfWork.NewLabBookingHeaders.FindAsync(x => x.NewLabBookingHeaderId == appointmentId);
                        var labBill = await this.unitOfWork.MasterBill.FindAsync(x => x.ModuleId == appointmentId && x.ReceiptAreaTypeId == 8);
                        data.OverallNetAmount = data.OverallNetAmount - labBill.RemovedAmount;
                        break;
                    case 9:
                    case 5:
                        data = await this.unitOfWork.BookScanAppointments.FindAsync(x => x.BookScanAppointmentId == appointmentId);
                        break;
                    case 8:
                        data = await this.admissionsServices.FindFinalBillAsync(appointmentId);
                        break;
                }

                var jsonSerializerSettings = new JsonSerializerSettings
                {
                    ContractResolver = new CamelCasePropertyNamesContractResolver()
                };

                return new
                {
                    tableData = JsonConvert.SerializeObject(data, jsonSerializerSettings),
                    otherTransactions
                };
            }

        }

        [HttpPost]
        [Authorize]
        [Route("update-partial-payment")]
        [Consumes("multipart/form-data")]
        public async Task<ActionResult> UpdatePartialPayment([FromForm] AppointmentModel request)
        {
            request = (AppointmentModel)EmptyFilter.Handler(request);
            var result = await this.appointmentsServices.CompletePartialPaymentAsync(request);
            var patient = await this.unitOfWork.Patients.FindAsync(x => x.PatientId == request.PatientId);
            var auditLogModel = new AuditLogModel
            {
                FullName = request.PatientName,
                AccountId = request.CreatedBy,
                LogTypeId = (int)LogTypes.Payment,
                LogFrom = request.LogFrom,
                LogDate = DateTime.UtcNow,
                LogDescription = $"Patient: <b>{patient.FullName}</b> has paid - <b>{request.TotalAmount}</b> rupees  on {DateTime.UtcNow.AddMinutes(330)} Successfully",
                LocationId = Convert.ToInt32(request.LocationId)
            };
            await this.auditLogServices.LogAsync(auditLogModel);
            return this.Success(new GenericResponse
            {
                Status = GenericStatus.Success,
                Data = result
            });
        }


        /// <summary>
        /// The fetch coupons.
        /// </summary>
        /// <param name="model">
        /// The coupon filter model.
        /// </param>
        /// <param name="filter"></param>
        /// <returns>
        /// The list of coupons.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of coupons.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Route("fetch-view")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(409)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> FetchViewAsync([FromBody] AppointmentFilterModel model)
        {
            try
            {
                model = (AppointmentFilterModel)EmptyFilter.Handler(model);
                var providerScheduleEvent = await this.appointmentsServices.FetchViewAsync(model);

                foreach (var item in providerScheduleEvent)
                {
                    item.AppointmentTimeString = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(item.AppointmentTime).ToString("hh:mm tt");
                }

                return this.Success(providerScheduleEvent);
            }
            catch (Exception ex)
            {
                _ = ex.Message.ToString();
            }
            return default;
        }

        /// <summary>
        /// The cancel of appointments.
        /// </summary>
        /// <param name="appointmentIds"></param>
        /// <param name="reason"></param>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - List of coupons.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpGet]
        [AllowAnonymous]
        [Route("cancel-all")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> CancelAllAsync(string appointmentIds, string reason)
        {
            try
            {
                // model = (AppointmentFilterModel)EmptyFilter.Handler(appointmentIds);
                var cancelAllResponse = await this.appointmentsServices.CancelAllAsync(appointmentIds, reason);
                return this.Success(cancelAllResponse);
            }
            catch (Exception ex)
            {
                _ = ex.Message.ToString();
            }
            return default;
        }


        /// <summary>
        /// The reschedule appointment.
        /// </summary>
        /// <param name="model">
        /// The model.
        /// </param>
        /// <param name="header"></param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        /// <remarks>
        /// ### REMARKS ###
        /// The following codes are returned
        /// - 200 - Appointment rescheduled successfully.
        /// - 500 - Problem with Server side code.
        /// </remarks>
        [HttpPost]
        [Authorize]
        [Route("reschedule-all")]
        [ProducesResponseType(typeof(string), 200)]
        [ProducesResponseType(500)]
        public async Task<ActionResult> RescheduleAllAppointmentAsync([FromBody] RescheduleAppointmentRequest model)
        {
            model = (RescheduleAppointmentRequest)EmptyFilter.Handler(model);
            var appointmentTime = TimeSpan.Parse(model.AppointmentTime);
            var appointmentEndTime = TimeSpan.Parse(model.AppointmentEndTime);
            var tokenNumber = model.TokenNumber == 0 ? 0 : model.TokenNumber;
            //var response = await this.appointmentsServices.RescheduleAsync(model.AppointmentId, model.AppointmentDate, appointmentTime, model.AppointmentNotes, Convert.ToInt32(model.ModifiedBy), model.ProviderId, model.ProviderLocationId, model.DepartmentId, model.LocationId, model.TokenNumber, model.SpecializationId);

            var response = await this.appointmentsServices.RescheduleAllAsync(model.AppointmentIds, model.AppointmentDate, appointmentTime, appointmentEndTime, model.AppointmentNotes, Convert.ToInt32(model.ModifiedBy), model.ProviderId, model.ProviderAvailabilityId, model.ConsultationTypeId, model.DepartmentId, model.LocationId, model.TokenNumbers, model.SpecializationId, model.AppointmentTimings, model.AppointmentEndTimings, model.VisitTypeId, model.ChargeTypesId, model.Amount, model.Total, model.Discount);
            if (response == 0)
            {
                return this.ServerError();
            }
            try
            {
                var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);


                //var appointment = await this.appointmentsServices.FindAsync(model.AppointmentId);
                var appointmentHangfireMapModel = new AppointmentHangfireMapModel()
                {
                    AppointmentId = model.AppointmentId,
                    AppointmentDate = model.AppointmentDate,
                    AppointmentTime = appointmentTime,
                    Status = "R",
                };
                var aHMapId = 0;

                aHMapId = await this.appointmentsServices.AddAppointmentHangfireAsync(appointmentHangfireMapModel);

                if (appointment != null)
                {
                    var timespan = new TimeSpan(appointment.AppointmentTime.Hours, appointment.AppointmentTime.Minutes, appointment.AppointmentTime.Seconds);
                    var time = DateTime.Today.Add(timespan);
                    var displayTime = time.ToString("hh:mm tt");
                    var messageType = "has been rescheduled successfully";
                    // Sending Message
                    await this.smsSender.SendAppointmentMessageAsync(appointment, messageType, displayTime);
                    var WhatsAppMessageSetting = await this.settingService.FetchAsync("WhatsAppMsgService", null, null);
                    var WhatsAppMessage = WhatsAppMessageSetting.ToList();
                    if ((bool)WhatsAppMessage[0].Active)
                    {
                        var LocationQuery = $@"select l.""LocationId"",l.""Name"",l.""PracticeId"",p.""FullName"" as ""PracticeName"" from ""Location"" l
                           join ""Practice"" p on p.""PracticeId"" = l.""PracticeId"" where ""LocationId"" = {appointment.LocationId} limit 1";

                        var Location = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LocationModel>(LocationQuery);
                        bool ret = await this.whatsAppSMSSender.SendWhatsAppMessageAsync(appointment, displayTime, messageType, Location.Name);
                    }
                    //email and Message.
                    BackgroundJob.Enqueue(() => this.AppointmentActions(appointment, "ReSchedule", true));


                }
                var auditLogModel = new AuditLogModel
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow.AddMinutes(330),
                    LogDescription = $@"Patient: <b>{appointment?.PatientName}</b>, Appointment on <b>{appointment?.AppointmentDate.ToString("MM/dd/yyyy")} {appointment?.AppointmentDate.Add(appointment.AppointmentTime).ToString("hh:mm tt")}</b><br>
                has been <b>Reschedule</b> with Doctor: <b>Dr.{appointment?.ProviderName}.</b>",
                    LocationId = model.LocationId
                };

                await this.auditLogServices.LogAsync(auditLogModel);
            }
            catch (Exception e)
            {
                e.Message.ToString();
            }
            return this.Success("Appointment has been Rescheduled successfully.");
        }
    }
}