using Hims.Domain.Entities.Enums;

namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;

    using Dapper;
    using Domain.Helpers;
    using Domain.Configurations;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Newtonsoft.Json.Linq;
    using Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.Library.Enums;
    using Shared.UserModels.Filters;
    using Hims.Shared.UserModels;
    using System.Transactions;
    using Newtonsoft.Json;
    using System.Data.Common;
    using System.Security.Cryptography;
    using System.Security.Cryptography.X509Certificates;
    using Hims.Shared.UserModels.WebNotification;
    using System.Text.RegularExpressions;
    using System.Collections;

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

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

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

        /// <summary>
        /// the wallet service
        /// </summary>
        private readonly IWalletService walletServices;

        /// <summary>
        /// The appointment transaction services.
        /// </summary>
        private readonly IAppointmentTransactionService appointmentTransactionsServices;

        /// <summary>
        /// The patient services.
        /// </summary>
        private readonly IPatientService patientService;

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

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

        public object PaymentType { get; private set; }

        /// <inheritdoc cref="IAppointmentService" />
        public AppointmentServices(IUnitOfWork unitOfWork, IWebNotificationService webNotificationService, IAmazonS3Configuration amazonS3Configuration, IDocumentHelper documentHelper, IWalletService walletServices, IAppointmentTransactionService appointmentTransactionsServices, IPatientService patientService, IAuditLogService auditLogServices, IRunningEnvironment runningEnvironment)
        {
            this.unitOfWork = unitOfWork;
            this.webNotificationService = webNotificationService;
            this.amazonS3Configuration = amazonS3Configuration;
            this.walletServices = walletServices;
            this.appointmentTransactionsServices = appointmentTransactionsServices;
            this.patientService = patientService;
            this.auditLogServices = auditLogServices;
            this.runningEnvironment = runningEnvironment;
        }

        public async Task<Appointment> GetRawAsync(int id)
        {
            return await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == id);
        }

        public async Task<int> GetLatestIdAsync(int id)
        {
            var query = $@"SELECT ""AppointmentId"" from ""Appointment"" WHERE ""PatientId"" = {id} AND ""Active"" IS TRUE ORDER BY 1 DESC LIMIT 1";
            return await this.unitOfWork.Current.QuerySingleAsync<int>(query);
        }

        public async Task<int> GetAppointmentCountForTodayAsync(int id)
        {
            var query = $@"SELECT  COUNT(""AppointmentId"") from ""Appointment"" WHERE ""PatientId"" = {id} AND ""Active"" IS TRUE AND ""AppointmentDate""::date=CURRENT_DATE ";
            return await this.unitOfWork.Current.QuerySingleAsync<int>(query);
        }

        /// <inheritdoc />
        public async Task<AppointmentModel> FindByAppointmentNoAsync(string appointmentNo)
        {
            try
            {
                var record = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentNo == appointmentNo);
                return new AppointmentModel
                {
                    AppointmentId = record.AppointmentId,
                    PatientId = record.PatientId
                };
            }
            catch
            {
                return null;
            }
        }

        ///// <inheritdoc />
        //public async Task<AppointmentModel> FindAsync(int appointmentId)
        //{
        //    var query = $@"SELECT apt.*, apt.""AppointmentTime"", enc.""EncounterId"", pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"", cunpra.""CurrencySymbol"",
        //                         (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
        //                        pr.""Email"" as ""ProviderEmail"", pr.""Mobile"" as ""ProviderMobile"",
        //                        pr.""EnableEmailAlerts"", pr.""EnableSMSAlerts"", pr.""EnableDesktopNotifications"",pr.""EnableMobileNotifications"" ,
        //                        pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"",
        //                        pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",pat.""UMRNo"",
        //                        cunpra.""CountryId"" AS ""ProviderCountryId"", cunpra.""CountryCode"" AS ""ProviderCountryCode"",
        //                        CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"",
        //                        CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
        //                        WHEN apt.""EncounterType"" in ('{EncounterTypes.Encounter}', '{EncounterTypes.InternalMedicine}') AND enc.""Medications"" IS NOT NULL THEN TRUE
        //                        WHEN apt.""EncounterType"" in ('{EncounterTypes.BehavioralHealth}') AND bh.""Medications"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsPrescription"",
        //                        pra.""FullName"" AS ""PracticeName"", CONCAT(pral.""Name"", ', ', cunpra.""CountryName"") AS ""ProviderLocation"",
        //                        (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"", apt.""EncounterType""
        //                        FROM ""Appointment"" apt
        //                        JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
        //                        LEFT JOIN ""PatientFamily"" PF on PF.""PatientFamilyId"" = apt.""PatientFamilyId""
        //                        LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
        //                        LEFT JOIN ""Encounter"" enc ON enc.""AppointmentId"" = apt.""AppointmentId"" AND enc.""Active"" IS TRUE
        //                        LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
        //                        JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE
        //                        left JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
        //                        JOIN ""Location"" pral ON pral.""LocationId"" = prl.""LocationId"" AND pral.""Active"" IS TRUE
        //                        left JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND  prl.""ProviderId""=apt.""ProviderId"" AND cunpra.""Active"" IS TRUE
        //                        JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
        //                        WHERE apt.""AppointmentId""= {appointmentId}";
        //    return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentModel>(query);
        //}



        /// <inheritdoc />
        public async Task<AppointmentModel> FindAsync(int appointmentId)
        {
            var query = $@"SELECT apt.*, apt.""AppointmentTime"", enc.""EncounterId"", pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"", cunpra.""CurrencySymbol"",
                                             (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
                                            pr.""Email"" as ""ProviderEmail"", pr.""Mobile"" as ""ProviderMobile"",
                                            pr.""EnableEmailAlerts"", pr.""EnableSMSAlerts"", pr.""EnableDesktopNotifications"",pr.""EnableMobileNotifications"" ,
                                            pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"",
                                            pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",pat.""UMRNo"",
                                            cunpra.""CountryId"" AS ""ProviderCountryId"", cunpra.""CountryCode"" AS ""ProviderCountryCode"",
                                            CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"",
                                            CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
                                            WHEN apt.""EncounterType"" in ('Encounter', 'InternalMedicine') AND enc.""Medications"" IS NOT NULL THEN TRUE
                                            WHEN apt.""EncounterType"" in ('BehavioralHealth') AND bh.""Medications"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsPrescription"",
                                            --pra.""FullName"" AS ""PracticeName"", CONCAT(pral.""Name"", ', ', cunpra.""CountryName"") AS ""ProviderLocation"",
                                            (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('https://hims-qa.s3.amazonaws.com/', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"", apt.""EncounterType""
                                            FROM ""Appointment"" apt
                                            JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                            LEFT JOIN ""PatientFamily"" PF on PF.""PatientFamilyId"" = apt.""PatientFamilyId""
                                            LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                            LEFT JOIN ""Encounter"" enc ON enc.""AppointmentId"" = apt.""AppointmentId"" AND enc.""Active"" IS TRUE
                                            LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
                                            JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE
								                                            left join ""ProviderAvailability"" PA on PA.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND PA.""Active"" IS TRUE
								                                           LEFT JOIN ""Location"" PAL ON PAL.""LocationId"" = PA.""LocationId"" AND PAL.""Active"" IS TRUE
								                                            left JOIN ""Country"" cunpra ON cunpra.""CountryId"" = PAL.""CountryId"" AND PA.""ProviderId""=apt.""ProviderId"" AND cunpra.""Active"" IS TRUE
                                            --left JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
                                            --JOIN ""Location"" pral ON pral.""LocationId"" = prl.""LocationId"" AND pral.""Active"" IS TRUE
                                            --left JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND prl.""ProviderId""=apt.""ProviderId"" AND cunpra.""Active"" IS TRUE
                                            --JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
                                WHERE apt.""AppointmentId""= {appointmentId}";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentModel>(query);
        }


        /// <inheritdoc />
        public Task<IEnumerable<AppointmentModel>> FindByDateAsync(string appointmentDate)
        {
            var query = $@"SELECT apt.*, apt.""AppointmentTime"", enc.""EncounterId"", pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender""
                                --, cunpra.""CurrencySymbol"",
                                pat.""FullName"" AS ""PatientName"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"", pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"",
                                pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",
                                --pra.""FullName"" AS ""PracticeName""
                                --, CONCAT(pral.""City"", ', ', pral.""State"", ', ', cunpra.""CountryName"", ' - ', pral.""Zipcode"") AS ""ProviderLocation"",
                                (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"",apt.""EncounterType""
                                FROM ""Appointment"" apt
                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE
                                --JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
                                JOIN ""ProviderAvailability"" prl ON prl.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND prl.""Active"" IS TRUE
                                --JOIN ""PracticeLocation"" pral ON pral.""PracticeLocationId"" = prl.""PracticeLocationId"" AND pral.""Active"" IS TRUE
                                --JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND cunpra.""Active"" IS TRUE
                                --JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
                                LEFT JOIN ""Encounter"" enc ON enc.""AppointmentId"" = apt.""AppointmentId"" AND enc.""Active"" IS TRUE
                                WHERE apt.""AppointmentDate"" :: date = '{appointmentDate}'";
            return this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
        }

        /// <inheritdoc />
        public async Task<AppointmentDashboardModel> FindAppointmentAsync(int appointmentId, bool isAdmission)
        {
            var query = !isAdmission
                    ? $@"SELECT apt.""AppointmentId"", apt.""AppointmentNo"", apt.""AppointmentDate"", apt.""AppointmentTime"", apt.""ConsultationTypeId"",apt.""SpecializationId"", apt.""ProviderAvailabilityId"", enc.""EncounterId"",
                                (case when apt.""PatientFamilyId"" is not null then null else pat.""DateOfBirth"" end) AS ""PatientDateOfBirth"",
                                acc.""AccountId"" as ""PatientAccountId"",
                                (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"", pat.""UMRNo"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
                                (case when apt.""PatientFamilyId"" is not null then PF.""Gender"" else pat.""Gender"" end) AS ""PatientGender"",
                                (case when apt.""PatientFamilyId"" is not null then PF.""Age"" else pat.""Age"" end) AS ""PatientAge"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
                                WHEN apt.""EncounterType"" in ('Encounter', 'InternalMedicine') AND enc.""Medications"" IS NOT NULL THEN TRUE
                                WHEN apt.""EncounterType"" in ('BehavioralHealth') AND bh.""Medications"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsPrescription"",
                                cun.""CountryCode"" AS ""PatientCountryCode"",pat.""PatientId"",pat.""MaritalStatus"" AS ""PatientMaritalStatus"",
                                (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('Local', '/', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",apt.""EncounterType"",
                                apt.""ProviderId"",apt.""ProviderLocationId"",
                                pr.""FullName"" as ""ProviderName"", pr.""Email"" as ""ProviderEmail"",
                                qs.""Name"" ""QueueStatus""
                                FROM ""Appointment"" apt
                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                LEFT JOIN ""QueueStatus"" qs on qs.""QueueStatusId"" = apt.""QueueStatusId""
                                Left join ""PatientFamily"" PF on PF.""PatientId"" = pat.""PatientId""
                                LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                LEFT JOIN ""Encounter"" enc ON enc.""AppointmentId"" = apt.""AppointmentId"" AND enc.""Active"" IS TRUE
                                LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
                                LEFT JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId"" AND acc.""RoleId""=4 AND acc.""Active"" IS TRUE
								left join ""Provider"" pr on pr.""ProviderId""=apt.""ProviderId""
                                WHERE apt.""AppointmentId""= {appointmentId}"

            : $@"SELECT
	                    apt.""AdmissionId"" ""AppointmentId"",
	                    apt.""AdmissionNo"" ""AppointmentNo"",
	                    apt.""AdmissionDate"" ""AppointmentDate"",
	                    apt.""AdmissionTime"" ""AdmissionTime"",
	                    enc.""EncounterId"",R.""RoomName"",
	                    ( CASE WHEN apt.""PatientFamilyId"" IS NOT NULL THEN NULL ELSE pat.""DateOfBirth"" END ) AS ""PatientDateOfBirth"",
	                    acc.""AccountId"" AS ""PatientAccountId"",
	                    ( CASE WHEN apt.""PatientFamilyId"" IS NOT NULL THEN PF.""FullName"" ELSE pat.""FullName"" END ) AS ""PatientName"",pat.""UMRNo"",pr.""FullName"" as ""ProviderName"",pr.""ProviderId"",

                        pat.""Email"" AS ""PatientEmail"",
	                    pat.""Mobile"" AS ""PatientMobile"",
	                    ( CASE WHEN apt.""PatientFamilyId"" IS NOT NULL THEN PF.""Gender"" ELSE pat.""Gender"" END ) AS ""PatientGender"",
	                    ( CASE WHEN apt.""PatientFamilyId"" IS NOT NULL THEN PF.""Age"" ELSE pat.""Age"" END ) AS ""PatientAge"",

			                    cun.""CountryCode"" AS ""PatientCountryCode"",
			                    pat.""PatientId"",
			                    pat.""MaritalStatus"" AS ""PatientMaritalStatus"",
                                (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",
			                    enc.""EncounterId"",
			                    CASE WHEN enc.""Medications"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsPrescription""
		                    FROM
			                    ""Admission"" apt
			                    JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId""
			                    AND pat.""Active""
			                    IS TRUE LEFT JOIN ""PatientFamily"" PF ON PF.""PatientId"" = pat.""PatientId""
			                    LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId""
			                    AND cun.""Active""
			                    IS TRUE LEFT JOIN ""Encounter"" enc ON enc.""AdmissionId"" = apt.""AdmissionId""
			                    AND enc.""Active"" IS TRUE
			                    IS TRUE JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId""
			                    AND acc.""RoleId"" = 4
			                    AND acc.""Active"" IS TRUE
                            left join ""Provider"" Pr on apt.""ProviderId""=Pr.""ProviderId""
                                left join ""Bed"" B on B.""BedId""=apt.""BedId""
	                            left join ""Room"" R on B.""RoomId""=R.""RoomId""
	                    WHERE
	                    apt.""AdmissionId"" = {appointmentId}";
            var record = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentDashboardModel>(query);
            if (isAdmission)
            {
                if (record != null)
                {
                    record.EncounterType = record.EncounterId > 0 ? "InternalMedicine" : null;
                    record.IsFullTranscript = record.EncounterId > 0;
                }
            }

            return record;
        }

        /// <inheritdoc />
        public Task<AppointmentSymptomModel> FetchAppointmentSymptomsAsync(int appointmentId, bool isAdmission)
        {
            var query = isAdmission
                ? $@"SELECT apts.* from ""AppointmentSymptom"" apts
                                WHERE apts.""AdmissionId""= {appointmentId}"
                : $@"SELECT apts.* from ""AppointmentSymptom"" apts
                                WHERE apts.""AppointmentId""= {appointmentId}";
            var result = this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentSymptomModel>(query);
            return result;
        }

        /// <inheritdoc />
        public Task<IEnumerable<AppointmentModel>> FetchAsync(AppointmentFilterModel model)
        {
            var where = $@" WHERE 1 = 1 ";

            if (model.VisitType != 0)
            {
                where += $@" AND A.""VisitType"" = '{model.VisitType}'";
            }
            if (model.VisitTypeId != 0)
            {
                where += $@" AND A.""VisitTypeId"" = {model.VisitTypeId}";
            }
            // if (!string.IsNullOrEmpty(model.FromDate))
            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND A.""AppointmentDate""::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND A.""AppointmentDate""::DATE <= '{model.ToDate}'::DATE";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND A.""AppointmentDate""::DATE >= '%{model.FromDate}%'";
            }

            if (!string.IsNullOrEmpty(model.AppointmentNo))
            {
                where += $@" AND A.""AppointmentNo"" ILIKE '%{model.AppointmentNo}%'";
            }

            if (!string.IsNullOrEmpty(model.Status))
            {
                where += $@" AND A.""Status"" = '{model.Status}'";
            }

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

            if (model.Gender != null)
            {
                where += $@" AND A.""PatientGender"" = '{model.Gender}'";
            }

            if (model.PatientId != null)
            {
                where += $@" AND A.""PatientId"" = {model.PatientId}";
            }

            if (model.CountryId != null)
            {
                where += $@" AND A.""PatientCountryId"" = {model.CountryId}";
            }

            if (model.Active != null)
            {
                where += $@" AND A.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            }

            if (model.Mobile != null)
            {
                where += $@" AND A.""PatientMobile"" ILIKE '%{model.Mobile}%'";
            }

            if (!string.IsNullOrEmpty(model.Column) && model.Sort != null)
            {
                if (model.Sort == true)
                {
                    where += $@" Order BY A.""{model.Column}"" ";
                }
                else
                {
                    where += $@" Order BY A.""{model.Column}"" DESC ";
                }
            }
            else
            {
                where += $@" Order BY A.""AppointmentDate"" DESC, A.""AppointmentTime"" DESC";
            }

            var query = $@"SELECT COUNT(A.*) OVER () AS ""TotalItems"", A.* ,

                                (
                                    SELECT
                                        c.""Status""
                                    FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
	                                WHERE h.""AppointmentId"" = A.""AppointmentId""
	                                ORDER BY ""TelemedicineCallHistoryId"" DESC LIMIT 1
                                ) AS ""VideoCallStatus"",

                                (
                                    SELECT
                                        u.""Status""
                                    FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
	                                LEFT JOIN ""TelemedicineUsersHistory"" u ON u.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
	                                LEFT JOIN ""Account"" aa ON aa.""AccountId"" = u.""AccountId""
	                                WHERE h.""AppointmentId"" = A.""AppointmentId"" AND aa.""RoleId"" = 4
	                                ORDER BY ""TelemedicineUsersHistoryId"" DESC LIMIT 1
                                ) AS ""PatientCallStatus"",

                                (
                                    SELECT
                                        u.""Status""
                                    FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
	                                LEFT JOIN ""TelemedicineUsersHistory"" u ON u.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
	                                WHERE h.""AppointmentId"" = A.""AppointmentId"" AND u.""AccountId"" = {model.AccountId}
	                                ORDER BY ""TelemedicineUsersHistoryId"" DESC LIMIT 1
                                ) AS ""CallStatus"",

                                (
                                    SELECT
                                        CONCAT('From ', aa.""FullName"", ' (', rr.""RoleName"", ')', ' At ', to_char(u.""Date""::date, 'DD Mon YYYY HH12:MI AM'))
                                    FROM
	                                ""TelemedicineCallHistory""
	                                C JOIN ""TelemedicineHistory"" h ON h.""TelemedicineHistoryId"" = C.""TelemedicineHistoryId""
	                                LEFT JOIN ""TelemedicineUsersHistory"" u ON u.""TelemedicineCallHistoryId"" = C.""TelemedicineCallHistoryId""
                                    LEFT JOIN ""Account"" aa on aa.""AccountId"" = u.""CallerId""
                                    LEFT JOIN ""Role"" rr on rr.""RoleId"" = aa.""RoleId""
	                                WHERE h.""AppointmentId"" = A.""AppointmentId"" AND u.""AccountId"" = {model.AccountId}
	                                ORDER BY ""TelemedicineUsersHistoryId"" DESC LIMIT 1
                                ) AS ""CallerName"",

                                TO_CHAR(A.""AppointmentDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(A.""AppointmentTime"", 'hh12:mi AM') ""AppointmentDateTime""  ,

                                CASE WHEN A.""OldAppointmentDate"" IS NOT NULL THEN TO_CHAR(A.""OldAppointmentDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(A.""OldAppointmentTime"", 'hh12:mi AM') ELSE '' END ""OldAppointmentDateTime""
                                FROM (SELECT acc.""AccountId"" as ""PatientAccountId"",prAcc.""AccountId"" as ""ProviderAccountId"", apt.*, pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"", pr.""Age"" AS ""ProviderAge""
                                --,cunpra.""CurrencySymbol""
                                , pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
                                WHEN apt.""EncounterType"" in ('{EncounterTypes.Encounter}', '{EncounterTypes.InternalMedicine}') AND e.""Medications"" IS NOT NULL THEN TRUE
                                WHEN apt.""EncounterType"" in ('{EncounterTypes.DentalEncounter}') AND de.""Medications"" IS NOT NULL THEN TRUE
                                WHEN apt.""EncounterType"" in ('{EncounterTypes.BehavioralHealth}') AND bh.""Medications"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsPrescription"",
                                (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"",
                                (case when apt.""PatientFamilyId"" is not null then PF.""Gender"" else pat.""Gender"" end) AS ""PatientGender"",
                                (case when apt.""PatientFamilyId"" is not null then PF.""Age"" else pat.""Age"" end) AS ""PatientAge"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile""
                                --,pra.""FullName"" AS ""PracticeName""
                                , pat.""Guid""::text AS ""PatientGuid"", pr.""Guid""::text AS ""ProviderGuid"",
                                (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"",
                                (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",apt.""EncounterType"",
                                count(distinct pd.""PatientDocumentId"")  as ""PatientDocumentCount"", message.""DoctorMessageCount"",message.""PatientMessageCount"",
								CASE WHEN acs.""AccountSessionId"" IS NULL THEN FALSE ELSE TRUE END AS ""IsOnline"" FROM ""Appointment"" apt
                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                Left join ""PatientFamily"" PF on PF.""PatientFamilyId"" = apt.""PatientFamilyId""
                                LEFT JOIN ""PatientDocument"" pd ON  pd.""PatientId""=pat.""PatientId"" AND pd.""Active"" IS TRUE
                                LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                LEFT JOIN ""Encounter"" e ON e.""AppointmentId"" = apt.""AppointmentId"" AND e.""Active"" IS TRUE
                                LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
                                LEFT JOIN ""DentalEncounter"" de ON de.""AppointmentId"" = apt.""AppointmentId"" AND de.""Active"" IS TRUE
                                left join ""Message"" message on message.""AppointmentId"" = apt.""AppointmentId""
                                JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE AND pr.""ApprovalStatus"" IS TRUE
                                --JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
                                --JOIN ""PracticeLocation"" pral ON pral.""PracticeLocationId"" = prl.""PracticeLocationId"" AND pral.""Active"" IS TRUE
                                --JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND cunpra.""Active"" IS TRUE
                                --JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
                                JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId"" AND acc.""RoleId""=4 AND acc.""Active"" IS TRUE
                                LEFT JOIN ""AccountSession"" acs ON acc.""AccountId"" = acs.""AccountId""
                                JOIN ""Account"" prAcc ON prAcc.""ReferenceId"" = pr.""ProviderId"" AND prAcc.""RoleId""=3 AND prAcc.""Active"" IS TRUE
          	                    group by acc.""AccountId"" ,prAcc.""AccountId"", apt.""AppointmentId"", apt.""ProviderLocationId"",e.""Medications"",bh.""Medications"",de.""Medications"", apt.""ProviderId"",
                                apt.""PatientId"", ""VisitType"", ""PatientType"", ""AppointmentNo"", ""AppointmentDate"", ""AppointmentTime"", ""AppointmentNotes"", ""CouponId"", ""Amount"", ""Discount"",
                                ""Total"", apt.""Active"", apt.""CreatedBy"", apt.""CreatedDate"", apt.""ModifiedBy"", apt.""ModifiedDate"", apt.""Status"", ""EncounterType"", ""IsRemainder"", pr.""FullName"", pr.""Gender"", pr.""Age""
                                --,cunpra.""CurrencySymbol""
                                , pat.""CountryId"", cun.""CountryCode"", ""IsOnline"",message.""DoctorMessageCount"",message.""PatientMessageCount"",
                                apt.""EncounterType"" ,  pat.""FullName"" , pat.""Gender"" , pat.""Age"" , pat.""Email"" , pat.""Mobile""
                                --,pra.""FullName""
                                , pat.""ThumbnailUrl""
                                --, pral.""FullName""
                                , pat.""Guid"", pr.""Guid"",pr.""ThumbnailUrl"" ,apt.""EncounterType"",PF.""FullName"" ,PF.""Gender"",PF.""Age""
                                ) AS A {where} ";

            if (model.PageIndex <= 0)
            {
                return this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
            return this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
        }


        public async Task<string> FindVisitors(AppointmentFilterModel model)
        {
            var visitTypeName = await this.unitOfWork.Visitors.FindAsync(m => m.VisitTypeId == model.VisitType);
            return visitTypeName.VisitorName;
        }
        /// <inheritdoc />
        //        public Task<IEnumerable<AppointmentModel>> FetchAllAsync(AppointmentFilterModel model)
        //        {
        //            var where = $@" WHERE 1 = 1 ";
        //            //if (!string.IsNullOrEmpty(model.VisitType))
        //            //{
        //            //    where += $@" AND A.""VisitType"" = '{model.VisitType}'";
        //            //}
        //            if (model.ResultsType == "Pending")
        //            {
        //                where += $@" AND A.""QueueStatusId"" != 5";
        //            }
        //           if (model.VisitType != null)
        //            {
        //                where += $@" AND A.""VisitTypeId"" = {model.VisitType}";
        //            }
        //            if (model.VisitTypeId != null)
        //            {
        //                where += $@" AND A.""VisitTypeId"" = {model.VisitTypeId}";
        //            }

        //            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
        //            {
        //                where += $@" AND A.""AppointmentDate""::DATE >= '{model.FromDate}'::DATE";
        //                where += $@" AND A.""AppointmentDate""::DATE <= '{model.ToDate}'::DATE";
        //            }

        //            if (!string.IsNullOrEmpty(model.FromDate) && string.IsNullOrEmpty(model.ToDate))
        //            {
        //                where += $@" AND A.""AppointmentDate""::DATE >= '%{model.FromDate}%'";
        //            }

        //            if (!string.IsNullOrEmpty(model.AppointmentNo))
        //            {
        //                where += $@" AND A.""AppointmentNo"" ILIKE '%{model.AppointmentNo}%'";
        //            }

        //            if (!string.IsNullOrEmpty(model.Status))
        //            {
        //                where += $@" AND A.""Status"" = '{model.Status}'";
        //            }
        //            else
        //            {
        //                if (model.ResultsType == "Pending")
        //                {
        //                    where += $@" AND A.""Status"" != 'C'";
        //                }

        //            }
        //            if (model.Ids != null)
        //            {
        //                where += $@" AND A.""ProviderId"" in ({model.Ids}) ";
        //            }
        //            if (model.SIds != null)
        //            {
        //                where += $@" and A.""SpecializationId"" in ({model.SIds})";
        //            }
        //            if (model.ProviderId != null)
        //            {
        //                where += $@" AND A.""ProviderId"" = {model.ProviderId}";
        //            }

        //            if (model.Gender != null)
        //            {
        //                where += $@" AND A.""PatientGender"" = '{model.Gender}'";
        //            }

        //            if (model.PatientId != null)
        //            {
        //                where += $@" AND A.""PatientId"" = {model.PatientId}";
        //            }

        //            if (model.PayTypeId != null)
        //            {
        //                where += $@" AND A.""PayTypeId"" = {model.PayTypeId}";
        //            }

        //            if (model.CountryId != null)
        //            {
        //                where += $@" AND A.""PatientCountryId"" = {model.CountryId}";
        //            }

        //            if (model.DepartmentId != null)
        //            {
        //                where += $@" AND A.""DepartmentId"" = {model.DepartmentId}";
        //            }

        //            if (model.Active != null)
        //            {
        //                where += $@" AND A.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
        //            }
        //            if (model.UMRNo != null)
        //            {
        //                where += $@" AND A.""UMRNo"" ILIKE '%{model.UMRNo}%'";
        //            }

        //            if (model.QueueStatusId != 0)
        //            {
        //                where += $@" AND A.""QueueStatusId"" = {model.QueueStatusId}";
        //            }

        //            if (model.IsFollowUpAppointment != null)
        //            {
        //                where += $@" AND A.""AppointmentTypeId"" = {model.IsFollowUpAppointment}";
        //            }

        //            if (model.LocationId != null)
        //            {
        //                where += $@" AND A.""LocationId"" = {model.LocationId}";
        //            }


        //            var telemedicineIdsQuery = $@" LEFT JOIN LATERAL (
        //		                                SELECT
        //			                                STRING_AGG (DISTINCT callLog.""TelemedicineId""::VARCHAR, ',') AS ""TelemedicineIds""
        //		                                FROM ""CallLog"" callLog
        //		                                WHERE
        //			                                callLog.""AppointmentNo"" = apt.""AppointmentNo""
        //		                                LIMIT 1
        //                                          ) telemedicineIds ON true ";

        //            var query = $@"SELECT COUNT(A.*) OVER () AS ""TotalItems"", A.* FROM (SELECT DISTINCT apt.""PaymentStatus"",string_agg(DISTINCT spl.""SpecializationName"", ',') AS ""SpecializationNames"",sp.""SpecializationName"",apt.""SpecializationId"",pr.""Languages"",apt.""FollowUpForAppointmentId"",apt.""FollowUpForAdmissionId"",pat.""StreetAddress"",pat.""City"",vt.""VisitorName"",pat.""State"",pat.""Zipcode"",pat.""Amount"" as ""PatientRegistrationAmount"",pat.""PaymentStatus"" as ""PatientPaymentStatus"",acc.""AccountId"" as ""PatientAccountId"",prAcc.""AccountId"" as ""ProviderAccountId"",
        //            													 apt.""AppointmentId"", apt.""ProviderLocationId"", apt.""ProviderId"", apt.""PatientId"", apt.""VisitType"", apt.""PatientType"", apt.""AppointmentNo"", apt.""AppointmentDate"", apt.""AppointmentTime"", apt.""AppointmentNotes"", apt.""CouponId"", apt.""Amount"", apt.""Discount"", apt.""Total"", apt.""Active"",apt.""CreatedBy"", apt.""CreatedDate"", apt.""ModifiedBy"", apt.""ModifiedDate"", apt.""Status"", apt.""EncounterType"", apt.""Old_AppointmentId"", apt.""IsRemainder"", apt.""Reason"",
        //                                                                 apt.""AppCharges"", apt.""PatientFamilyId"", apt.""WalletAmount"", apt.""DepartmentId"", PT.""PayTypeId"" as ""PaymentType"",PT.""PayTypeId"", PT.""PayTypeName"",
        //            													 apt.""PaymentNumber"", apt.""ChargeType"", apt.""ChargeTypesId"", apt.""VisitTypeId"",apt.""CheckedIn"",apt.""CheckedOut"",apt.""Tat"",apt.""LocationId"", apt.""AppointmentTypeId"",rt.""Name"",

        //                                                                 pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"",pat.""FatherOrHusband"",ct.""ChargeName"" AS ""ChargeTypesName"",Lt.""Name"" as ""LocationName"",
        //                                            cunpra.""CurrencySymbol"", pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",telemedicine.*,telemedicineIds.""TelemedicineIds"",
        //                                            (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentDate"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""AppointmentPreviousDate"",
        //                                            (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentTime"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""AppointmentPreviousTime"",
        //                                            (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentNo"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""PreviousAppointmentNo"",
        //                                            (case when apt.""FollowUpForAdmissionId"" is not null then (select dis.""DischargeDate"" from ""Discharge"" dis join ""Admission"" adm on adm.""AdmissionId"" = dis.""AdmissionId""	where adm.""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""AdmissionDischargeDate"",
        //                                            (case when apt.""FollowUpForAdmissionId"" is not null then (select dis.""DischargeTime"" from ""Discharge"" dis join ""Admission"" adm on adm.""AdmissionId"" = dis.""AdmissionId""	where adm.""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""AdmissionDischargeTime"",
        //                                            (case when apt.""FollowUpForAdmissionId"" is not null then (select ""AdmissionNo"" from ""Admission"" where ""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""PreviousAdmissionNo"",

        //                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"", pat.""UMRNo"", D.""DepartmentName"", pat.""MaritalStatus"" AS ""PatientMaritalStatus"",
        //                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
        //                               WHEN apt.""EncounterType"" in ('{EncounterTypes.Encounter}', '{EncounterTypes.InternalMedicine}')
        //--AND e.""Medications""
        //IS NOT NULL THEN TRUE
        //                                --WHEN apt.""EncounterType"" in ('{EncounterTypes.BehavioralHealth}') AND bh.""Medications"" IS NOT NULL THEN TRUE
        //ELSE FALSE END AS ""IsPrescription"",
        //                               (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"", pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"",pr.""Age"" as ""ProviderAge"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
        //                                pra.""FullName"" AS ""PracticeName"", pral.""Name"" AS ""ProviderLocation"", pat.""Guid""::text AS ""PatientGuid"", pr.""Guid""::text AS ""ProviderGuid"",
        //                                 (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"",
        //                                (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE NULL END) AS ""PatientThumbnailUrl"", apt.""EncounterType"",
        //                                CASE WHEN acs.""AccountSessionId"" IS NULL THEN FALSE ELSE TRUE END AS ""IsOnline"",pat.""ReferredBy"",pat.""ReferredByName""
        //                                --(case when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is  null  then false
        //                                --when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is not null and max(dc.""DischargeId"")over(partition by adm.""AdmissionId"") is  null  then true
        //                                --when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is not null and max(dc.""DischargeId"")over(partition by adm.""AdmissionId"") is not null  then false end
        //                                --)""isActiveAdmissionExists""
        //                                , qq.""Name"" ""QueueStatus""
        //                                , apt.""TokenNumber"", apt.""QueueStatusId"", apt.""WaitingCount""
        //                               	,IDP.""IdProofName"",pat.""IdProofValue""
        //                                , rt.""Name"" as ""PatientReferredName""
        //                                , APTP.""Name"" as ""AppointmentTypeName""
        //                                , apt.""QueueEndDate""
        //							 	, apt.""QueueStartDate""
        //								,Extract(epoch FROM(apt.""QueueEndDate"" - apt.""QueueStartDate"")) / 60 AS ""Minutes""
        //                                FROM ""Appointment"" apt
        //                                LEFT JOIN ""QueueStatus"" qq on qq.""QueueStatusId"" = apt.""QueueStatusId""
        //                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
        //                                left join ""Admission"" adm on adm.""PatientId"" = pat.""PatientId""
        //                                left join ""Discharge"" dc on dc.""AdmissionId"" = adm.""AdmissionId""
        //                                LEFT JOIN ""PatientFamily"" PF on PF.""PatientFamilyId"" = apt.""PatientFamilyId""
        //                                LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
        //                                LEFT JOIN ""Encounter"" e ON e.""AppointmentId"" = apt.""AppointmentId"" AND e.""Active"" IS TRUE
        //                                LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
        //                                JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE AND pr.""ApprovalStatus"" IS TRUE
        //							    LEFT JOIN ""Specialization"" spl ON spl.""SpecializationId"" = ANY(pr.""Specializations"") AND spl.""Active"" IS TRUE
        //								left join ""Specialization"" sp on sp.""SpecializationId"" = apt.""SpecializationId""
        //                                LEFT JOIN ""Department"" D on D.""DepartmentId"" = pr.""DepartmentId""
        //                                JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
        //                                JOIN ""Location"" pral ON pral.""LocationId"" = prl.""LocationId"" AND pral.""Active"" IS TRUE
        //                                JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND cunpra.""Active"" IS TRUE
        //                                JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
        //                                JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId"" AND acc.""RoleId""= 4
        //                                LEFT JOIN ""AccountSession"" acs ON acs.""AccountId"" = acc.""AccountId""
        //                                JOIN ""Account"" prAcc ON prAcc.""ReferenceId"" = pr.""ProviderId"" AND prAcc.""RoleId""=3 AND prAcc.""Active"" IS TRUE
        //                                JOIN ""ChargeTypes"" ct ON ct.""ChargeTypesId"" = apt.""ChargeTypesId""
        //                                left JOIN ""Location"" Lt ON Lt.""LocationId"" = apt.""LocationId""
        //                                left Join ""PayType"" PT on PT.""PayTypeId""=apt.""PayTypeId""
        //                                left join ""AppointmentType"" APTP on APTP.""AppointmentTypeId"" = apt.""AppointmentTypeId""
        //                                left Join ""IdProof"" IDP on IDP.""IdProofId""	= pat.""IdProofId""
        //                                left join ""PatientReferredBy"" rt on rt.""PatientReferredById"" = pat.""PatientReferredById""
        //								left Join ""VisitType"" vt on vt.""VisitTypeId"" = apt.""VisitTypeId""
        //                               -- left Join ""PatientRegistrationDetail"" PRD on PRD.""PatientId""=pat.""PatientId""
        //                                    { telemedicineIdsQuery}
        //            LEFT JOIN LATERAL(
        //                SELECT
        //                    telemedicineCallHistory.""TelemedicineCallHistoryId"",
        //                    telemedicineCallHistory.""Status"" AS ""CallStatus"",
        //                    telemedicineCallHistory.""InProgress"",
        //                    telemedicineCallHistory.""CreatedDate"" AS ""CallStatusDate"",
        //                    telemedicineCallHistory.""ModifiedDate"" AS ""CallStatusModifiedDate"",
        //                    telemedicineCallHistory.""CallType"",
        //                    callerTelemedicine.*,
        //                    receiverTelemedicine.*,
        //                    activeUsers.*
        //                FROM ""TelemedicineHistory"" telemedicineHistory
        //                JOIN ""TelemedicineCallHistory"" telemedicineCallHistory on telemedicineCallHistory.""TelemedicineHistoryId"" = telemedicineHistory.""TelemedicineHistoryId""
        //                LEFT JOIN LATERAL(
        //                      SELECT
        //                            telemedicineCallerHistory.""Status"" AS ""CallerCallStatus"",
        //                            telemedicineCallerHistory.""Date"" AS ""CallerCallStatusDate"",
        //                            callerAccount.""RoleId"" AS ""CallerRoleId""
        //                        FROM ""TelemedicineUsersHistory"" telemedicineCallerHistory
        //                            JOIN ""Account"" callerAccount on callerAccount.""AccountId"" = telemedicineCallerHistory.""CallerId""
        //                            WHERE telemedicineCallerHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""
        //                            AND callerAccount.""RoleId"" != 4
        //                            ORDER BY telemedicineCallerHistory.""Date"" DESC
        //                            LIMIT 1
        //                ) callerTelemedicine ON TRUE
        //                LEFT JOIN LATERAL(
        //                      SELECT
        //                            telemedicineReceiverHistory.""Status"" AS ""ReceiverCallStatus"",
        //                            telemedicineReceiverHistory.""Date"" AS ""ReceiverCallStatusDate"",
        //                            receiverAccount.""RoleId"" AS ""ReceiverRoleId""
        //                        FROM ""TelemedicineUsersHistory"" telemedicineReceiverHistory
        //                            JOIN ""Account"" receiverAccount on receiverAccount.""AccountId"" = telemedicineReceiverHistory.""AccountId""
        //                            WHERE telemedicineReceiverHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""
        //                            AND receiverAccount.""RoleId"" = 4
        //                            ORDER BY telemedicineReceiverHistory.""Date"" DESC
        //                            LIMIT 1
        //                ) receiverTelemedicine ON TRUE
        //                LEFT JOIN LATERAL(
        //                        SELECT
        //                            STRING_AGG(activeAccount.""FullName"" || '#' || role.""RoleName"" || '#' || telemedicineActiveUsersHistory.""Date"", ',') ""ActiveUsers""
        //                        FROM ""TelemedicineUsersHistory"" telemedicineActiveUsersHistory
        //                            JOIN ""Account"" activeAccount on activeAccount.""AccountId"" = telemedicineActiveUsersHistory.""AccountId""
        //                            JOIN ""Role"" role on role.""RoleId"" = activeAccount.""RoleId""
        //                            WHERE telemedicineActiveUsersHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""
        //                            AND telemedicineActiveUsersHistory.""InProgress"" IS TRUE AND telemedicineCallHistory.""InProgress"" IS TRUE
        //                            LIMIT 1
        //                ) activeUsers ON TRUE
        //                WHERE
        //                    telemedicineHistory.""AppointmentId"" = apt.""AppointmentId""
        //                    ORDER BY telemedicineCallHistory.""CreatedDate"" DESC
        //                LIMIT 1
        //        ) telemedicine ON true
        //                                group by sp.""SpecializationName"",apt.""PaymentStatus"" ,pr.""Languages"",apt.""FollowUpForAppointmentId"",apt.""FollowUpForAdmissionId"",pat.""StreetAddress"",pat.""City"",vt.""VisitorName"",pat.""State"",pat.""Zipcode"",acc.""AccountId"",pracc.""AccountId"",apt.""AppointmentId"",
        //                                                   pt.""PayTypeId"", pt.""PayTypeName"",pr.""FullName"",pr.""Gender"",pat.""FatherOrHusband"",ct.""ChargeName"",lt.""Name"",cunpra.""CurrencySymbol"",pat.""CountryId"",cun.""CountryCode"",pat.""UMRNo"",d.""DepartmentName"",pat.""MaritalStatus"",e.""Medications"",
        //													bh.""Medications"",pf.""FullName"",pat.""FullName"",pat.""Gender"",pat.""Age"",pr.""Age"",pat.""Email"",pat.""Mobile"",pra.""FullName"",pral.""Name"",pat.""Guid"",pr.""Guid"",pr.""ThumbnailUrl"",pat.""ThumbnailUrl"",acs.""AccountSessionId"",pat.""ReferredBy"",pat.""ReferredByName"",qq.""Name"",rt.""Name"",
        //telemedicine.""TelemedicineCallHistoryId"",telemedicine.""CallStatus"",telemedicine.""InProgress"",telemedicine.""CallStatusDate"",
        //      telemedicine.""CallStatusModifiedDate"",telemedicine.""CallType"",telemedicine.""CallerCallStatus"",telemedicine.""CallerCallStatusDate"",
        //	  telemedicine.""CallerRoleId"", telemedicine.""ReceiverCallStatus"",telemedicine.""ReceiverCallStatusDate"",telemedicine.""ReceiverRoleId"",telemedicine.""ActiveUsers""
        //	 ,telemedicineIds.""TelemedicineIds"",IDP.""IdProofName"",pat.""IdProofValue"" , APTP.""Name"",pat.""Amount"",pat.""PaymentStatus"",apt.""SpecializationId""
        //                            ) AS A  {where}  Order BY A.""AppointmentDate"" ASC, A.""AppointmentTime"" ASC";

        //            if (model.PageIndex <= 0)
        //            {
        //                return this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
        //            }

        //            model.PageIndex -= 1;
        //            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
        //            var appointments = this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
        //            return appointments;
        //        }


        /// <inheritdoc />
        public async Task<IEnumerable<AppointmentModel>> FetchAllAsync(AppointmentFilterModel model)
        {
            var where = $@" WHERE 1 = 1 ";
            //if (!string.IsNullOrEmpty(model.VisitType))
            //{
            //    where += $@" AND A.""VisitType"" = '{model.VisitType}'";
            //}
            if (model.ResultsType == "Pending" && model.isMobile == false)
            {
                where += $@" AND A.""QueueStatusId"" != 5";
            }
            if (model.CubicleId != null)
            {
                where += $@" AND A.""CubicleId"" = {model.CubicleId}";
            }
            if (model.VisitType != null)
            {
                where += $@" AND A.""VisitTypeId"" = {model.VisitType}";
            }
            if (model.VisitTypeId != null)
            {
                where += $@" AND A.""VisitTypeId"" = {model.VisitTypeId}";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND A.""AppointmentDate""::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND A.""AppointmentDate""::DATE <= '{model.ToDate}'::DATE";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND A.""AppointmentDate""::DATE >= '%{model.FromDate}%'";
            }

            if (!string.IsNullOrEmpty(model.AppointmentNo))
            {
                where += $@" AND A.""AppointmentNo"" ILIKE '%{model.AppointmentNo}%'";
            }

            if (!string.IsNullOrEmpty(model.Status))
            {
                where += $@" AND A.""Status"" = '{model.Status}'";
            }
            else
            {
                if (model.ResultsType == "Pending")
                {
                    where += $@" AND A.""Status"" != 'C'";
                }

            }
            if (model.Ids != null)
            {
                where += $@" AND A.""ProviderId"" in ({model.Ids}) ";
            }
            if (model.SIds != null)
            {
                where += $@" and A.""SpecializationId"" in ({model.SIds})";
            }
            if (model.ProviderId != null)
            {
                where += $@" AND A.""ProviderId"" = {model.ProviderId}";
            }

            if (model.Gender != null)
            {
                where += $@" AND A.""PatientGender"" = '{model.Gender}'";
            }

            if (model.PatientId != null)
            {
                where += $@" AND A.""PatientId"" = {model.PatientId}";
            }

            if (model.PayTypeId != null)
            {
                where += $@" AND A.""PayTypeId"" = {model.PayTypeId}";
            }

            if (model.CountryId != null)
            {
                where += $@" AND A.""PatientCountryId"" = {model.CountryId}";
            }

            if (model.DepartmentId != null)
            {
                where += $@" AND A.""DepartmentId"" = {model.DepartmentId}";
            }

            if (model.Active != null)
            {
                where += $@" AND A.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            }
            if (model.UMRNo != null)
            {
                where += $@" AND A.""UMRNo"" ILIKE '%{model.UMRNo}%'";
            }

            if (model.QueueStatusId != 0)
            {
                where += $@" AND A.""QueueStatusId"" = {model.QueueStatusId}";
            }
            if (model.IsFollowUpAppointment != null)
            {
                where += $@" AND A.""AppointmentTypeId"" = {model.IsFollowUpAppointment}";
            }

            if (model.LocationId != null)
            {
                where += $@" AND A.""LocationId"" = {model.LocationId}";
            }

            if (model.PaymentStatus != null)
            {
                where += $@" AND A.""PaymentStatus"" = {model.PaymentStatus}";
            }

            if (model.isMobile)
            {
                where += $@" Order BY A.""AppointmentDate"" DESC, A.""AppointmentTime"" DESC";
            }
            else
            {
                where += $@" Order BY A.""AppointmentDate"" ASC, A.""AppointmentTime"" ASC";
            }

            var telemedicineIdsQuery = $@" LEFT JOIN LATERAL (
		                                SELECT
			                                STRING_AGG (DISTINCT callLog.""TelemedicineId""::VARCHAR, ',') AS ""TelemedicineIds""
		                                FROM ""CallLog"" callLog
		                                WHERE
			                                callLog.""AppointmentNo"" = apt.""AppointmentNo""
		                                LIMIT 1
                                          ) telemedicineIds ON true ";
            //patient registration charges and status
            var query = $@"SELECT COUNT(A.*) OVER () AS ""TotalItems"", A.* FROM (SELECT DISTINCT COUNT(DISTINCT AT.""AppointmentTransactionId"") as ""TransactionCount"",apt.""IsEmergency"",message.""DoctorMessageCount"",message.""PatientMessageCount"",apt.""IsSalucroAppointment"",apt.""PaymentStatus"",string_agg(DISTINCT spl.""SpecializationName"", ',') AS ""SpecializationNames"",sp.""SpecializationName"",apt.""IsEncounter"",apt.""SpecializationId"",pr.""Languages"",apt.""FollowUpForAppointmentId"",apt.""FollowUpForAdmissionId"",HWC.""HWCName"" as ""HWCCategory"", csl.""CounsellingId"", csl.""IsDraft"" AS ""IsDraftCounselling"", pat.""StreetAddress"",pat.""City"",vt.""VisitorName"",pat.""RelationType"" as ""PatientRelation"",pat.""Salutation"" as ""PatientSalutation"",pat.""AddressLine2"" as ""Area"",pat.""State"",pat.""Zipcode"",pat.""PaymentStatus"" as ""PatientPaymentStatus"",acc.""AccountId"" as ""PatientAccountId"",prAcc.""AccountId"" as ""ProviderAccountId"",
            													 apt.""AppointmentId"", cub.""Name"" ""CubicleName"", apt.""ProviderAvailabilityId"", apt.""ProviderId"", apt.""PatientId"", apt.""VisitType"", apt.""PatientType"", apt.""AppointmentNo"", apt.""AppointmentDate"", apt.""AppointmentTime"", apt.""AppointmentNotes"", apt.""CouponId"", apt.""Amount"", apt.""Discount"", apt.""Total"", apt.""Active"",apt.""CreatedBy"", apt.""CreatedDate"", apt.""ModifiedBy"", apt.""ModifiedDate"", apt.""Status"", apt.""EncounterType"", apt.""Old_AppointmentId"", apt.""IsRemainder"", apt.""Reason"",
                                                                 apt.""AppCharges"", apt.""PatientFamilyId"", apt.""WalletAmount"", apt.""DepartmentId"", apt.""PaymentType"",PT.""PayTypeId"", PT.""PayTypeName"",
            													 apt.""PaymentNumber"", apt.""ChargeType"", apt.""ChargeTypesId"", apt.""VisitTypeId"",apt.""CheckedIn"",apt.""CheckedOut"",apt.""Tat"",apt.""LocationId"", apt.""AppointmentTypeId"",rt.""Name"",apt.""ConsultationTypeId"",cst.""Name"" ""ConsultationName"", apt.""AppointmentEndTime"",apt.""SessionId"",

                                                                 pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"",pat.""FatherOrHusband"",ct.""ChargeName"" AS ""ChargeTypesName"",Lt.""Name"" as ""LocationName"",Lt.""MapUrl"" as ""MapUrl"",
                                            cunpra.""CurrencySymbol"", pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",telemedicine.*,telemedicineIds.""TelemedicineIds"",
                                            (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentDate"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""AppointmentPreviousDate"",
                                            (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentTime"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""AppointmentPreviousTime"",
                                            (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentNo"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""PreviousAppointmentNo"",
                                            (case when apt.""FollowUpForAdmissionId"" is not null then (select dis.""DischargeDate"" from ""Discharge"" dis join ""Admission"" adm on adm.""AdmissionId"" = dis.""AdmissionId""	where adm.""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""AdmissionDischargeDate"",
                                            (case when apt.""FollowUpForAdmissionId"" is not null then (select dis.""DischargeTime"" from ""Discharge"" dis join ""Admission"" adm on adm.""AdmissionId"" = dis.""AdmissionId""	where adm.""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""AdmissionDischargeTime"",
                                            (case when apt.""FollowUpForAdmissionId"" is not null then (select ""AdmissionNo"" from ""Admission"" where ""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""PreviousAdmissionNo"",

                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"", pat.""UMRNo"", D.""DepartmentName"", pat.""MaritalStatus"" AS ""PatientMaritalStatus"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
                               WHEN apt.""EncounterType"" in ('Encounter', 'InternalMedicine')
--AND e.""Medications""
IS NOT NULL THEN TRUE
                                --WHEN apt.""EncounterType"" in ('BehavioralHealth') AND bh.""Medications"" IS NOT NULL THEN TRUE
ELSE FALSE END AS ""IsPrescription"",
                               (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"", pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"",pat.""DateOfBirth"" AS ""PatientDateOfBirth"",pr.""Age"" as ""ProviderAge"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
                                pra.""FullName"" AS ""PracticeName"", PAL.""Name"" AS ""ProviderLocation"", pat.""Guid""::text AS ""PatientGuid"", pr.""Guid""::text AS ""ProviderGuid"",
        (Case when  pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/', pr.""Guid"", '/',  pr.""ThumbnailUrl"") else null end) AS ""ProviderThumbnailUrl"",

    (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"", apt.""EncounterType"",
                                CASE WHEN acs.""AccountSessionId"" IS NULL THEN FALSE ELSE TRUE END AS ""IsOnline"",rt.""Name"" as ""ReferredBy"",pat.""ReferredByName""
                                --(case when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is  null  then false
                                --when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is not null and max(dc.""DischargeId"")over(partition by adm.""AdmissionId"") is  null  then true
                                --when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is not null and max(dc.""DischargeId"")over(partition by adm.""AdmissionId"") is not null  then false end
                                --)""isActiveAdmissionExists""
                                , qq.""Name"" ""QueueStatus"",Count(Distinct pc.""PatientChatBoxId"")  as ""MessageCount""
                                , apt.""TokenNumber"", apt.""QueueStatusId"", apt.""WaitingCount""
                               	,IDP.""IdProofName"",pat.""IdProofValue""
                                , rt.""Name"" as ""PatientReferredName""
                                , APTP.""Name"" as ""AppointmentTypeName""
                                , apt.""QueueEndDate""
							 	, apt.""QueueStartDate""
                                , apt.""CubicleId"",
                                ET.""EncounterName"",
                                ob.""IsAppointmentClosed"",
                                gyn.""IsEncounterClosed"",
								Extract(epoch FROM(apt.""QueueEndDate"" - apt.""QueueStartDate"")) / 60 AS ""Minutes""
                                ,apt.""AppointmentDate""+ DSM.""FollowUpDays""::int as ""FollowUpValidityDate""
                                FROM ""Appointment"" apt
                                LEFT JOIN ""QueueStatus"" qq on qq.""QueueStatusId"" = apt.""QueueStatusId""
                                LEFT JOIN ""Cubicle"" cub on cub.""CubicleId"" = apt.""CubicleId""
                                left join ""Message"" message on message.""AppointmentId"" = apt.""AppointmentId""
                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                LEFT JOIN ""Counselling"" csl ON csl.""PatientId"" = apt.""PatientId"" AND csl.""Active"" IS TRUE
                                left join ""Admission"" adm on adm.""PatientId"" = pat.""PatientId""
                                left join ""Discharge"" dc on dc.""AdmissionId"" = adm.""AdmissionId""
                                LEFT JOIN ""PatientFamily"" PF on PF.""PatientFamilyId"" = apt.""PatientFamilyId""
                                LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                LEFT JOIN ""Encounter"" e ON e.""AppointmentId"" = apt.""AppointmentId"" AND e.""Active"" IS TRUE
                                LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
                                JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE AND pr.""ApprovalStatus"" IS TRUE
							    LEFT JOIN ""Specialization"" spl ON spl.""SpecializationId"" = ANY(pr.""Specializations"") AND spl.""Active"" IS TRUE
								left join ""Specialization"" sp on sp.""SpecializationId"" = apt.""SpecializationId""
                                LEFT JOIN ""Department"" D on D.""DepartmentId"" = pr.""DepartmentId""
								LEFT JOIN ""ProviderAvailability"" PA ON PA.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND PA.""Active"" IS TRUE
								LEFT JOIN ""Location"" PAL ON PAL.""LocationId"" = PA.""LocationId"" AND PAL.""Active"" IS TRUE
                                --JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
                                --JOIN ""Location"" pral ON pral.""LocationId"" = prl.""LocationId"" AND pral.""Active"" IS TRUE
                                LEFT JOIN ""Country"" cunpra ON cunpra.""CountryId"" = PAL.""CountryId"" AND cunpra.""Active"" IS TRUE
                                LEFT JOIN ""Practice"" pra ON pra.""PracticeId"" = PAL.""PracticeId"" AND pra.""Active"" IS TRUE
                                JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId"" AND acc.""RoleId""= 4
                                LEFT JOIN ""AccountSession"" acs ON acs.""AccountId"" = acc.""AccountId""
                                LEFT JOIN ""Account"" prAcc ON prAcc.""ReferenceId"" = pr.""ProviderId"" AND prAcc.""RoleId""=3 AND prAcc.""Active"" IS TRUE
                                JOIN ""ChargeTypes"" ct ON ct.""ChargeTypesId"" = apt.""ChargeTypesId""
                                join ""ConsultationType"" cst on cst.""ConsultationTypeId"" = apt.""ConsultationTypeId""
                                left JOIN ""Location"" Lt ON Lt.""LocationId"" = apt.""LocationId""
                                left Join ""PayType"" PT on PT.""PayTypeId""=apt.""PayTypeId""
                                left join ""AppointmentType"" APTP on APTP.""AppointmentTypeId"" = apt.""AppointmentTypeId""
                                left Join ""IdProof"" IDP on IDP.""IdProofId""	= pat.""IdProofId""
                                left Join ""HWCPatient"" HWC on HWC.""HWCPatientId""= pat.""HWCPatientId""
                                left join ""PatientReferredBy"" rt on rt.""PatientReferredById"" = pat.""PatientReferredById""
								left Join ""VisitType"" vt on vt.""VisitTypeId"" = apt.""VisitTypeId""
                                left join ""EncounterType"" ET ON ET.""EncounterTypeId""=sp.""EncounterTypeId""
                                left join ""ObEncounter"" ob ON ob.""AppointmentId""=apt.""AppointmentId""
                                left join ""GynEncounter"" gyn ON gyn.""AppointmentId""=apt.""AppointmentId""
                                --left Join ""Receipt"" R on R.""RespectiveId""=pat.""PatientId""	 and R.""ReceiptAreaTypeId""=3
							 --left Join ""Receipt"" RA on RA.""RespectiveId""=apt.""AppointmentId""	 and RA.""ReceiptAreaTypeId""=4
                                --left Join ""Receipt"" RCA on RCA.""RespectiveId""=apt.""AppointmentId""	 and R.""ReceiptAreaTypeId""=5
                                 left Join ""PatientChatBox"" pc on pc.""AppointmentId""=apt.""AppointmentId""
                                LEFT JOIN ""DoctorSpecializationChargeModuleDetails"" PAC ON PAC.""DoctorSpecializationChargeModuleDetailsId"" = apt.""DoctorSpecializationChargeModuleDetailsId""
                                Left Join ""DoctorSpecializationMap"" DSM on DSM.""DoctorSpecializationMapId"" = PAC.""ReferenceId""
                                left join ""AppointmentTransaction"" AT on AT.""AppointmentId""=apt.""AppointmentId"" and ""ReceiptTypeId""=1
                                     LEFT JOIN LATERAL (
		                                SELECT
			                                STRING_AGG (DISTINCT callLog.""TelemedicineId""::VARCHAR, ',') AS ""TelemedicineIds""
		                                FROM ""CallLog"" callLog
		                                WHERE
			                                callLog.""AppointmentNo"" = apt.""AppointmentNo""
		                                LIMIT 1
                                          ) telemedicineIds ON true
            LEFT JOIN LATERAL(
                SELECT
                    telemedicineCallHistory.""TelemedicineCallHistoryId"",
                    telemedicineCallHistory.""Status"" AS ""CallStatus"",
                    telemedicineCallHistory.""InProgress"",
                    telemedicineCallHistory.""CreatedDate"" AS ""CallStatusDate"",
                    telemedicineCallHistory.""ModifiedDate"" AS ""CallStatusModifiedDate"",
                    telemedicineCallHistory.""CallType"",
                    callerTelemedicine.*,
                    receiverTelemedicine.*,
                    activeUsers.*
                FROM ""TelemedicineHistory"" telemedicineHistory
                JOIN ""TelemedicineCallHistory"" telemedicineCallHistory on telemedicineCallHistory.""TelemedicineHistoryId"" = telemedicineHistory.""TelemedicineHistoryId""
                LEFT JOIN LATERAL(
                      SELECT
                            telemedicineCallerHistory.""Status"" AS ""CallerCallStatus"",
                            telemedicineCallerHistory.""Date"" AS ""CallerCallStatusDate"",
                            callerAccount.""RoleId"" AS ""CallerRoleId""
                        FROM ""TelemedicineUsersHistory"" telemedicineCallerHistory
                            JOIN ""Account"" callerAccount on callerAccount.""AccountId"" = telemedicineCallerHistory.""CallerId""
                            WHERE telemedicineCallerHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""
                            AND callerAccount.""RoleId"" != 4
                            ORDER BY telemedicineCallerHistory.""Date"" DESC
                            LIMIT 1
                ) callerTelemedicine ON TRUE
                LEFT JOIN LATERAL(
                      SELECT
                            telemedicineReceiverHistory.""Status"" AS ""ReceiverCallStatus"",
                            telemedicineReceiverHistory.""Date"" AS ""ReceiverCallStatusDate"",
                            receiverAccount.""RoleId"" AS ""ReceiverRoleId""
                        FROM ""TelemedicineUsersHistory"" telemedicineReceiverHistory
                            JOIN ""Account"" receiverAccount on receiverAccount.""AccountId"" = telemedicineReceiverHistory.""AccountId""
                            WHERE telemedicineReceiverHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""
                            AND receiverAccount.""RoleId"" = 4
                            ORDER BY telemedicineReceiverHistory.""Date"" DESC
                            LIMIT 1
                ) receiverTelemedicine ON TRUE
                LEFT JOIN LATERAL(
                        SELECT
                            STRING_AGG(activeAccount.""FullName"" || '#' || role.""RoleName"" || '#' || telemedicineActiveUsersHistory.""Date"", ',') ""ActiveUsers""
                        FROM ""TelemedicineUsersHistory"" telemedicineActiveUsersHistory
                            JOIN ""Account"" activeAccount on activeAccount.""AccountId"" = telemedicineActiveUsersHistory.""AccountId""
                            JOIN ""Role"" role on role.""RoleId"" = activeAccount.""RoleId""
                            WHERE telemedicineActiveUsersHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""
                            AND telemedicineActiveUsersHistory.""InProgress"" IS TRUE AND telemedicineCallHistory.""InProgress"" IS TRUE
                            LIMIT 1
                ) activeUsers ON TRUE
                WHERE
                    telemedicineHistory.""AppointmentId"" = apt.""AppointmentId""
                    ORDER BY telemedicineCallHistory.""CreatedDate"" DESC
                LIMIT 1
        ) telemedicine ON true
                                group by message.""DoctorMessageCount"",message.""PatientMessageCount"",DSM.""FollowUpDays"",HWC.""HWCName"",pat.""AddressLine2"",pat.""RelationType"",pat.""Salutation"",sp.""SpecializationName"",apt.""PaymentStatus"" ,pr.""Languages"",apt.""FollowUpForAppointmentId"",apt.""FollowUpForAdmissionId"",pat.""StreetAddress"",pat.""City"",vt.""VisitorName"",pat.""State"",pat.""Zipcode"",acc.""AccountId"",pracc.""AccountId"",apt.""AppointmentId"",apt.""ConsultationTypeId"",cst.""Name"",
                                                   pt.""PayTypeId"", pt.""PayTypeName"",pr.""FullName"",pr.""Gender"", csl.""CounsellingId"", csl.""IsDraft"", pat.""FatherOrHusband"",ct.""ChargeName"",lt.""Name"",lt.""MapUrl"",cunpra.""CurrencySymbol"",pat.""CountryId"",cun.""CountryCode"",pat.""UMRNo"",d.""DepartmentName"",pat.""MaritalStatus"",e.""Medications"",
													bh.""Medications"",pf.""FullName"",pat.""FullName"",pat.""Gender"",pat.""Age"", pat.""DateOfBirth"",pr.""Age"",pat.""Email"",pat.""Mobile"",pra.""FullName"",PAL.""Name"",pat.""Guid"",pr.""Guid"",pr.""ThumbnailUrl"",pat.""ThumbnailUrl"",acs.""AccountSessionId"",rt.""PatientReferredById"",pat.""ReferredByName"",qq.""Name"",rt.""Name"",
telemedicine.""TelemedicineCallHistoryId"",telemedicine.""CallStatus"",telemedicine.""InProgress"",telemedicine.""CallStatusDate"",
      telemedicine.""CallStatusModifiedDate"",telemedicine.""CallType"",telemedicine.""CallerCallStatus"",telemedicine.""CallerCallStatusDate"",
	  telemedicine.""CallerRoleId"", telemedicine.""ReceiverCallStatus"",telemedicine.""ReceiverCallStatusDate"",telemedicine.""ReceiverRoleId"",telemedicine.""ActiveUsers""
	 ,telemedicineIds.""TelemedicineIds"",IDP.""IdProofName"",pat.""IdProofValue"" , APTP.""Name"",pat.""PaymentStatus"",apt.""SpecializationId"", cub.""Name"",  ET.""EncounterName"",  ob.""IsAppointmentClosed"",gyn.""IsEncounterClosed"",apt.""SessionId""
                            ) AS A  {where}";

            if (model.RoleId != 3)

                if (model.RoleId == 3)
                {
                    if (model.PageIndex <= 0)
                    {
                        return await this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
                    }
                    model.PageIndex -= 1;
                    query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
                    //var q = model.pagination;
                    //if (model.pagination == true)
                    //{
                    //    model.PageIndex = 1;
                    //    query += " LIMIT " + 100 + " offset " + (model.PageIndex * model.PageSize);
                    //}
                    //else
                    //{
                    //    query += " LIMIT " + 100;
                    //}
                }
                else
                {
                    if (model.PageIndex <= 0)
                    {
                        return await this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
                    }
                    model.PageIndex -= 1;
                    query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);

                    //if (model.pagination == true)
                    //{
                    //    model.PageIndex -= 1;
                    //    query += " LIMIT " + 100 + " offset " + (model.PageIndex * model.PageSize);
                    //}
                    //else
                    //{
                    //    query += " LIMIT " + 100;
                    //}

                }

            var appointments = await this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);

            var appointmentModels = appointments.ToList();
            foreach (var appointment in appointmentModels)
            {
                var apptsQuery = $@"select A.""AppointmentId"",A.""AppointmentTime"",A.""AppointmentDate""::Date,P.""FullName"" as ""ProviderName"",A.""Total"" from ""Appointment"" A
                                    join ""Provider"" P on P.""ProviderId""=A.""ProviderId""
                                    where A.""PatientId""={appointment.PatientId} order by A.""AppointmentId"" desc";
                var appts = await this.unitOfWork.Current.QueryAsync<AppointmentModel>(apptsQuery);
                if (appts != null && appts.Count() > 1)
                {
                    var appt = appts.ToList()[0];
                    var nextAppt = appt.AppointmentId != appointment.AppointmentId ? appt : null;

                    if (nextAppt != null)
                    {

                        var time = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(nextAppt.AppointmentTime).ToString("hh:mm tt");
                        appointment.NextAppointment = $@"Given on {nextAppt.AppointmentDate:yyyy-MM-dd} To Dr.{nextAppt.ProviderName} at {time}.";
                    }
                    var lastAppt = appts.ToList()[1];
                    appointment.LastConsultedDate = lastAppt.AppointmentDate;
                    appointment.LastConsultedTime = Convert.ToDateTime(DateTime.Now.ToString("yyyy-MM-dd")).Add(lastAppt.AppointmentTime).ToString("hh:mm tt");

                    appointment.LastConsultedDoctor = lastAppt.ProviderName;
                    appointment.LastPaidAmount = lastAppt.Total;
                }
            }

            return appointments;
        }



        /// <inheritdoc />
        public Task<IEnumerable<AppointmentModel>> FindByPatientAsync(int patientId, int providerId)
        {
            var where = $@" WHERE A.""PatientId"" = {patientId} Order BY A.""AppointmentDate"" DESC, A.""AppointmentTime"" DESC";
            if (providerId > 0)
            {
                where = $@" WHERE A.""ProviderId"" = {providerId} AND A.""PatientId"" = {patientId} Order BY A.""AppointmentDate"" DESC, A.""AppointmentTime"" DESC";
            }

            var query = $@"SELECT COUNT(A.*) OVER () AS ""TotalItems"", A.* ,
                                TO_CHAR(A.""AppointmentDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(A.""AppointmentTime"", 'hh12:mi AM') ""AppointmentDateTime""
                                FROM (SELECT acc.""AccountId"" as ""PatientAccountId"",prAcc.""AccountId"" as ""ProviderAccountId"", apt.*, pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"", pr.""Age"" AS ""ProviderAge"",
                                 cun.""CountryCode"" AS ""PatientCountryCode"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
                                WHEN apt.""EncounterType"" in ('{EncounterTypes.Encounter}', '{EncounterTypes.InternalMedicine}') AND e.""Medications"" IS NOT NULL THEN TRUE
                                WHEN apt.""EncounterType"" in ('{EncounterTypes.DentalEncounter}') AND de.""Medications"" IS NOT NULL THEN TRUE
                                WHEN apt.""EncounterType"" in ('{EncounterTypes.BehavioralHealth}') AND bh.""Medications"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsPrescription"",
                                pat.""FullName"" AS ""PatientName"", pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
                                 pat.""Guid""::text AS ""PatientGuid"", pr.""Guid""::text AS ""ProviderGuid"",
                                (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"",
                                (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",apt.""EncounterType"",
                                count(distinct pd.""PatientDocumentId"")  as ""PatientDocumentCount"" FROM ""Appointment"" apt
                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                LEFT JOIN ""PatientDocument"" pd ON  pd.""PatientId""=pat.""PatientId"" AND pd.""Active"" IS TRUE
                                LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                LEFT JOIN ""Encounter"" e ON e.""AppointmentId"" = apt.""AppointmentId"" AND e.""Active"" IS TRUE
                                LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
                                LEFT JOIN ""DentalEncounter"" de ON de.""AppointmentId"" = apt.""AppointmentId"" AND de.""Active"" IS TRUE
                                JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE AND pr.""ApprovalStatus"" IS TRUE
                                --JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
                                JOIN ""ProviderAvailability"" prl ON prl.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND prl.""Active"" IS TRUE
                                JOIN ""Location"" pral ON pral.""LocationId"" = prl.""LocationId"" AND pral.""Active"" IS TRUE
                               JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND cunpra.""Active"" IS TRUE
                                JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
                                JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId"" AND acc.""RoleId""=4 AND acc.""Active"" IS TRUE
                                JOIN ""Account"" prAcc ON prAcc.""ReferenceId"" = pr.""ProviderId"" AND prAcc.""RoleId""=3 AND prAcc.""Active"" IS TRUE
          	                    group by acc.""AccountId"" ,prAcc.""AccountId"", apt.""AppointmentId"", apt.""ProviderLocationId"",e.""Medications"",bh.""Medications"",de.""Medications"", apt.""ProviderId"",
                                apt.""PatientId"", ""VisitType"", ""PatientType"", ""AppointmentNo"", ""AppointmentDate"", ""AppointmentTime"", ""AppointmentNotes"", ""CouponId"", apt.""Amount"", apt.""Discount"",
                                apt.""Total"", apt.""Active"", apt.""CreatedBy"", apt.""CreatedDate"", apt.""ModifiedBy"", apt.""ModifiedDate"", apt.""Status"", ""EncounterType"", ""IsRemainder"", pr.""FullName"", pr.""Gender"", pr.""Age"",
                                cun.""CountryCode"",
                                apt.""EncounterType"" ,  pat.""FullName"" , pat.""Gender"" , pat.""Age"" , pat.""Email"" , pat.""Mobile"" ,
                               pat.""ThumbnailUrl"",  pat.""Guid"", pr.""Guid"",pr.""ThumbnailUrl"" ,apt.""EncounterType""
                                ) AS A {where} ";
            return this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
        }

        // <inheritdoc />
        public async Task<int> AddAsync(AppointmentModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var billId = 0;
            var appointment = new Appointment { };
            if (model.AppointmentId == null || model.AppointmentId == 0)
            {
                //var query1 = $@"SELECT COUNT(""AppointmentId"") FROM ""Appointment"" WHERE ""PatientId"" = '{model.PatientId}' AND ""ProviderId"" = '{model.ProviderId}' AND ""ProviderLocationId"" = '{model.ProviderLocationId}' AND ""AppointmentDate""::DATE = '{model.AppointmentDate:yyyy-MM-dd}'::DATE AND ""AppointmentTime"" = '{model.AppointmentTime}'  AND ""Active"" = TRUE AND ""SpecializationId"" = '{model.SpecializationId}'";

                var query1 = $@"SELECT COUNT(""AppointmentId"") FROM ""Appointment"" WHERE ""PatientId"" = '{model.PatientId}' AND ""ProviderId"" = '{model.ProviderId}' AND ""ProviderAvailabilityId"" = '{model.ProviderAvailabilityId}' AND ""AppointmentDate""::DATE = '{model.AppointmentDate:yyyy-MM-dd}'::DATE AND ""AppointmentTime"" = '{model.AppointmentTime}'  AND ""Active"" = TRUE AND ""SpecializationId"" = '{model.SpecializationId}'";

                var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>(query1);
                if (checkIf > 0)
                {
                    return -1;
                }

                //var prevAppointment = await this.unitOfWork.Appointments.FindAsync(m => m.PatientId == model.PatientId);
            }
            else if (model.AppointmentId > 0 || model.AppointmentId != null)
            {
                appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == model.AppointmentId);
                appointment.Active = true;
                appointment.ModifiedBy = model.CreatedBy;
                appointment.ModifiedDate = DateTime.Now;
                appointment.AppointmentDate = model.AppointmentDate;
                appointment.AppointmentTime = model.AppointmentTime;
                appointment.ProviderId = model.ProviderId;
                appointment.PatientId = model.PatientId;
                appointment.PatientFamilyId = model.PatientFamilyId;
                //ProviderLocationId = model.ProviderAvailabilityId;
                appointment.Amount = model.Amount; /// appointment amt ?
                appointment.Discount = model.Discount;
                appointment.DiscountInPercentage = model.DiscountInPercentage;
                appointment.CouponId = model.CouponId == 0 ? null : model.CouponId;
                appointment.Total = model.Total;
                appointment.PatientType = model.PatientType;
                appointment.AppointmentNotes = model.AppointmentNotes;
                appointment.DepartmentId = model.DepartmentId;
                //PaymentType = model.PaymentType;
                appointment.PaymentNumber = model.PaymentNumber;
                appointment.AppointmentNo = appointment.AppointmentNo;
                appointment.Status = "B";
                appointment.AppCharges = appointment.AppCharges;
                appointment.FollowUpForAppointmentId = model.FollowUpForAppointmentId;
                appointment.FollowUpForAdmissionId = appointment.FollowUpForAdmissionId;
                appointment.PaymentStatus = (bool)model.PaymentStatus;
                appointment.VisitTypeId = model.VisitTypeId;
                appointment.ChargeTypesId = model.ChargeTypesId;
                appointment.LocationId = model.LocationId;
                appointment.AppointmentTypeId = model.AppointmentTypeId;
                appointment.PayTypeId = model.PayTypeId;
                appointment.TokenNumber = model.TokenNumber;
                appointment.QueueStatusId = 7;
                appointment.SpecializationId = model.SpecializationId;
                appointment.ConsultationTypeId = model.ConsultationTypeId;
                appointment.ProviderAvailabilityId = model.ProviderAvailabilityId;
                appointment.AppointmentEndTime = model.AppointmentEndTime;
                appointment.IsSalucroAppointment = model.IsSalucroAppointment;
                appointment.DoctorSpecializationChargeModuleDetailsId = model.DoctorSpecializationChargeModuleDetailsId;
                appointment.OtherRemarks = model.OtherRemarks;
                appointment.AuthorityMasterId = model.AuthorityId;
                appointment.ReasonsId = model.ReasonId;
                appointment.Remarks = model.Remarks;
                appointment.PatientId = model.PatientId;
                appointment.PaymentType = (model.TypeOfPayment == "PartialPayment" || model.TypeOfPayment == "MultiPaymodes") ? 'P' : 'F';
                appointment.IsHealthCard = model.IsHealthCard;
                appointment.SessionId = model.SessionId;
                await this.unitOfWork.Appointments.UpdateAsync(appointment, transaction);
            }

            if (model.AppointmentId == 0)
            {
                try
                {
                    dynamic paymentType;
                    if ((bool)model.PaymentStatus)
                    {
                        if (model.TypeOfPayment == "PartialPayment" || model.TypeOfPayment == "MultiPaymodes")
                        {
                            paymentType = 'P';
                        }
                        else
                        {
                            paymentType = 'F';
                        }
                    }
                    else
                    {
                        paymentType = null;
                    }
                    appointment = new Appointment
                    {
                        Active = true,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        AppointmentDate = model.AppointmentDate,
                        AppointmentTime = model.AppointmentTime,
                        ProviderId = model.ProviderId,
                        PatientId = model.PatientId,
                        PatientFamilyId = model.PatientFamilyId,
                        //ProviderLocationId = model.ProviderAvailabilityId,
                        Amount = model.Amount, /// appointment amt ?
                        Discount = model.Discount,
                        DiscountInPercentage = model.DiscountInPercentage,
                        CouponId = model.CouponId == 0 ? null : model.CouponId,
                        Total = model.Total,
                        PatientType = model.PatientType,
                        VisitType = model.VisitType,
                        AppointmentNotes = model.AppointmentNotes,
                        WalletAmount = model.WalletAmount,
                        DepartmentId = model.DepartmentId,
                        //PaymentType = model.PaymentType,
                        ChargeType = model.ChargeType,
                        PaymentNumber = model.PaymentNumber,
                        AppointmentNo = await this.GetAppointmentNo(model.PatientType == 'I' ? "IP" : "OP"),
                        Status = "B",
                        AppCharges = model.AppCharges != 0 ? model.AppCharges : 0,
                        FollowUpForAppointmentId = model.FollowUpForAppointmentId,
                        FollowUpForAdmissionId = model.FollowUpForAdmissionId,
                        PaymentStatus = (bool)model.PaymentStatus,
                        VisitTypeId = model.VisitTypeId,
                        ChargeTypesId = model.ChargeTypesId,
                        LocationId = model.LocationId,
                        AppointmentTypeId = model.AppointmentTypeId,
                        PayTypeId = model.PayTypeId,
                        TokenNumber = model.TokenNumber,
                        QueueStatusId = 7,
                        SpecializationId = model.SpecializationId,
                        ConsultationTypeId = model.ConsultationTypeId,
                        ProviderAvailabilityId = model.ProviderAvailabilityId,
                        AppointmentEndTime = model.AppointmentEndTime,
                        IsSalucroAppointment = model.IsSalucroAppointment,
                        DoctorSpecializationChargeModuleDetailsId = model.DoctorSpecializationChargeModuleDetailsId,
                        OtherRemarks = model.OtherRemarks,
                        AuthorityMasterId = model.AuthorityId == 0 ? null : model.AuthorityId,
                        ReasonsId = model.ReasonId == 0 ? null : model.ReasonId,
                        Remarks = model.Remarks,
                        PaymentType = paymentType,
                        IsEmergency = model.VisitTypeId == 11 ? true : false,
                        IsHealthCard = model.IsHealthCard,
                        SessionId = model.SessionId
                    };


                    appointment.AppointmentId = await this.unitOfWork.Appointments.InsertAsync(appointment, transaction);


                }
                catch (Exception ex)
                {
                    ex.Message.ToString();
                }

            }

            var query2 = $@"SELECT COUNT(""AppointmentId"") FROM ""Appointment"" WHERE ""PatientId"" = '{model.PatientId}'";
            var checkIsNewPatient = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>(query2);

            var patientDetails = await this.unitOfWork.Patients.FindAsync(p => p.PatientId == model.PatientId);
            if (checkIsNewPatient > 1)
            {
                patientDetails.Salutation = patientDetails.Salutation;
                patientDetails.FirstName = patientDetails.FirstName;
                patientDetails.MiddleName = patientDetails.MiddleName;
                patientDetails.LastName = patientDetails.LastName;
                patientDetails.FullName = patientDetails.FullName;
                patientDetails.FatherOrHusband = patientDetails.FatherOrHusband;
                patientDetails.DateOfBirth = patientDetails.DateOfBirth;
                patientDetails.Age = patientDetails.Age;
                patientDetails.Gender = patientDetails.Gender;
                patientDetails.MaritalStatus = patientDetails.MaritalStatus;
                patientDetails.Email = patientDetails.Email;
                patientDetails.Mobile = patientDetails.Mobile;
                patientDetails.StreetAddress = patientDetails.StreetAddress;
                patientDetails.AddressLine2 = patientDetails.AddressLine2;
                patientDetails.City = patientDetails.City;
                patientDetails.State = patientDetails.State;
                patientDetails.Zipcode = patientDetails.Zipcode;
                patientDetails.CountryId = patientDetails.CountryId;
                patientDetails.ModifiedBy = patientDetails.ModifiedBy;
                patientDetails.ModifiedDate = DateTime.UtcNow;
                patientDetails.AadharNo = patientDetails.AadharNo;
                //patientDetails.patientDetailsReferredById = patientDetails.patientDetailsReferredById;
                patientDetails.ReferredByName = patientDetails.ReferredByName;
                //patientDetails.HWCpatientDetailsId = patientDetails.HWCpatientDetailsId;
                patientDetails.Education = patientDetails.Education;
                patientDetails.Occupation = patientDetails.Occupation;
                patientDetails.Nationality = patientDetails.Nationality;
                patientDetails.Religion = patientDetails.Religion;
                patientDetails.IdProofId = patientDetails.IdProofId;
                patientDetails.IdProofValue = patientDetails.IdProofValue;
                patientDetails.BloodGroup = patientDetails.BloodGroup;
                patientDetails.PaymentStatus = patientDetails.PaymentStatus != null ? patientDetails.PaymentStatus : patientDetails.PaymentStatus;
                patientDetails.PayTypeId = patientDetails.PayTypeId > 0 ? patientDetails.PayTypeId : patientDetails.PayTypeId;
                patientDetails.PaymentNumber = patientDetails.PaymentNumber;
                patientDetails.UMRNo = patientDetails.UMRNo;
                // patientDetails.TemppatientDetails = patientDetails.PaymentStatus == true ? false : patientDetails.TemppatientDetails;
                patientDetails.HowDidYouKnowId = patientDetails.HowDidYouKnowId;
                patientDetails.EducationId = patientDetails.EducationId;
                patientDetails.OccupationId = patientDetails.OccupationId;
                patientDetails.BirthMark1 = patientDetails.BirthMark1;
                patientDetails.BirthMark2 = patientDetails.BirthMark2;
                patientDetails.RelationType = patientDetails.RelationType;
                patientDetails.OccupationDetail = patientDetails.OccupationDetail;

                patientDetails.IsNewPatient = false;
                patientDetails.InsuranceCompanyId = patientDetails.InsuranceCompanyId;

                var updatedPatient = await this.unitOfWork.Patients.UpdateAsync(patientDetails, transaction);
            }
            var patient = await this.unitOfWork.Patients.FindAsync(m => m.PatientId == model.PatientId, transaction);
            //dynamic transactionDetails = !string.IsNullOrEmpty(model.Transaction) ? JsonConvert.DeserializeObject(model.Transaction) : null;
            decimal aptAmount = 0;
            decimal patAmount = 0;

            //begin-MasterBill
            var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.Appointment && x.ModuleId == appointment.AppointmentId); //need to check more
            if (getbillrecord != null)
            {
                getbillrecord.Total = (double)model.Amount;
                getbillrecord.Discount = (double)model.Amount - (double)model.AfterDiscount;
                getbillrecord.NetTotal = (double)model.AfterDiscount;
                getbillrecord.Rounding = (int)model.AfterDiscount - (double)model.AfterDiscount;
                await this.unitOfWork.MasterBill.UpdateAsync(getbillrecord);
            }
            if (getbillrecord == null)
            {
                var onebill = new MasterBill
                {
                    ReceiptAreaTypeId = (int)ReceiptAreaType.Appointment,//main module
                                                                         //ModuleId = (int)ReceiptAreaType.Labs, //sub module
                    ModuleId = appointment.AppointmentId, // module-main table id.
                    BillDate = DateTime.Now,
                    BillNumber = string.Format("{0:000000}", new Random().Next(0, 999999).ToString()),
                    BillStatusTypeId = (int)BillStatusType.Not_Generated,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    Active = true,
                    PatientId = model.PatientId,
                    Total = (double)model.Amount,
                    Discount = (double)model.Amount - (double)model.AfterDiscount,
                    NetTotal = (double)model.AfterDiscount,
                    Rounding = (int)model.AfterDiscount - (double)model.AfterDiscount,
                    LocationId = model.LocationId
                };
                onebill.MasterBillId = await this.unitOfWork.MasterBill.InsertAsync(onebill, transaction);
                billId = onebill.MasterBillId;
                if (onebill.MasterBillId == 0)
                {
                    transaction.Rollback();
                    return -5;
                }
            }
            //end-MasterBill
            if (model.PaymentStatus == false && model.SalucroStatusCode != 1201)
            {
                transaction.Commit();
                return appointment.AppointmentId;
            }
            else
            {
                decimal amount = (decimal)model.Total;

                if (patient.PaymentStatus != true)
                {
                    // wrote for partial payments
                    //aptAmount = amount > (decimal)model.PatientRegistrationAmount ? amount + (decimal)model.PatientRegistrationAmount - (decimal)model.PatientRegistrationAmount : 0;
                    //patAmount = amount > (decimal)model.PatientRegistrationAmount ? (decimal)model.PatientRegistrationAmount : amount;

                    aptAmount = amount;
                    patAmount = (decimal)model.PatientRegistrationAmount;// not assiging
                }
                else
                {
                    aptAmount = amount;
                    patAmount = (decimal)model.PatientRegistrationAmount;
                }
                // transaction for appointment
                var commonTransaction = new AppointmentTransaction
                {
                    AppointmentId = appointment.AppointmentId, // respective Id
                    Transaction = model.Transaction ?? "",
                    TransactionDate = DateTime.Now,
                    TransactionId = model.TransactionId ?? await this.appointmentTransactionsServices.GetATransactionId(),
                    VoucherNumber = model.SalucroStatusCode == 1201 ? null : await this.appointmentTransactionsServices.GetVoucherNumber(),
                    BankReference = "",
                    BankCode = "",
                    Active = true,
                    PaymentId = 0,
                    PaymentModeId = 1,
                    SettledAmount = aptAmount,
                    SalucroStatusCode = model.SalucroStatusCode,
                    SalucroTransactionId = model.SalucroTransactionId,
                    CreatedBy = (int)model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    LocationId = model.LocationId,
                    ReceiptTypeId = (int)ReceiptType.Cash, // credit
                    ReceiptAreaTypeId = (int)ReceiptAreaType.Appointment,
                    PatientId = model.PatientId,
                    PayStatus = (model.TypeOfPayment == "PartialPayment" || model.TypeOfPayment == "MultiPaymodes") ? 'P' : 'F'
                };
                commonTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTransaction, transaction);
                if (commonTransaction.AppointmentTransactionId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }

                if (model.SalucroStatusCode != 1201)
                {
                    var receipt = new Receipt ///receipt  while pat reg + appointment
                    {
                        Active = true,
                        Cost = (double)aptAmount,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        IsAdvance = false,
                        IsRefunded = false,
                        PayTypeId = (int)model.PayTypeId,
                        PaymentDetails = model.PaymentNumber,
                        IsAppointmentReceipt = true,
                        ReceiptTypeId = ReceiptType.Cash,    // credit
                                                             // PatientRegistrationDetailId = registration  // we r deleting this col
                        ReceiptAreaTypeId = ReceiptAreaType.Appointment,
                        RespectiveId = appointment.AppointmentId,
                        TransactionId = commonTransaction.AppointmentTransactionId,
                        MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : billId
                    };

                    receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt, transaction);
                    if (receipt.ReceiptId == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                    //begin-to update bill status as genereated.
                    var allreceiptforbill = await this.unitOfWork.Receipt.FindAllAsync(x => x.MasterBillId == receipt.MasterBillId);
                    allreceiptforbill.ToList();
                    var receiptcostsum = 0.0;
                    foreach (var item in allreceiptforbill.ToList())
                    {
                        receiptcostsum += item.Cost;
                    }
                    var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == receipt.MasterBillId);
                    if (receiptcostsum == getbill.NetTotal)
                    {
                        getbill.BillStatusTypeId = (int)BillStatusType.Generated;
                        getbill.ModifiedBy = (int)model.CreatedBy;
                        getbill.ModifiedDate = DateTime.Now;
                        await this.unitOfWork.MasterBill.UpdateAsync(getbill);
                    }
                    //end-to update bill status as genereated.
                }
            }
            if (patient.PaymentStatus != true) //// we need to current ps status also
            {
                //begin-MasterBill
                var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.PatientRegistration && x.ModuleId == model.PatientId); //need to check more
                if (getbill != null)
                {
                    getbill.Total = (double)patAmount;
                    getbill.NetTotal = (double)model.PatientTotal;
                    getbill.Discount = (double)model.PatientDiscountInRupees;
                    getbill.Rounding = (int)patAmount - (double)patAmount;
                    await this.unitOfWork.MasterBill.UpdateAsync(getbill);
                }
                if (getbill == null)
                {
                    var onebill = new MasterBill
                    {
                        ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,//main module
                                                                                     // ModuleId = (int)ReceiptAreaType.Labs, //sub module
                        ModuleId = patient.PatientId, // module-main table id.
                        BillDate = DateTime.Now,
                        BillNumber = string.Format("{0:000000}", new Random().Next(0, 999999).ToString()),
                        BillStatusTypeId = (int)BillStatusType.Not_Generated,
                        CreatedBy = (int)model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        Active = true,
                        PatientId = model.PatientId,
                        Total = (double)patAmount,
                        NetTotal = (double)model.PatientTotal,
                        Discount = (double)model.PatientDiscountInRupees,
                        Rounding = (int)patAmount - (double)patAmount,
                        LocationId = model.LocationId
                    };
                    onebill.MasterBillId = await this.unitOfWork.MasterBill.InsertAsync(onebill, transaction);
                    billId = onebill.MasterBillId;
                    if (onebill.MasterBillId == 0)
                    {
                        transaction.Rollback();
                        return -5;
                    }
                }
                else
                {
                    getbill.Total = (double)patAmount;
                    getbill.Discount = (double)model.PatientDiscountInRupees;
                    getbill.NetTotal = (double)model.PatientTotal;

                    var res = await this.unitOfWork.MasterBill.UpdateAsync(getbill, transaction);
                    //end-MasterBill
                    if (res == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }
                var masterBillId = getbill != null ? getbill.MasterBillId : billId;
                var receiptId = await this.UpadtePatientPayment(model.PatientId, patAmount, model.CreatedBy, model.CreatedBy, model.LocationId, (int)model.PayTypeId, model.PaymentNumber, model.Transaction, model.TransactionId, model.SalucroStatusCode, model.SalucroTransactionId, appointment.AppointmentId, masterBillId, (decimal)model.PatientDiscountInRupees, (decimal)model.PatientTotal, (decimal)model.PatientDiscountInPercentage);


                patientDetails.PaymentStatus = true;
                patientDetails.PaymentStatus = model.PaymentStatus == true ? model.PaymentStatus : patient.PaymentStatus;
                patientDetails.PayTypeId = model.PayTypeId > 0 ? model.PayTypeId : patient.PayTypeId;
                patientDetails.PaymentNumber = model.PaymentNumber != null ? model.PaymentNumber : patient.PaymentNumber;
                patientDetails.UMRNo = model.PaymentStatus == true && patient.TempPatient == true ? await this.GetLatestUMRNo() : patient.UMRNo;
                patientDetails.TempPatient = model.PaymentStatus == true ? false : patient.TempPatient;
                patientDetails.Amount = model.PaymentStatus == true ? model.PatientRegistrationAmount : patient.Amount;
                patientDetails.Total = model.PaymentStatus == true ? model.PatientTotal : patient.Total;
                patientDetails.DiscountInPercentage = model.PaymentStatus == true ? model.PatientDiscountInPercentage : patient.DiscountInPercentage;
                patientDetails.DiscountInRupees = model.PaymentStatus == true ? model.PatientDiscountInRupees : patient.DiscountInPercentage;
                var patientStatus = await this.unitOfWork.Patients.UpdateAsync(patientDetails, transaction);
                if (receiptId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }
            }

            transaction.Commit();
            return appointment.AppointmentId;
        }
        public 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 limit 1");
            if (umrNo != null)
            {
                var text = Regex.Replace(umrNo, @"[\d-]", string.Empty);
                var number = umrNo.Replace(text, string.Empty);
                var sequence = Convert.ToInt64(number) + 1;
                return $@"{text}{sequence}";
            }
            else
            {
                return $@"UMR400000";
            }
        }
        /// <inheritdoc />
        public async Task<Tuple<int, bool, string>> AddAsync(int appointmentLogId, string transactionId, string transactionDetails, string bankReference, string bankCode, long paymentId, int salucroStatusCode, string salucroTransactionId)//model.PaymentNumber, model.Transaction, model.TransactionId, (int) model.SalucroStatusCode, model.SalucroTransactionId
        {
            using (var transaction = this.unitOfWork.BeginTransaction())
            {
                var appointmentTransaction = await this.unitOfWork.AppointmentTransactions.FindAsync(m => m.TransactionId == transactionId && m.Active, transaction);
                if (appointmentTransaction != null && appointmentTransaction.AppointmentTransactionId > 0)
                {
                    return new Tuple<int, bool, string>(appointmentTransaction.AppointmentId, true, null);
                }

                var appointmentLog = await this.unitOfWork.AppointmentLogs.FindAsync(m => m.AppointmentLogId == appointmentLogId, transaction);
                if (appointmentLog == null || appointmentLog.AppointmentLogId == 0)
                {
                    // transaction.Rollback();
                    return new Tuple<int, bool, string>(0, false, $"Appointment log not found for '{appointmentLogId}'.");
                }

                var symptoms = appointmentLog.AppointmentNotes;
                appointmentLog.AppointmentNotes = null;

                //Delete code
                var where = $@"WHERE ""PatientId"" = '{appointmentLog.PatientId}' AND ""ProviderId"" = '{appointmentLog.ProviderId}' AND ""ProviderAvailabilityId"" = '{appointmentLog.ProviderAvailabilityId}' AND ""AppointmentDate""::DATE = '{appointmentLog.AppointmentDate:yyyy-MM-dd}'::DATE AND ""AppointmentTime"" = '{appointmentLog.AppointmentTime}' AND ""Status"" != 'C' ";
                var checkIf = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>($@"SELECT COUNT(""AppointmentId"") FROM ""Appointment"" {where}", null, transaction);
                if (checkIf > 0)
                {
                    transaction.Rollback();
                    return new Tuple<int, bool, string>(-1, false, $"Appointment has already been exist with Provider ID : '{appointmentLog.ProviderId}', Provider Availability ID : '{appointmentLog.ProviderAvailabilityId}', Appointment date : '{appointmentLog.AppointmentDate:yyyy-MM-dd}' and Appointment time : '{appointmentLog.AppointmentTime}'.");
                }

                //var prevAppointment = await this.unitOfWork.Appointments.FindAsync(m => m.PatientId == appointmentLog.PatientId);

                var appointment = new Appointment
                {
                    Active = true,
                    CreatedBy = appointmentLog.CreatedBy,
                    CreatedDate = DateTime.Now,
                    AppointmentDate = appointmentLog.AppointmentDate,
                    AppointmentTime = appointmentLog.AppointmentTime,
                    ProviderId = appointmentLog.ProviderId,
                    PatientId = appointmentLog.PatientId,
                    //ProviderLocationId = appointmentLog.ProviderLocationId,
                    Amount = appointmentLog.Amount,
                    AppCharges = appointmentLog.AppCharges,
                    WalletAmount = appointmentLog.WalletAmount,
                    Discount = appointmentLog.Discount,
                    CouponId = appointmentLog.CouponId == 0 ? null : appointmentLog.CouponId,
                    Total = appointmentLog.Total,
                    PatientType = appointmentLog.PatientType,
                    VisitType = appointmentLog.VisitType,
                    ChargeType = appointmentLog.ChargeType,
                    AppointmentNotes = appointmentLog.AppointmentNotes,
                    AppointmentNo = await this.GetAppointmentNo(appointmentLog.PatientType == 'I' ? "IP" : "OP"),
                    Status = "B",
                    //PaymentType = appointmentLog.PaymentType,
                    PaymentNumber = transactionId,
                    PatientFamilyId = appointmentLog.PatientFamilyId == 0 ? null : appointmentLog.PatientFamilyId,
                    VisitTypeId = appointmentLog.VisitTypeId,
                    ChargeTypesId = appointmentLog.ChargeTypesId,
                    LocationId = appointmentLog.LocationId,
                    AppointmentTypeId = appointmentLog.AppointmentTypeId,
                    PayTypeId = appointmentLog.PayTypeId,
                    QueueStatusId = 7,
                    TokenNumber = appointmentLog.TokenNumber,
                    PaymentStatus = salucroStatusCode == 1200 ? true : false,
                    DepartmentId = appointmentLog.DepartmentId,
                    SpecializationId = appointmentLog.SpecializationId,
                    ConsultationTypeId = appointmentLog.ConsultationTypeId,
                    ProviderAvailabilityId = appointmentLog.ProviderAvailabilityId,
                    DoctorSpecializationChargeModuleDetailsId = appointmentLog.DoctorSpecializationChargeModuleDetailsId,
                    SessionId = appointmentLog.SessionId
                };

                appointment.AppointmentId = await this.unitOfWork.Appointments.InsertAsync(appointment, transaction);

                if (appointment.AppointmentId > 0 && !string.IsNullOrEmpty(symptoms))
                {
                    var appointmentSymptom = new AppointmentSymptom
                    {
                        Active = true,
                        CreatedBy = appointmentLog.CreatedBy,
                        CreatedDate = DateTime.Now,
                        Symptoms = symptoms,
                        AppointmentId = appointment.AppointmentId
                    };

                    appointmentSymptom.AppointmentSymptomId = await this.unitOfWork.AppointmentSymptoms.InsertAsync(appointmentSymptom);
                }

                if (appointment.AppointmentId == 0)
                {
                    transaction.Rollback();
                    return new Tuple<int, bool, string>(0, false, $"Error occurred while inserting appointment for Appointment log ID : '{appointmentLogId}'.");
                }

                try
                {
                    this.AddSupportLogAsync(appointment.AppointmentId);
                }
                catch (Exception)
                {
                    // ignore
                }
                dynamic details = JObject.Parse(transactionDetails);
                dynamic paymentResponse = details["payment_response"];
                string txnMode = paymentResponse["txnMode"];
                string acquirerCode = paymentResponse["acquirerCode"];
                string payment_type = paymentResponse["payment_type"];
                appointmentTransaction = new AppointmentTransaction
                {
                    AppointmentId = appointment.AppointmentId,
                    Active = true,
                    Transaction = transactionDetails,
                    TransactionId = transactionId,
                    BankCode = bankCode,
                    BankReference = bankReference,
                    TransactionDate = DateTime.Now,
                    PaymentModeId = transactionDetails == "AMEX" ? 2 : 1,
                    PaymentId = paymentId,
                    SettledAmount = appointmentLog.Total,
                    Percentage = appointmentLog.Percentage,
                    SalucroStatusCode = salucroStatusCode,
                    SalucroTransactionId = salucroTransactionId,
                    CreatedBy = appointmentLog.CreatedBy,
                    CreatedDate = appointmentLog.CreatedDate,
                    LocationId = appointmentLog.LocationId,
                    ReceiptTypeId = (int)ReceiptType.Cash,
                    ReceiptAreaTypeId = (int)ReceiptAreaType.Appointment,
                    VoucherNumber = salucroStatusCode == 1200 ? await this.appointmentTransactionsServices.GetVoucherNumber() : null,
                    SendedVia = txnMode != null ? txnMode : payment_type != null ? payment_type : "",
                    ReceivedIn = acquirerCode != null ? acquirerCode : "",
                    StatusCheckInProgress = false,
                    PatientId = appointmentLog.PatientId,
                    PayStatus = appointment.PaymentType
                };

                appointmentTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(appointmentTransaction, transaction);
                if (appointmentTransaction.AppointmentTransactionId == 0)
                {
                    transaction.Rollback();
                    return new Tuple<int, bool, string>(0, false, $"Error occurred while inserting appointment transactions for Appointment log ID : '{appointmentLogId}'.");
                }

                if (appointment.PaymentStatus == true)
                {
                    var receipt = new Receipt ///receipt  while pat reg + appointment
                    {

                        Active = true,
                        Cost = Convert.ToDouble(appointment.Total),
                        CreatedBy = appointment.CreatedBy,
                        CreatedDate = DateTime.Now,
                        IsAdvance = false,
                        IsRefunded = false,
                        PayTypeId = (int)appointment.PayTypeId,
                        PaymentDetails = appointment.PaymentNumber,
                        IsAppointmentReceipt = true,
                        ReceiptTypeId = ReceiptType.Cash,    // credit
                                                             // PatientRegistrationDetailId = registration  // we r deleting this col
                        ReceiptAreaTypeId = ReceiptAreaType.Appointment,
                        RespectiveId = appointment.AppointmentId,
                        TransactionId = appointmentTransaction.AppointmentTransactionId
                        //MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                    };

                    receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt, transaction);

                    if (receipt.ReceiptId == 0)
                    {
                        transaction.Rollback();
                        return new Tuple<int, bool, string>(0, false, $"Error occurred while inserting appointment receipt for Appointment ID : '{appointment.AppointmentId}'.");
                    }
                }

                var patient = await this.unitOfWork.Patients.FindAsync(m => m.PatientId == appointmentLog.PatientId);

                if (patient.PaymentStatus == false && appointmentLog.PatientRegistrationCharges >= 0)
                {
                    var patientTransaction = new AppointmentTransaction
                    {
                        AppointmentId = appointmentLog.PatientId, // respective Id

                        Transaction = transactionDetails,
                        TransactionDate = DateTime.Now,
                        TransactionId = await this.appointmentTransactionsServices.GetATransactionId(),
                        VoucherNumber = salucroStatusCode == 1200 ? await this.appointmentTransactionsServices.GetVoucherNumber() : null,
                        BankReference = bankReference,
                        BankCode = bankCode,
                        Active = true,
                        PaymentModeId = transactionDetails == "AMEX" ? 2 : 1,
                        PaymentId = paymentId,
                        SettledAmount = appointmentLog.PatientRegistrationCharges,
                        SalucroStatusCode = salucroStatusCode,
                        SalucroTransactionId = salucroTransactionId,
                        CreatedBy = appointmentLog.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = appointmentLog.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Cash, // credit
                        ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,
                        SendedVia = appointmentTransaction.SendedVia,
                        ReceivedIn = appointmentTransaction.ReceivedIn,
                        StatusCheckInProgress = false,
                        PatientId = appointmentLog.PatientId,
                        PayStatus = 'F'
                    };
                    patientTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(patientTransaction, transaction);

                    if (patientTransaction.AppointmentTransactionId == 0)
                    {
                        transaction.Rollback();
                        return new Tuple<int, bool, string>(0, false, $"Error occurred while inserting patient transactions for Appointment log ID : '{appointmentLogId}'.");
                    }

                    if (appointment.PaymentStatus == true)
                    {
                        var umrNo = await this.patientService.GetLatestUMRNo();
                        var patientQuery = "";
                        if (patient.TempPatient == true)
                        {
                            patientQuery = $@"UPDATE ""Patient"" SET ""PaymentStatus"" = true,""TempPatient"" = false, ""PayTypeId"" = '{appointment.PayTypeId}',""PaymentNumber"" = '{appointment.PaymentNumber}', ""UMRNo""='{umrNo}', ""ModifiedBy"" = {appointment.CreatedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""PatientId""= {appointment.PatientId}";
                        }
                        else
                        {
                            patientQuery = $@"UPDATE ""Patient"" SET ""PaymentStatus"" = true,""TempPatient"" = false, ""PayTypeId"" = '{appointment.PayTypeId}',""PaymentNumber"" = '{appointment.PaymentNumber}', ""ModifiedBy"" = {appointment.CreatedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""PatientId""= {appointment.PatientId}";
                        }
                        var result = await this.unitOfWork.Current.ExecuteAsync(patientQuery, transaction);
                        if (result <= 0)
                        {
                            transaction.Rollback();
                            return new Tuple<int, bool, string>(0, false, $"Issue while updating the patient payment details : '{appointment.PatientId}'.");
                        }

                        var receipt = new Receipt ///receipt  while pat reg + appointment
                        {

                            Active = true,
                            Cost = Convert.ToDouble(appointmentLog.PatientRegistrationCharges),
                            CreatedBy = appointment.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)appointment.PayTypeId,
                            PaymentDetails = appointment.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.PatientRegistration,
                            RespectiveId = appointment.PatientId,
                            TransactionId = patientTransaction.AppointmentTransactionId
                            //MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                        };

                        receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt, transaction);

                        if (receipt.ReceiptId == 0)
                        {
                            transaction.Rollback();
                            return new Tuple<int, bool, string>(0, false, $"Error occurred while inserting patient receipt for Patient ID : '{appointment.PatientId}'.");
                        }
                    }
                }
                //if (patient.ReferralBy != null && prevAppointment == null)
                //{
                //    var wallet = new WalletModel
                //    {
                //        PatientId = Convert.ToInt32(patient.ReferralBy),
                //        CreditedAmount = 30.00,
                //        CreditedFor = patient.FullName + " booked an appointment at first time"
                //    };

                //    await this.walletServices.AddAsync(wallet);
                //}

                if (appointmentLog.WalletAmount != null)
                {
                    var wallet = new WalletModel
                    {
                        PatientId = appointmentLog.PatientId,
                        DebitedAmount = (double?)appointmentLog.WalletAmount,
                        CreditedFor = "Used for book an appointment"
                    };

                    await this.walletServices.AddAsync(wallet);
                }

                transaction.Commit();
                return new Tuple<int, bool, string>(appointment.AppointmentId, false, null);
            }
        }

        /// <inheritdoc />
        public async Task<int> RescheduleAsync(int appointmentId, DateTime appointmentDate, TimeSpan appointmentTime, TimeSpan appointmentEndTime, string appointmentNotes, int modifiedBy, int providerId, int providerAvailabilityId, int consultationTypeId, int? departmentId, int locationId, int tokenNumber, int? specializationId)
        {
            try
            {
                var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == appointmentId);
                appointment.Status = "R";
                appointment.OldAppointmentDate = appointment.AppointmentDate;
                appointment.OldAppointmentTime = appointment.AppointmentTime;
                appointment.AppointmentDate = appointmentDate;
                appointment.AppointmentTime = appointmentTime;
                appointment.AppointmentNotes = appointmentNotes;
                appointment.ModifiedBy = modifiedBy;
                appointment.ProviderId = providerId;
                //appointment.ProviderLocationId = providerLocationId;
                appointment.ProviderAvailabilityId = providerAvailabilityId;
                appointment.ConsultationTypeId = consultationTypeId;
                //appointment.DepartmentId = departmentId;
                appointment.ModifiedDate = DateTime.UtcNow;
                appointment.LocationId = locationId;
                appointment.AppointmentTypeId = appointment.AppointmentTypeId;
                appointment.TokenNumber = tokenNumber;
                appointment.SpecializationId = specializationId;
                appointment.AppointmentEndTime = appointmentEndTime;

                return await this.unitOfWork.Appointments.UpdateAsync(appointment);
            }
            catch (Exception e)
            {
                return 0;
            }
        }

        /// <inheritdoc />
        public async Task<int> UpdatePatientTypeAsync(int appointmentId, int modifiedBy, char? patientType, int visitTypeId)
        {
            var query = $@"UPDATE ""Appointment"" SET ""VisitType"" = '{patientType}',""VisitTypeId"" = '{visitTypeId}',""PatientType"" = '{patientType}', ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AppointmentId""= {appointmentId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<int> UpdatePaymentStatusAsync(PatientPaymentModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var billId = 0;
            // var processing_id = PaymentHelper.GenerateTransactionId();
            //transaction for app
            //begin-MasterBill
            var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.Appointment && x.ModuleId == model.AppointmentId); //need to check more


            if (getbillrecord == null)
            {
                var onebill = new MasterBill
                {
                    ReceiptAreaTypeId = (int)ReceiptAreaType.Appointment,//main module
                                                                         //ModuleId = (int)ReceiptAreaType.Labs, //sub module
                    ModuleId = model.AppointmentId, // module-main table id.
                    BillDate = DateTime.Now,
                    BillNumber = string.Format("{0:000000}", new Random().Next(0, 999999).ToString()),
                    BillStatusTypeId = (int)BillStatusType.Not_Generated,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    Active = true,
                    PatientId = model.PatientId,
                    Total = (double)model.Amount,
                    Discount = (double)model.Amount - (double)model.AppointmentDiscountInRupees,
                    NetTotal = (double)model.AppointmentTotal,
                    Rounding = (int)model.AppointmentTotal - (double)model.AppointmentTotal,
                    LocationId = model.LocationId
                };
                onebill.MasterBillId = await this.unitOfWork.MasterBill.InsertAsync(onebill, transaction);
                billId = onebill.MasterBillId;
                if (onebill.MasterBillId == 0)
                {
                    transaction.Rollback();
                    return -5;
                }
            }

            //end-MasterBill
            var commonTransaction = new AppointmentTransaction
            {
                AppointmentId = model.AppointmentId, // respective Id

                Transaction = model.Transaction ?? "",
                TransactionDate = DateTime.Now,
                TransactionId = model.TransactionId ?? await this.appointmentTransactionsServices.GetATransactionId(),
                VoucherNumber = model.SalucroStatusCode == 1201 ? null : await this.appointmentTransactionsServices.GetVoucherNumber(),
                BankReference = "",
                BankCode = "",
                Active = true,

                PaymentId = 0,
                PaymentModeId = 1,
                // RefundId=null,
                // PaymentStatusId=null,
                SettledAmount = model.AppointmentTotal,
                //PayoutId=null,
                //SettledDate=null,
                //  Percentage = appointmentLog.Percentage,
                //SalucroStatusCode = salucroStatusCode,
                // SalucroTransactionId = salucroTransactionId,
                CreatedBy = (int)model.CreatedBy,
                CreatedDate = DateTime.Now,

                LocationId = model.LocationId,
                ReceiptTypeId = (int)ReceiptType.Cash, // credit
                ReceiptAreaTypeId = (int)ReceiptAreaType.Appointment,
                SalucroStatusCode = model.SalucroStatusCode,
                SalucroTransactionId = model.SalucroTransactionId,
                PatientId = model.PatientId,
                PayStatus = (model.TypeOfPayment == "PartialPayment" || model.TypeOfPayment == "MultiPaymodes") ? 'P' : 'F'

            };
            commonTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTransaction, transaction);
            if (commonTransaction.AppointmentTransactionId == 0)
            {
                transaction.Rollback();
                return 0;
            }
            if (model.SalucroStatusCode != 1201)
            {
                var appReceipt = new Receipt
                {
                    Active = true,
                    Cost = Convert.ToDouble(model.AppointmentTotal),
                    CreatedBy = (int)model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    IsAdvance = false,
                    IsRefunded = false,
                    PayTypeId = (int)model.PayTypeId,
                    PaymentDetails = model.PaymentNumber,
                    IsAppointmentReceipt = true,
                    ReceiptTypeId = ReceiptType.Cash,    // credit
                                                         // PatientRegistrationDetailId = registration
                    ReceiptAreaTypeId = ReceiptAreaType.Appointment,
                    RespectiveId = model.AppointmentId,
                    TransactionId = commonTransaction.AppointmentTransactionId,
                    MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : billId
                };
                appReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(appReceipt, transaction);
                if (appReceipt.ReceiptId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }
                //begin-to update bill status as genereated.
                var allreceiptforbill = await this.unitOfWork.Receipt.FindAllAsync(x => x.MasterBillId == appReceipt.MasterBillId);
                allreceiptforbill.ToList();
                var receiptcostsum = 0.0;
                foreach (var item in allreceiptforbill.ToList())
                {
                    receiptcostsum += item.Cost;
                }
                var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == appReceipt.MasterBillId);
                if (receiptcostsum == getbill.NetTotal)
                {
                    getbill.BillStatusTypeId = (int)BillStatusType.Generated;
                    getbill.ModifiedBy = (int)model.CreatedBy;
                    getbill.ModifiedDate = DateTime.Now;
                    await this.unitOfWork.MasterBill.UpdateAsync(getbill);
                }
                //end-to update bill status as genereated.
            }

            //var query = $@"UPDATE ""Appointment"" SET ""OtherRemarks""='{model.OtherRemarks}',""ProviderId"" = {model.ProviderId}, ""AppointmentDate"" = {model.AppointmentDate}, ""Amount""={model.Amount},""Discount""={model.Discount},""Total""={model.Total},""PaymentStatus"" = {model.PaymentStatus},""PayTypeId"" = '{model.PayTypeId}',""PaymentNumber"" = '{model.PaymentNumber}',""IsSalucroAppointment"" = {model.IsSalucroAppointment}, ""ModifiedBy"" = {model.ModifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AppointmentId""= {model.AppointmentId}";
            //var updatesucess = await this.unitOfWork.Current.ExecuteAsync(query, transaction);


            var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == model.AppointmentId);
            appointment.Active = true;
            appointment.OldAppointmentDate = appointment.AppointmentDate;
            appointment.OldAppointmentTime = appointment.AppointmentTime;
            appointment.ModifiedBy = model.ModifiedBy;
            appointment.ModifiedDate = DateTime.Now;
            appointment.AppointmentDate = model.AppointmentDate;
            appointment.AppointmentTime = model.AppointmentTime;
            appointment.ProviderId = model.ProviderId;
            appointment.PatientId = model.PatientId;
            appointment.PatientFamilyId = model.PatientFamilyId;
            //ProviderLocationId = model.ProviderAvailabilityId;
            appointment.Amount = model.Amount; /// appointment amt ?
            appointment.Discount = model.Discount;
            appointment.CouponId = model.CouponId == 0 ? null : model.CouponId;
            appointment.Total = model.AppointmentTotal;
            appointment.PatientType = model.PatientType;
            appointment.AppointmentNotes = model.AppointmentNotes;
            appointment.DepartmentId = model.DepartmentId;
            //PaymentType = model.PaymentType;
            appointment.PaymentNumber = model.PaymentNumber;
            appointment.AppointmentNo = appointment.AppointmentNo;
            appointment.Status = (appointment.ProviderId != model.ProviderId && appointment.AppointmentTime != model.AppointmentTime && appointment.SpecializationId != model.SpecializationId && appointment.AppointmentDate != model.AppointmentDate) ? "R" : "B";
            appointment.AppCharges = appointment.AppCharges;
            appointment.FollowUpForAppointmentId = model.FollowUpForAppointmentId;
            appointment.FollowUpForAdmissionId = appointment.FollowUpForAdmissionId;
            appointment.PaymentStatus = model.PaymentStatus;
            appointment.VisitTypeId = model.VisitTypeId;
            appointment.ChargeTypesId = model.ChargeTypesId;
            appointment.LocationId = model.LocationId;
            appointment.AppointmentTypeId = model.AppointmentTypeId;
            appointment.PayTypeId = model.PayTypeId;
            appointment.TokenNumber = model.TokenNumber;
            appointment.QueueStatusId = 7;
            appointment.SpecializationId = model.SpecializationId;
            appointment.ConsultationTypeId = model.ConsultationTypeId;
            appointment.ProviderAvailabilityId = model.ProviderAvailabilityId;
            appointment.AppointmentEndTime = model.AppointmentEndTime;
            appointment.IsSalucroAppointment = model.IsSalucroAppointment;
            appointment.DoctorSpecializationChargeModuleDetailsId = model.DoctorSpecializationChargeModuleDetailsId;
            appointment.OtherRemarks = model.OtherRemarks;
            appointment.AuthorityMasterId = model.AuthorityId;
            appointment.ReasonsId = model.ReasonId;
            appointment.Remarks = model.Remarks;
            appointment.PatientId = model.PatientId;
            appointment.PaymentType = (model.TypeOfPayment == "PartialPayment" || model.TypeOfPayment == "MultiPaymodes") ? 'P' : 'F';
            appointment.AppointmentId = await this.unitOfWork.Appointments.UpdateAsync(appointment, transaction);

            if (appointment.AppointmentId == 0)
            {
                transaction.Rollback();
                return 0;
            }
            if (model.PaymentStatus)
            {
                var auditLogModel = new AuditLog
                {
                    AccountId = model.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow,
                    LogDescription = $"For Patient: {model.PatientName}, payment charges has been <b>Updated</b> successfully",
                    LocationId = model.LocationId
                };
                await this.unitOfWork.AuditLogs.InsertAsync(auditLogModel);
            }

            var patient = await this.unitOfWork.Patients.FindAsync(m => m.PatientId == model.PatientId, transaction);

            //if (patient.PaymentStatus == false)
            //{
            //    var receiptId = await this.UpadtePatientPayment(model.PatientId, (decimal)model.PatientRegistrationAmount, model.CreatedBy, (int)model.ModifiedBy, model.LocationId, (int)model.PayTypeId, model.PaymentNumber, null, null, null, null, model.AppointmentId);

            //    if (receiptId == 0)
            //    {
            //        transaction.Rollback();
            //        return 0;
            //    }


            //}

            if (patient.PaymentStatus == true || patient.PaymentStatus == false)
            {
                var updatedPatientId = await this.UpadtePatientDetailsAsync(model);
                if (updatedPatientId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }
            }

            transaction.Commit();

            //return appReceipt.ReceiptId;
            return 1;
        }

        private async Task<int> UpadtePatientPayment(int patientId, decimal patAmount, int createdBy, int modifiedBy, int locationId, int payTypeId, string paymentNumber, string paymentTransaction, string transactionId, int? salucroStatusCode, string salucroTransactionId, int appointmentId, int masterBillId, decimal patientDiscountInRupees, decimal patientTotal, decimal patientDiscountInPercentage)
        {
            // var transaction = this.unitOfWork.BeginTransaction();
            var patient = await this.unitOfWork.Patients.FindAsync(m => m.PatientId == patientId);
            var umrNo = await this.patientService.GetLatestUMRNo();
            var id = 0;
            var commonTrans = new AppointmentTransaction//
            {
                AppointmentId = patientId, // respective Id
                Transaction = paymentTransaction ?? "",
                TransactionDate = DateTime.Now,
                TransactionId = transactionId ?? await this.appointmentTransactionsServices.GetATransactionId(),
                VoucherNumber = salucroStatusCode == 1201 ? null : await this.appointmentTransactionsServices.GetVoucherNumber(),
                BankReference = "",
                BankCode = "",
                Active = true,
                PaymentId = 0,
                PaymentModeId = 1,
                SettledAmount = patientTotal,
                SalucroStatusCode = salucroStatusCode,
                SalucroTransactionId = salucroTransactionId,
                CreatedBy = (int)createdBy,
                CreatedDate = DateTime.Now,
                ReceiptTypeId = (int)ReceiptType.Cash, // credit
                ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,
                LocationId = locationId,
                PatientId = patientId,
                PayStatus = 'F'
            };
            commonTrans.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTrans);
            id = commonTrans.AppointmentTransactionId;
            if (commonTrans.AppointmentTransactionId == 0)
            {
                // transaction.Rollback();
                return 0;
            }
            if (salucroStatusCode != 1201)
            {
                var regReceipt = new Receipt
                {
                    Active = true,
                    Cost = Decimal.ToDouble(patientTotal),
                    CreatedBy = (int)createdBy,
                    CreatedDate = DateTime.Now,
                    IsAdvance = false,
                    IsRefunded = false,
                    PayTypeId = (int)payTypeId,
                    PaymentDetails = paymentNumber,
                    ReceiptTypeId = ReceiptType.Cash,    // credit
                                                         // PatientRegistrationDetailId = registration
                    ReceiptAreaTypeId = ReceiptAreaType.PatientRegistration,
                    RespectiveId = patientId,
                    TransactionId = commonTrans.AppointmentTransactionId,
                    MasterBillId = masterBillId
                };
                regReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(regReceipt);
                if (regReceipt.ReceiptId == 0)
                {
                    //transaction.Rollback();
                    return 0;

                }
                //begin-to update bill status as genereated.
                var allreceiptforbill = await this.unitOfWork.Receipt.FindAllAsync(x => x.MasterBillId == regReceipt.MasterBillId);
                allreceiptforbill.ToList();
                var receiptcostsum = 0.0;
                foreach (var item in allreceiptforbill.ToList())
                {
                    receiptcostsum += item.Cost;
                }
                var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == regReceipt.MasterBillId);
                if (receiptcostsum == getbill.NetTotal)
                {
                    getbill.BillStatusTypeId = (int)BillStatusType.Generated;
                    getbill.ModifiedBy = createdBy;
                    getbill.ModifiedDate = DateTime.Now;
                    await this.unitOfWork.MasterBill.UpdateAsync(getbill);
                }
                //end-to update bill status as genereated.
            }
            var patientQuery = "";
            var paymentStatus = salucroStatusCode == 1201 ? false : true;
            if (patient.TempPatient == true)
            {
                patientQuery = $@"UPDATE ""Patient"" SET ""PaymentStatus"" = {paymentStatus},""TempPatient"" = false, ""PayTypeId"" = '{payTypeId}',""PaymentNumber"" = '{paymentNumber}', ""UMRNo""='{umrNo}', ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC', ""AppointmentId""={appointmentId}, ""Total""={patientTotal},""DiscountInPercentage""={patientDiscountInPercentage},""DiscountInRupees""={patientDiscountInRupees},""Amount""={patAmount} WHERE ""PatientId""= {patientId}";
            }
            else
            {
                patientQuery = $@"UPDATE ""Patient"" SET ""PaymentStatus"" = {paymentStatus},""TempPatient"" = false,""PayTypeId"" = '{payTypeId}',""PaymentNumber"" = '{paymentNumber}', ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC',""AppointmentId""={appointmentId}, ""Total""={patientTotal},""DiscountInPercentage""={patientDiscountInPercentage},""DiscountInRupees""={patientDiscountInRupees},""Amount""={patAmount} WHERE ""PatientId""= {patientId}";
            }
            var updateSuccess = await this.unitOfWork.Current.ExecuteAsync(patientQuery);
            if (updateSuccess == 0)
            {
                //transaction.Rollback();
                return 0;
            }
            if (paymentStatus)
            {
                var auditLogModel = new AuditLog
                {
                    AccountId = patient.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    //LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow,
                    LogDescription = $"For Patient: {patient.FullName}, patient registration charges has been <b>Updated</b> successfully",
                    LocationId = patient.LocationId
                };
                await this.unitOfWork.AuditLogs.InsertAsync(auditLogModel);
            }
            // transaction.Commit();
            return id;
        }

        private async Task<int> UpadtePatientDetailsAsync(PatientPaymentModel model)
        {
            // var transaction = this.unitOfWork.BeginTransaction();
            var patient = await this.unitOfWork.Patients.FindAsync(m => m.PatientId == model.PatientId);
            var umrNo = await this.patientService.GetLatestUMRNo();
            var id = 0;
            if (model.PaymentStatus == false)
            {
                var commonTrans = new AppointmentTransaction
                {
                    AppointmentId = model.PatientId, // respective Id
                    Transaction = model.Transaction ?? "",
                    TransactionDate = DateTime.Now,
                    TransactionId = model.TransactionId ?? await this.appointmentTransactionsServices.GetATransactionId(),
                    VoucherNumber = model.SalucroStatusCode == 1201 ? null : await this.appointmentTransactionsServices.GetVoucherNumber(),
                    BankReference = "",
                    BankCode = "",
                    Active = true,
                    PaymentId = 0,
                    PaymentModeId = 1,
                    SettledAmount = model.PatientRegistrationAmount,
                    SalucroStatusCode = model.SalucroStatusCode,
                    SalucroTransactionId = model.SalucroTransactionId,
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    ReceiptTypeId = (int)ReceiptType.Cash, // credit
                    ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,
                    LocationId = model.LocationId,
                    PatientId = model.PatientId,
                    PayStatus = 'F'
                };
                commonTrans.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTrans);
                id = commonTrans.AppointmentTransactionId;
                if (commonTrans.AppointmentTransactionId == 0)
                {
                    // transaction.Rollback();
                    return 0;
                }
                if (model.SalucroStatusCode != 1201)
                {
                    var regReceipt = new Receipt
                    {
                        Active = true,
                        Cost = Decimal.ToDouble(model.PatientRegistrationAmount),
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        IsAdvance = false,
                        IsRefunded = false,
                        PayTypeId = model.PayTypeId,
                        PaymentDetails = model.PaymentNumber,
                        ReceiptTypeId = ReceiptType.Cash,    // credit
                                                             // PatientRegistrationDetailId = registration
                        ReceiptAreaTypeId = ReceiptAreaType.PatientRegistration,
                        RespectiveId = model.PatientId,
                        TransactionId = commonTrans.AppointmentTransactionId,
                        //MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                    };
                    regReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(regReceipt);
                    if (regReceipt.ReceiptId == 0)
                    {
                        //transaction.Rollback();
                        return 0;
                    }
                }
            }

            var patientQuery = "";
            var paymentStatus = model.SalucroStatusCode == 1201 ? false : true;



            //var patient = await this.unitOfWork.Patients.FindAsync(m => m.PatientId == model.PatientId, transaction);
            //patientQuery = $@"UPDATE ""Patient"" SET ""PaymentStatus"" = {paymentStatus},""TempPatient"" = false, ""PayTypeId"" = '{payTypeId}',""PaymentNumber"" = '{paymentNumber}', ""UMRNo""='{umrNo}', ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC', ""AppointmentId""={appointmentId} WHERE ""PatientId""= {patientId}";
            patient.Salutation = model.Salutation ?? patient.Salutation;
            patient.FirstName = model.FirstName ?? patient.FirstName;
            patient.MiddleName = patient.MiddleName ?? patient.MiddleName;
            patient.LastName = model.LastName ?? patient.LastName;
            patient.FullName = model.FirstName != null && model.MiddleName != null && model.LastName != null ? CoreFilter.FullName(model.FirstName, model.MiddleName, model.LastName) : CoreFilter.FullName(patient.FirstName, patient.MiddleName, patient.LastName);
            patient.FatherOrHusband = model.FatherOrHusband ?? patient.FatherOrHusband;
            patient.DateOfBirth = model.DateOfBirth ?? patient.DateOfBirth;
            patient.Age = model.Age ?? patient.Age;
            patient.Gender = model.Gender ?? patient.Gender;
            patient.MaritalStatus = model.MaritalStatus ?? patient.MaritalStatus;
            patient.Email = model.Email ?? patient.Email;
            patient.Mobile = model.Mobile ?? patient.Mobile;
            patient.StreetAddress = model.StreetAddress ?? patient.StreetAddress;
            patient.AddressLine2 = model.AddressLine2 ?? patient.AddressLine2;
            patient.City = model.City ?? patient.City;
            patient.State = model.State ?? patient.State;
            patient.Zipcode = model.Zipcode ?? patient.Zipcode;
            patient.CountryId = model.CountryId ?? patient.CountryId;
            patient.ModifiedBy = model.ModifiedBy;
            patient.ModifiedDate = DateTime.UtcNow;
            patient.AadharNo = model.AadharNo ?? patient.AadharNo;
            patient.PatientReferredById = model.PatientReferredById ?? patient.PatientReferredById;
            patient.ReferredByName = model.ReferredByName ?? patient.ReferredByName;
            patient.HWCPatientId = model.HWCPatientId ?? patient.HWCPatientId;
            patient.Education = model.Education ?? patient.Education;
            patient.Occupation = model.Occupation ?? patient.Occupation;
            patient.Nationality = model.Nationality ?? patient.Nationality;
            patient.Religion = model.Religion ?? patient.Religion;
            patient.IdProofId = model.IdProofId ?? patient.IdProofId;
            patient.IdProofValue = model.IdProofValue ?? patient.IdProofValue;
            patient.BloodGroup = model.BloodGroup ?? patient.BloodGroup;
            //patient.PaymentStatus = model.PaymentStatus ? model.PaymentStatus : patient.PaymentStatus;
            patient.PaymentStatus = model.SalucroStatusCode == 1201 ? false : true;
            patient.PayTypeId = model.PayTypeId != null ? model.PayTypeId : patient.PayTypeId;
            patient.PaymentNumber = model.PaymentStatus ? model.PaymentNumber : patient.PaymentNumber;
            patient.UMRNo = patient.TempPatient == true ? umrNo : patient.UMRNo;
            patient.TempPatient = model.PaymentStatus == true ? false : patient.TempPatient;
            patient.HowDidYouKnowId = model.HowDidYouKnowId ?? patient.HowDidYouKnowId;
            patient.EducationId = model.EducationId ?? patient.EducationId;
            patient.OccupationId = model.OccupationId ?? patient.OccupationId;
            //patient.BirthMark1 = model.BirthMark1;
            //patient.BirthMark2 = model.BirthMark2;
            //patient.RelationType = model.RelationType;
            patient.OccupationDetail = model.OccupationDetail ?? patient.OccupationDetail;
            patient.InsuranceCompanyId = model.InsuranceCompanyId ?? patient.InsuranceCompanyId;
            patient.Amount = model.Charges ?? model.Charges;
            patient.Total = model.PatientRegistrationAmount;
            var updated = await this.unitOfWork.Patients.UpdateAsync(patient);

            if (updated == 0)
            {
                return 0;
            }

            //Patient RelativeDetails
            if (model.RelativeDetails != null && model.RelativeDetails.Count() > 0 && model.RelativeDetails[0].FullName != null && model.RelativeDetails[0].Relation != null)
            {
                var query = $@"DELETE FROM ""PatientFamily"" WHERE ""PatientId"" = '{model.PatientId}'";

                await this.unitOfWork.Current.ExecuteAsync(query, null);
                var patientFamily = new PatientFamily
                {
                    PatientId = patient.PatientId,
                    FullName = model.RelativeDetails[0].FullName,
                    Relation = model.RelativeDetails[0].Relation,
                    Age = model.RelativeDetails[0].Age != null ? (int)model.RelativeDetails[0].Age : 0,
                    Gender = model.RelativeDetails[0].RelativeGender,
                    Active = true,
                    CreatedBy = Convert.ToInt32(model.ModifiedBy),
                    CreatedDate = DateTime.UtcNow,
                    ContactNo = model.RelativeDetails[0].ContactNo,
                    Education = model.RelativeDetails[0].Education,
                    Occupation = model.RelativeDetails[0].Occupation,
                    DOB = model.RelativeDetails[0].DOB,
                    OccupationDetails = model.RelativeDetails[0].OccupationDetails
                };
                var response = await this.unitOfWork.PatientFamily.InsertAsync(patientFamily);
                if (response == 0)
                {
                    return 0;
                }
            }

            // Patient's Account
            var account = await this.unitOfWork.Accounts.FindAsync(m => m.RoleId == (int)Roles.Patient && m.ReferenceId == patient.PatientId);
            if (account == null || account.AccountId == 0)
            {

                return 0;
            }

            if (account.Email != patient.Email || account.Mobile != patient.Mobile || account.CountryId != patient.CountryId || account.FullName != patient.FullName)
            {
                account.Email = model.Email ?? patient.Email;
                account.Mobile = model.Mobile ?? patient.Mobile;
                account.CountryId = model.CountryId ?? patient.CountryId;
                account.FullName = model.FirstName != null && model.MiddleName != null && model.LastName != null ? CoreFilter.FullName(model.FirstName, model.MiddleName, model.LastName) : CoreFilter.FullName(patient.FirstName, patient.MiddleName, patient.LastName);
                updated = await this.unitOfWork.Accounts.UpdateAsync(account);
                if (updated == 0)
                {

                    return 0;
                }
            }

            return updated;


            if (paymentStatus)
            {
                var auditLogModel = new AuditLog
                {
                    AccountId = patient.ModifiedBy,
                    LogTypeId = (int)LogTypes.Appointments,
                    //LogFrom = model.LogFrom,
                    LogDate = DateTime.UtcNow,
                    LogDescription = $"For Patient: {patient.FullName}, patient registration charges has been <b>Updated</b> successfully",
                    LocationId = patient.LocationId
                };
                await this.unitOfWork.AuditLogs.InsertAsync(auditLogModel);
            }
            // transaction.Commit();
            return id;
        }

        /// <summary>
        /// The get latest UMR no.
        /// </summary>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        //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");
        //}

        /// <inheritdoc />
        public async Task<int> CancelAsync(int appointmentId, int? modifiedBy, string reason)
        {
            var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == appointmentId);
            var query = $@"UPDATE ""Appointment"" SET ""Active"" = FALSE, ""Status"" = 'C',""Reason"" = '{reason}', ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AppointmentId""= {appointmentId}";
            await this.DeleteSupportLogAsync(appointmentId);
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<int> AddSymptomsAsync(int appointmentId, string symptoms, int createdBy, bool isAdmission)
        {

            var appointmentSymptomExisting = isAdmission
            ? await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentSymptom>($@"SELECT * FROM ""AppointmentSymptom"" where ""AdmissionId"" = {appointmentId} and ""Active"" = true ORDER BY ""AdmissionId"" DESC")
            : await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentSymptom>($@"SELECT * FROM ""AppointmentSymptom"" where ""AppointmentId"" = {appointmentId} and ""Active"" = true ORDER BY ""AppointmentId"" DESC");

            if (appointmentSymptomExisting != null)
            {
                appointmentSymptomExisting.ModifiedBy = createdBy;
                appointmentSymptomExisting.ModifiedDate = DateTime.UtcNow;
                appointmentSymptomExisting.Symptoms = symptoms;
                appointmentSymptomExisting.Active = true;
                var response = await this.unitOfWork.AppointmentSymptoms.UpdateAsync(appointmentSymptomExisting);
                return response;
            }

            var appointmentSymptom = new AppointmentSymptom
            {
                Active = true,
                Symptoms = symptoms,
                CreatedBy = createdBy,
                CreatedDate = DateTime.Now,
                AppointmentId = isAdmission ? null : (int?)appointmentId,
                AdmissionId = isAdmission ? (int?)appointmentId : null
            };

            return await this.unitOfWork.AppointmentSymptoms.InsertAsync(appointmentSymptom);
        }

        /// <inheritdoc />
        public async Task<int> UpdateRelationIdAsync(int appointmentId, int userId, int? patientFamilyId)
        {
            var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == appointmentId);
            appointment.PatientFamilyId = patientFamilyId;
            appointment.ModifiedBy = userId;
            appointment.ModifiedDate = DateTime.UtcNow;

            var result = await this.unitOfWork.Appointments.UpdateAsync(appointment);
            return result;
        }

        /// <inheritdoc />
        public Task<int> DeleteAsync(int appointmentId)
        {
            var query = $@"DELETE FROM ""Appointment"" WHERE ""AppointmentId""= {appointmentId}";
            return this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<int> UpdateEncounterTypeAsync(int appointmentId, int encounterType, bool isAdmission)
        {
            var query = "";
            //if(isAdmission==true)
            //{
            //     query = $@"UPDATE ""Admission"" SET ""EncounterType"" = '{Enum.GetName(typeof(EncounterTypes), encounterType)}', ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AdmissionId""= {appointmentId}";
            //}
            //else
            //{
            query = $@"UPDATE ""Appointment"" SET ""EncounterType"" = '{Enum.GetName(typeof(EncounterTypes), encounterType)}', ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AppointmentId""= {appointmentId}";
            // }
            return await this.unitOfWork.Current.ExecuteAsync(query);

        }

        /// <inheritdoc />
        public async Task<IEnumerable<AppointmentSupportLogModel>> FetchSupportLogAsync(AppointmentSupportLogModel model)
        {
            var where = " where 1=1";
            if (!model.IsAdmin)
            {
                where += model.AssigneeId != null
                             ? $@" and ASL.""AssigneeId"" = {model.AssigneeId}"
                             : $@" and ASL.""AssigneeId"" is null ";
            }

            model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" AND AP.""AppointmentDate""::DATE >= '{model.FromDate}'::DATE";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND AP.""AppointmentDate""::DATE <= '{model.ToDate}'::DATE";
            }

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

            if (!string.IsNullOrEmpty(model.Mobile))
            {
                where += $@" AND PA.""Mobile"" ilike '%{model.Mobile}%' ";
            }

            var query =
                $@"SELECT A.*, count(*) over() as ""TotalItems"" FROM (
                                SELECT Distinct ASL.""AppointmentSupportLogId"",ASL.""CreatedDate"", ASL.""AppointmentId"", ASL.""AssigneeId"",
                                ASL.""Audio"",ASL.""Video"", ASL.""Document"", ASL.""Invoice"", ASL.""Comments"",ASL.""CallStatus"", ASL.""Active"",
                                PR.""FullName"" as ""ProviderName"", (case when AP.""PatientFamilyId"" is not null then PF.""FullName"" else PA.""FullName"" end) AS ""PatientName"",AP.""AppointmentDate"",AP.""AppointmentNo"",
                                AP.""AppointmentTime"",PA.""Mobile"" as ""PatientMobile"", A.""FullName"" as ""AssigneeName"",R.""RoleName"",AA.""AccountId"" as ""PatientAccountId""
                                ,PA.""ThumbnailUrl"" as ""PatientThumbnailUrl""
                                ,CASE WHEN acs.""AccountSessionId"" IS NULL THEN FALSE ELSE TRUE END AS ""IsOnline""
                                FROM ""AppointmentSupportLog"" ASL
                                join ""Appointment"" AP on AP.""AppointmentId"" = ASL.""AppointmentId""
                                join ""Provider"" PR on PR.""ProviderId"" = AP.""ProviderId""
                                join ""Patient"" PA on PA.""PatientId"" = AP.""PatientId""
                                Left join ""PatientFamily"" PF on PF.""PatientFamilyId"" = AP.""PatientFamilyId""
                                left join ""Account"" AA on AA.""ReferenceId""= PA.""PatientId"" and AA.""RoleId"" = 4
                                left join ""Account"" A on A.""AccountId"" = ASL.""AssigneeId""
                                left join ""Role"" R on R.""RoleId"" = A.""RoleId""
                                left JOIN ""AccountSession"" acs ON acs.""AccountId"" = AA.""AccountId""
                                {where} order by AP.""AppointmentDate""::date desc ) A";

            if (!model.IsAdmin)
            {
                if (model.AssigneeId == null)
                {
                    query = $@"SELECT distinct ASL.""AppointmentSupportLogId"",count(ASL.*) over() as ""TotalItems"",ASL.""CreatedDate"", ASL.""AppointmentId"", ASL.""AssigneeId"",
                                ASL.""Audio"",ASL.""Video"", ASL.""Document"", ASL.""Invoice"", ASL.""Comments"",ASL.""CallStatus"", ASL.""Active"",
                                PR.""FullName"" as ""ProviderName"",(case when AP.""PatientFamilyId"" is not null then PF.""FullName"" else PA.""FullName"" end) AS ""PatientName"",AP.""AppointmentDate"",AP.""AppointmentNo"",
                                AP.""AppointmentTime"",PA.""Mobile"" as ""PatientMobile"", A.""FullName"" as ""AssigneeName"",R.""RoleName"",AA.""AccountId"" as ""PatientAccountId""
								,PA.""ThumbnailUrl"" as ""PatientThumbnailUrl""
	                                FROM ""AppointmentSupportLog"" ASL
	                                join ""Appointment"" AP on AP.""AppointmentId"" = ASL.""AppointmentId""
	                                join ""Provider"" PR on PR.""ProviderId"" = AP.""ProviderId""
	                                join ""Patient"" PA on PA.""PatientId"" = AP.""PatientId""
                                     Left join ""PatientFamily"" PF on PF.""PatientFamilyId"" = AP.""PatientFamilyId""
									left join ""Account"" AA on AA.""ReferenceId""= PA.""PatientId"" and AA.""RoleId"" = 4
									left join ""Account"" A on A.""AccountId"" = ASL.""AssigneeId""
									left join ""Role"" R on R.""RoleId"" = A.""RoleId""
                                    {where}  order by AP.""AppointmentDate""::date desc";
                }
            }
            if (model.IsAdmin && model.IsAdminFilaterApplied)
            {
                if (model.AssigneeId == null)
                {
                    query = $@"SELECT distinct ASL.""AppointmentSupportLogId"",count(ASL.*) over() as ""TotalItems"",ASL.""CreatedDate"", ASL.""AppointmentId"", ASL.""AssigneeId"",
                                ASL.""Audio"",ASL.""Video"", ASL.""Document"", ASL.""Invoice"", ASL.""Comments"",ASL.""CallStatus"", ASL.""Active"",
                                PR.""FullName"" as ""ProviderName"",(case when AP.""PatientFamilyId"" is not null then PF.""FullName"" else PA.""FullName"" end) AS ""PatientName"",AP.""AppointmentDate"",AP.""AppointmentNo"",
                                AP.""AppointmentTime"",PA.""Mobile"" as ""PatientMobile"", A.""FullName"" as ""AssigneeName"",R.""RoleName"",AA.""AccountId"" as ""PatientAccountId""
								,PA.""ThumbnailUrl"" as ""PatientThumbnailUrl""
	                                FROM ""AppointmentSupportLog"" ASL
	                                join ""Appointment"" AP on AP.""AppointmentId"" = ASL.""AppointmentId""
	                                join ""Provider"" PR on PR.""ProviderId"" = AP.""ProviderId""
	                                join ""Patient"" PA on PA.""PatientId"" = AP.""PatientId""
                                     Left join ""PatientFamily"" PF on PF.""PatientFamilyId"" = AP.""PatientFamilyId""
									left join ""Account"" AA on AA.""ReferenceId""= PA.""PatientId"" and AA.""RoleId"" = 4
									left join ""Account"" A on A.""AccountId"" = ASL.""AssigneeId""
									left join ""Role"" R on R.""RoleId"" = A.""RoleId""
                                     {where}  order by AP.""AppointmentDate""::date desc";
                }
                else
                {
                    query = $@"SELECT distinct ASL.""AppointmentSupportLogId"",count(ASL.*) over() as ""TotalItems"",ASL.""CreatedDate"", ASL.""AppointmentId"", ASL.""AssigneeId"",
                                ASL.""Audio"",ASL.""Video"", ASL.""Document"", ASL.""Invoice"", ASL.""Comments"",ASL.""CallStatus"", ASL.""Active"",
                                PR.""FullName"" as ""ProviderName"",(case when AP.""PatientFamilyId"" is not null then PF.""FullName"" else PA.""FullName"" end) AS ""PatientName"",AP.""AppointmentDate"",AP.""AppointmentNo"",
                                AP.""AppointmentTime"",PA.""Mobile"" as ""PatientMobile"", A.""FullName"" as ""AssigneeName"",R.""RoleName"",AA.""AccountId"" as ""PatientAccountId""
								,PA.""ThumbnailUrl"" as ""PatientThumbnailUrl""
	                                FROM ""AppointmentSupportLog"" ASL
	                                join ""Appointment"" AP on AP.""AppointmentId"" = ASL.""AppointmentId""
	                                join ""Provider"" PR on PR.""ProviderId"" = AP.""ProviderId""
	                                join ""Patient"" PA on PA.""PatientId"" = AP.""PatientId""
                                     Left join ""PatientFamily"" PF on PF.""PatientFamilyId"" = AP.""PatientFamilyId""
									left join ""Account"" AA on AA.""ReferenceId""= PA.""PatientId"" and AA.""RoleId"" = 4
									left join ""Account"" A on A.""AccountId"" = ASL.""AssigneeId""
									left join ""Role"" R on R.""RoleId"" = A.""RoleId""
                                    {where}  and ASL.""AssigneeId"" = {model.AssigneeId}  order by AP.""AppointmentDate""::date desc";
                }


            }

            query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";

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

        /// <inheritdoc />
        public async Task<int> UpdateLog(AppointmentSupportLogModel model)
        {
            var log = await this.unitOfWork.AppointmentSupportLogRepository.FindAsync(
                          m => m.AppointmentSupportLogId == model.AppointmentSupportLogId);
            log.Audio = model.Audio;
            log.Video = model.Video;
            log.Comments = model.Comments;
            log.Invoice = model.Invoice;
            log.Document = model.Document;
            log.CallStatus = model.CallStatus;
            return await this.unitOfWork.AppointmentSupportLogRepository.UpdateAsync(log);
        }

        /// <inheritdoc />
        public async Task<int> AssignAppointmentToSupport(AppointmentSupportLogModel model)
        {
            var query = $@"UPDATE ""AppointmentSupportLog"" SET ""AssigneeId""={model.AssigneeId}	WHERE ""AppointmentSupportLogId""= {model.AppointmentSupportLogId} ";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<long> FetchAppointmentLogCount()
        {
            var query = $@"Select count(*) from ""AppointmentSupportLog"" where ""AssigneeId"" is null";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<long>(query);
        }

        /// <inheritdoc />
        public async Task<PreviousAppointmentModel> FindPreviousAppointmentAsync(int appointmentId)
        {
            var patientFamilyIdQuery =
                $@"Select ""PatientFamilyId"" from ""Appointment"" WHERE ""AppointmentId"" = {appointmentId} ";
            var patientFamilyId = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int?>(patientFamilyIdQuery);

            var where = patientFamilyId == null ? $@" And A.""PatientFamilyId"" is null" : $@" And A.""PatientFamilyId"" ={patientFamilyId}";

            var query = $@"SELECT DISTINCT A.""AppointmentDate"",A.""AppointmentTime"",
							TO_CHAR(A.""AppointmentDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(A.""AppointmentTime"", 'hh12:mi AM') ""AppointmentDateTime"",
							A.""AppointmentId"", A.""PatientId"", A.""EncounterType""::text, PR.""FullName"" AS ""ProviderName"" FROM ""Appointment"" A
                            JOIN ""Patient"" P ON A.""PatientId"" = (SELECT DISTINCT ""PatientId"" FROM ""Appointment"" WHERE ""AppointmentId"" = {appointmentId} )
							JOIN ""Provider"" PR ON PR.""ProviderId"" = A.""ProviderId""
                            WHERE A.""Active"" IS TRUE AND A.""EncounterType"" IS NOT NULL {where}
							ORDER BY A.""AppointmentDate""::date desc, A.""AppointmentTime"" desc LIMIT 1";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<PreviousAppointmentModel>(query);
        }

        /// <inheritdoc />
        public async Task<IEnumerable<AppointmentNewModel>> FetchNewAsync(AppointmentFilterModel model)
        {
            var where = $@" WHERE 1 = 1 ";
            var limit = string.Empty;
            var email = string.Empty;
            var orderBy = $@" Order BY A.""AppointmentDate"" DESC, A.""AppointmentTime"" DESC";

            if (model.VisitType != null)
            {
                where += $@" AND A.""VisitType"" = '{model.VisitType}'";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND A.""AppointmentDate""::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND A.""AppointmentDate""::DATE <= '{model.ToDate}'::DATE";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND A.""AppointmentDate""::DATE >= '%{model.FromDate}%'";
            }

            if (!string.IsNullOrEmpty(model.AppointmentNo))
            {
                where += $@" AND A.""AppointmentNo"" ILIKE '%{model.AppointmentNo}%'";
            }

            if (!string.IsNullOrEmpty(model.Status))
            {
                where += $@" AND A.""Status"" = '{model.Status}'";
            }

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

            if (model.Gender != null)
            {
                where += $@" AND A.""PatientGender"" = '{model.Gender}'";
            }

            if (model.PatientId != null)
            {
                where += $@" AND A.""PatientId"" = {model.PatientId}";
            }

            if (model.CountryId != null)
            {
                where += $@" AND A.""PatientCountryId"" = {model.CountryId}";
            }

            if (model.DepartmentId != null)
            {
                where += $@" AND A.""DepartmentId"" = {model.DepartmentId}";
            }

            if (model.Active != null)
            {
                where += $@" AND A.""Active"" IS {((bool)model.Active ? "TRUE" : "FALSE")}";
            }
            if (model.UMRNo != null)
            {
                where += $@" AND A.""UMRNo"" ILIKE '%{model.UMRNo}%'";
            }

            if (model.IsFollowUpAppointment != null)
            {
                where += $@" AND A.""AppointmentTypeId"" = {model.IsFollowUpAppointment}";
            }

            var telemedicineIdsQuery = $@" LEFT JOIN LATERAL (
		                                SELECT
			                                STRING_AGG (DISTINCT callLog.""TelemedicineId""::VARCHAR, ',') AS ""TelemedicineIds""
		                                FROM ""CallLog"" callLog
		                                WHERE
			                                callLog.""AppointmentNo"" = inside.""AppointmentNo""
		                                LIMIT 1
                                          ) telemedicineIds ON true ";

            if (model.PageIndex > 0)
            {
                model.PageIndex -= 1;
                limit = $@"LIMIT {model.PageSize} offset {(model.PageIndex * model.PageSize)}";
            }

            //     if (model.AccountId != null && model.AccountId != 0)
            //     {
            //         email = $@" ,
            //                     (select distinct ""IsTaskDone"" from ""EmailDetails"" ed
            //                     where ed.""AppointmentId"" = appointment.""AppointmentId"" and ed.""IsCc"" = false ) AS ""IsTaskDone"",
            //                     emailDetails.""EmailDetailsId"",replyEmailDetails.""ReplyEmailDetailsId"",emailDetails.""EmailHeadersId"",
            //(select count(a.""ReplyEmailDetailsId"") ""NoOfEmails"" from (
            //select a.""ReplyEmailDetailsId""  from ""ReplyEmailDetails"" a
            //                     join ""ReplyEmailHeaders"" reH on reH.""ReplyEmailDetailsId"" = a.""ReplyEmailDetailsId""
            //                     join ""EmailHeaders"" eH on eH.""EmailHeadersId"" = reH.""EmailHeadersId""
            //                     join ""EmailDetails"" eD on eD.""EmailHeadersId"" = eH.""EmailHeadersId""
            //                     where a.""IsRead"" = false and a.""Active"" = true and a.""ReplyToId"" = {model.AccountId} and eD.""AppointmentId"" = appointment.""AppointmentId""
            //                     union
            //select a.""EmailHeadersId""  from ""EmailDetails"" a
            //                     join ""Appointment"" app on app.""AppointmentId"" = a.""AppointmentId""
            //                     where a.""IsRead"" = false and a.""Active""= true and a.""CcAccountId"" = {model.AccountId} and a.""AppointmentId"" = appointment.""AppointmentId"")a) ""NoOfEmails"" ";
            //     }

            var query = $@"SELECT
                                    *
                                FROM
                                    (SELECT COUNT(A.*) OVER () AS ""TotalItems"", A.* FROM (SELECT DISTINCT apt.""PaymentStatus"",string_agg(DISTINCT spl.""SpecializationName"", ',') AS ""SpecializationNames"",pr.""Languages"",apt.""FollowUpForAppointmentId"",apt.""FollowUpForAdmissionId"",pat.""StreetAddress"",pat.""City"",pat.""State"",pat.""Zipcode"",acc.""AccountId"" as ""PatientAccountId"",prAcc.""AccountId"" as ""ProviderAccountId"",
													 apt.""AppointmentId"", apt.""ProviderLocationId"", apt.""ProviderId"", apt.""PatientId"", apt.""VisitType"", apt.""PatientType"", apt.""AppointmentNo"", apt.""AppointmentDate"", apt.""AppointmentTime"", apt.""AppointmentNotes"", apt.""CouponId"", apt.""Amount"", apt.""Discount"", apt.""Total"", apt.""Active"",apt.""CreatedBy"", apt.""CreatedDate"", apt.""ModifiedBy"", apt.""ModifiedDate"", apt.""Status"", apt.""EncounterType"", apt.""Old_AppointmentId"", apt.""IsRemainder"", apt.""Reason"",
                                                     apt.""AppCharges"", apt.""PatientFamilyId"", apt.""WalletAmount"", apt.""DepartmentId"", apt.""PaymentType"",
													 apt.""PaymentNumber"", apt.""ChargeType"" {email}, apt.""VisitTypeId"", apt.""ChargeTypesId"",
													 pr.""FullName"" AS ""ProviderName"", pr.""Gender"" AS ""ProviderGender"", pat.""FatherOrHusband"",
                                cunpra.""CurrencySymbol"", pat.""CountryId"" AS ""PatientCountryId"", cun.""CountryCode"" AS ""PatientCountryCode"",pral.""LocationId"",
                                (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentDate"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""AppointmentPreviousDate"",
                                (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentTime"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""AppointmentPreviousTime"",
                                (case when apt.""FollowUpForAppointmentId"" is not null then (select ""AppointmentNo"" from ""Appointment"" where ""AppointmentId"" = apt.""FollowUpForAppointmentId"") else null end) AS ""PreviousAppointmentNo"",
                                (case when apt.""FollowUpForAdmissionId"" is not null then (select dis.""DischargeDate"" from ""Discharge"" dis join ""Admission"" adm on adm.""AdmissionId"" = dis.""AdmissionId""	where adm.""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""AdmissionDischargeDate"",
                                (case when apt.""FollowUpForAdmissionId"" is not null then (select dis.""DischargeTime"" from ""Discharge"" dis join ""Admission"" adm on adm.""AdmissionId"" = dis.""AdmissionId""	where adm.""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""AdmissionDischargeTime"",
                                (case when apt.""FollowUpForAdmissionId"" is not null then (select ""AdmissionNo"" from ""Admission"" where ""AdmissionId"" = apt.""FollowUpForAdmissionId"") else null end) AS ""PreviousAdmissionNo"",

                            CASE
                                WHEN apt.""EncounterType"" IS NULL THEN FALSE
                                ELSE TRUE END AS ""IsFullTranscript"",
                            CASE
                                WHEN apt.""EncounterType"" IS NULL THEN FALSE
                                WHEN apt.""EncounterType"" IN ('Encounter',
                                'InternalMedicine')
                                THEN TRUE ELSE FALSE END AS ""IsPrescription"",

                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE ELSE TRUE END AS ""IsFullTranscript"", pat.""UMRNo"", D.""DepartmentName"", pat.""MaritalStatus"" AS ""PatientMaritalStatus"",
                                CASE WHEN apt.""EncounterType"" IS NULL THEN FALSE
                               WHEN apt.""EncounterType"" in ('{EncounterTypes.Encounter}', '{EncounterTypes.InternalMedicine}')  IS NOT NULL THEN TRUE
                               -- WHEN apt.""EncounterType"" in ('{EncounterTypes.BehavioralHealth}') IS NOT NULL THEN TRUE
ELSE FALSE END AS ""IsPrescription"",
                               (case when apt.""PatientFamilyId"" is not null then PF.""FullName"" else pat.""FullName"" end) AS ""PatientName"", pat.""Gender"" AS ""PatientGender"", pat.""Age"" AS ""PatientAge"",pr.""Age"" as ""ProviderAge"", pat.""Email"" AS ""PatientEmail"", pat.""Mobile"" AS ""PatientMobile"",
                                pral.""Name"" AS ""ProviderLocation"", pat.""Guid""::text AS ""PatientGuid"", pr.""Guid""::text AS ""ProviderGuid"",
                                 (CASE WHEN pr.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.amazonS3Configuration.BucketURL}', pr.""Guid"", '/', pr.""ThumbnailUrl"") ELSE NULL END) AS ""ProviderThumbnailUrl"",
                                (CASE WHEN pat.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/', pat.""Guid"", '/', pat.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"", apt.""EncounterType"",
                                CASE WHEN acs.""AccountSessionId"" IS NULL THEN FALSE ELSE TRUE END AS ""IsOnline"",pat.""AadharNo"",pat.""ReferredBy"",pat.""ReferredByName""
                                --(case when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is  null  then false
                                --when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is not null and max(dc.""DischargeId"")over(partition by adm.""AdmissionId"") is  null  then true
                                --when max(adm.""AdmissionId"")over(partition by adm.""PatientId"") is not null and max(dc.""DischargeId"")over(partition by adm.""AdmissionId"") is not null  then false end
                                --)""isActiveAdmissionExists""
                                , qq.""Name"" ""QueueStatus""
                                FROM ""Appointment"" apt
                                LEFT JOIN ""QueueStatus"" qq on qq.""QueueStatusId"" = apt.""QueueStatusId""
                                JOIN ""Patient"" pat ON pat.""PatientId"" = apt.""PatientId"" AND pat.""Active"" IS TRUE
                                left join ""Admission"" adm on adm.""PatientId"" = pat.""PatientId""
                                left join ""Discharge"" dc on dc.""AdmissionId"" = adm.""AdmissionId""
                                LEFT JOIN ""PatientFamily"" PF on PF.""PatientFamilyId"" = apt.""PatientFamilyId""
                                LEFT JOIN ""Country"" cun ON cun.""CountryId"" = pat.""CountryId"" AND cun.""Active"" IS TRUE
                                LEFT JOIN ""Encounter"" e ON e.""AppointmentId"" = apt.""AppointmentId"" AND e.""Active"" IS TRUE
                                LEFT JOIN ""BehavioralHealth"" bh ON bh.""AppointmentId"" = apt.""AppointmentId"" AND bh.""Active"" IS TRUE
                                JOIN ""Provider"" pr ON pr.""ProviderId"" = apt.""ProviderId"" AND pr.""Active"" IS TRUE AND pr.""ApprovalStatus"" IS TRUE
					LEFT JOIN ""Specialization"" spl ON spl.""SpecializationId"" = ANY(pr.""Specializations"") AND spl.""Active"" IS TRUE
                                LEFT JOIN ""Department"" D on D.""DepartmentId"" = pr.""DepartmentId""
                                --JOIN ""ProviderLocation"" prl ON prl.""ProviderLocationId"" = apt.""ProviderLocationId"" AND prl.""Active"" IS TRUE
                                JOIN ""ProviderAvailability"" prl ON prl.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND prl.""Active"" IS TRUE
                                JOIN ""Location"" pral ON pral.""LocationId"" = prl.""LocationId"" AND pral.""Active"" IS TRUE
                                JOIN ""Country"" cunpra ON cunpra.""CountryId"" = pral.""CountryId"" AND cunpra.""Active"" IS TRUE
                                JOIN ""Practice"" pra ON pra.""PracticeId"" = pral.""PracticeId"" AND pra.""Active"" IS TRUE
                                JOIN ""Account"" acc ON acc.""ReferenceId"" = pat.""PatientId"" AND acc.""RoleId""=4 AND acc.""Active"" IS TRUE
                                LEFT JOIN ""AccountSession"" acs ON acs.""AccountId"" = acc.""AccountId""
                                JOIN ""Account"" prAcc ON prAcc.""ReferenceId"" = pr.""ProviderId"" AND prAcc.""RoleId""=3 AND prAcc.""Active"" IS TRUE
group by apt.""PaymentStatus"",pr.""Languages"",apt.""FollowUpForAppointmentId"",apt.""FollowUpForAdmissionId"",pat.""StreetAddress"",pat.""City"",pat.""State"",pat.""Zipcode"",acc.""AccountId"",pracc.""AccountId"",apt.""AppointmentId"",pr.""FullName"",pr.""Gender"",pat.""FatherOrHusband"",cunpra.""CurrencySymbol"",pat.""CountryId"",
											cun.""CountryCode"",e.""Medications"",pat.""UMRNo"",d.""DepartmentName"",pat.""MaritalStatus"",bh.""Medications"",pf.""FullName"",pat.""FullName"",pat.""Gender"",pat.""Age"",pr.""Age"",pat.""Email"",pat.""Mobile"",pral.""Name"",pat.""Guid"",pr.""Guid"",pr.""ThumbnailUrl"",pat.""ThumbnailUrl"",acs.""AccountSessionId"",pat.""AadharNo"",pat.""ReferredBy"",pat.""ReferredByName"",qq.""Name"",pral.""LocationId""
                                     ) A

	                                                   {where} {orderBy} {limit}
                                    ) inside

                                    LEFT JOIN LATERAL(
                                        SELECT
                                            CASE WHEN accountSession.""AccountSessionId"" IS NOT NULL THEN TRUE ELSE FALSE END AS ""IsOnline""

                                        FROM ""AccountSession"" accountSession
                                        WHERE

                                            accountSession.""AccountId"" = inside.""ProviderAccountId""

                                        LIMIT 1
                                    ) session ON true


                                    LEFT JOIN LATERAL(
                                        SELECT

                                            COUNT(patientDocument.""PatientDocumentId"") OVER() AS ""PatientDocumentCount""

                                        FROM ""PatientDocument"" patientDocument

                                        WHERE

                                            patientDocument.""PatientId"" = inside.""PatientId"" AND patientDocument.""Active"" IS TRUE

                                        LIMIT 1
                                    ) patientDocuments ON true


                                    {telemedicineIdsQuery}

            LEFT JOIN LATERAL(
                SELECT

                    telemedicineCallHistory.""TelemedicineCallHistoryId"",
                    telemedicineCallHistory.""Status"" AS ""CallStatus"",
                    telemedicineCallHistory.""InProgress"",
                    telemedicineCallHistory.""CreatedDate"" AS ""CallStatusDate"",
                    telemedicineCallHistory.""ModifiedDate"" AS ""CallStatusModifiedDate"",
                    telemedicineCallHistory.""CallType"",
                    callerTelemedicine.*,
                    receiverTelemedicine.*,
                    activeUsers.*
                FROM ""TelemedicineHistory"" telemedicineHistory

                JOIN ""TelemedicineCallHistory"" telemedicineCallHistory on telemedicineCallHistory.""TelemedicineHistoryId"" = telemedicineHistory.""TelemedicineHistoryId""


                LEFT JOIN LATERAL(
                      SELECT

                            telemedicineCallerHistory.""Status"" AS ""CallerCallStatus"",
                            telemedicineCallerHistory.""Date"" AS ""CallerCallStatusDate"",
                            callerAccount.""RoleId"" AS ""CallerRoleId""

                        FROM ""TelemedicineUsersHistory"" telemedicineCallerHistory

                            JOIN ""Account"" callerAccount on callerAccount.""AccountId"" = telemedicineCallerHistory.""CallerId""

                            WHERE telemedicineCallerHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""

                            AND callerAccount.""RoleId"" != 4

                            ORDER BY telemedicineCallerHistory.""Date"" DESC

                            LIMIT 1
                ) callerTelemedicine ON TRUE


                LEFT JOIN LATERAL(
                      SELECT

                            telemedicineReceiverHistory.""Status"" AS ""ReceiverCallStatus"",
                            telemedicineReceiverHistory.""Date"" AS ""ReceiverCallStatusDate"",
                            receiverAccount.""RoleId"" AS ""ReceiverRoleId""

                        FROM ""TelemedicineUsersHistory"" telemedicineReceiverHistory

                            JOIN ""Account"" receiverAccount on receiverAccount.""AccountId"" = telemedicineReceiverHistory.""AccountId""

                            WHERE telemedicineReceiverHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""

                            AND receiverAccount.""RoleId"" = 4

                            ORDER BY telemedicineReceiverHistory.""Date"" DESC

                            LIMIT 1
                ) receiverTelemedicine ON TRUE


                LEFT JOIN LATERAL(
                        SELECT

                            STRING_AGG(activeAccount.""FullName"" || '#' || role.""RoleName"" || '#' || telemedicineActiveUsersHistory.""Date"", ',') ""ActiveUsers""

                        FROM ""TelemedicineUsersHistory"" telemedicineActiveUsersHistory

                            JOIN ""Account"" activeAccount on activeAccount.""AccountId"" = telemedicineActiveUsersHistory.""AccountId""

                            JOIN ""Role"" role on role.""RoleId"" = activeAccount.""RoleId""

                            WHERE telemedicineActiveUsersHistory.""TelemedicineCallHistoryId"" = telemedicineCallHistory.""TelemedicineCallHistoryId""

                            AND telemedicineActiveUsersHistory.""InProgress"" IS TRUE AND telemedicineCallHistory.""InProgress"" IS TRUE

                            LIMIT 1
                ) activeUsers ON TRUE


                WHERE

                    telemedicineHistory.""AppointmentId"" = inside.""AppointmentId""

                    ORDER BY telemedicineCallHistory.""CreatedDate"" DESC

                LIMIT 1
        ) telemedicine ON true";
            try
            {
                return await this.unitOfWork.Current.QueryAsync<AppointmentNewModel>(query);
            }
            catch (Exception e)
            {

            }
            return null;
        }

        /// <summary>
        /// The add support log async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        private bool AddSupportLogAsync(int appointmentId)
        {
            var supportAppointment = new AppointmentSupportLog
            {
                Active = true,
                AppointmentId = appointmentId,
                AssigneeId = null,
                Audio = null,
                CreatedDate = DateTime.Now,
                Comments = null,
                Document = null,
                Invoice = null,
                Video = null,
                CallStatus = null
            };

            return this.unitOfWork.AppointmentSupportLogRepository.Insert(supportAppointment);
        }

        /// <summary>
        /// The delete support log async.
        /// </summary>
        /// <param name="appointmentId">
        /// The appointment id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>.
        /// </returns>
        private async Task<int> DeleteSupportLogAsync(int appointmentId)
        {
            try
            {
                var query = $@"Delete from ""AppointmentSupportLog"" where ""AppointmentId"" = {appointmentId}";
                return await this.unitOfWork.Current.ExecuteAsync(query);
            }
            catch (Exception)
            {
                return 0;
            }
        }

        /// <summary>
        /// The get appointment number.
        /// </summary>
        /// <param name="patientType">
        /// The patient Type.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        private async Task<string> GetAppointmentNo(string patientType)
        {
            // Ex: IP20010005/OP20010005
            var appointmentNumber = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<string>($@"SELECT ""AppointmentNo"" FROM ""Appointment"" where ""AppointmentNo"" ILIKE '%{patientType}%' ORDER BY ""AppointmentId"" DESC");
            return CoreFilter.GetTransactionId(appointmentNumber, patientType);
        }

        /// <inheritdoc />
        public async Task<int> FindReceiptByAppointmentId(int appointmentId)
        {
            var query = $@"select R.""ReceiptId""
                    from ""Patient"" P
                    join ""Appointment"" A on A.""PatientId"" = P.""PatientId""
                    join ""Receipt"" R on R.""AppointmentId"" = A.""AppointmentId""
                    where A.""AppointmentId""={appointmentId}";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>(query);

        }

        /// <inheritdoc/>
        public async Task<Appointment> CheckInAsync(int appointmentId)
        {
            var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == appointmentId);
            appointment.CheckedIn = DateTime.UtcNow.AddMinutes(330);
            await this.unitOfWork.Appointments.UpdateAsync(appointment);
            return null;

        }

        /// <inheritdoc/>
        public async Task<Appointment> CheckOutAsync(int appointmentId, DateTime? checkedIn)
        {
            var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == appointmentId);
            appointment.CheckedOut = DateTime.UtcNow.AddMinutes(330);
            appointment.Tat = (int?)((appointment.CheckedOut ?? DateTime.Now) - (appointment.CheckedIn ?? DateTime.Now)).TotalMinutes;
            await this.unitOfWork.Appointments.UpdateAsync(appointment);

            return null;

        }
        public async Task<int> AddAppointmentHangfireAsync(AppointmentHangfireMapModel model)
        {
            var appointementHangfire = new AppointmentHangfireMap()
            {
                AppointmentId = model.AppointmentId,
                CreatedDate = DateTime.Now,
                Status = model.Status,
                SmsSent = false,
                EmailSent = false,
                AppointmentDate = model.AppointmentDate,
                AppointmentTime = model.AppointmentTime,
            };
            try
            {
                appointementHangfire.AHMapId = await this.unitOfWork.AppointmentHangfireMaps.InsertAsync(appointementHangfire);
            }
            catch (Exception e)
            {
                e.Message.ToString();
            }

            return appointementHangfire.AHMapId;
        }

        public async Task<IEnumerable<AppointmentTransactionModel>> FetchPendingSalucroTransactions()
        {
            var query = $@"Select * from ""AppointmentTransaction"" where ""SalucroStatusCode"" =1201 and ""StatusCheckInProgress""=false";
            return await this.unitOfWork.Current.QueryAsync<AppointmentTransactionModel>(query);
        }

        public async Task<int> UpdateSalucroStatusCheckProgress(int respectiveId, bool statusCheckInProgress)
        {
            var upadteQuery = $@"Update ""AppointmentTransaction"" Set ""StatusCheckInProgress""={statusCheckInProgress} where ""AppointmentId""={respectiveId}";
            return await this.unitOfWork.Current.ExecuteAsync(upadteQuery);
        }

        public async Task<int> UpadateSalucroPaymentStatusAsync(int respectiveId)
        {
            try
            {
                var transaction = await this.appointmentTransactionsServices.FetchAsync(respectiveId);
                var voucherNumber = await this.appointmentTransactionsServices.GetVoucherNumber();
                var upadteQuery = $@"Update ""AppointmentTransaction"" Set ""SalucroStatusCode""=1200 , ""VoucherNumber""='{voucherNumber}' where ""AppointmentId""={respectiveId}";
                await this.unitOfWork.Current.ExecuteAsync(upadteQuery);
                switch (transaction.ReceiptAreaTypeId)
                {
                    case 1:
                        var saleHeader = await this.unitOfWork.PharmacySaleHeaders.FindAsync(x => x.PharmacySaleHeaderId == respectiveId);

                        var saleQuery = $@"UPDATE ""PharmacySaleHeader"" SET ""PayTypeId"" = 18,""PaymentStatus"" = true,""ModifiedBy"" = {saleHeader.CreatedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""PharmacySaleHeaderId""= {respectiveId}";
                        await this.unitOfWork.Current.ExecuteAsync(saleQuery);

                        var saleReceipt = new Receipt()
                        {
                            Active = true,
                            Cost = Convert.ToDouble(transaction.SettledAmount),
                            CreatedBy = saleHeader.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = 18,
                            PaymentDetails = saleHeader.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.Pharmacy,
                            RespectiveId = saleHeader.PharmacySaleHeaderId,
                            TransactionId = transaction.AppointmentTransactionId
                            //MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                        };
                        saleReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(saleReceipt);
                        break;
                    case 2: break;
                    case 3: break;
                    case 4:
                        var appointment = await this.FindAsync(respectiveId);

                        var appointmentQuery = $@"UPDATE ""Appointment"" SET ""PayTypeId"" = 18,""PaymentStatus"" = true,""ModifiedBy"" = {appointment.CreatedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AppointmentId""= {appointment.AppointmentId}";
                        await this.unitOfWork.Current.ExecuteAsync(appointmentQuery);

                        var apptReceipt = new Receipt()
                        {
                            Active = true,
                            Cost = Convert.ToDouble(transaction.SettledAmount),
                            CreatedBy = appointment.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = 18,
                            PaymentDetails = appointment.PaymentNumber,
                            IsAppointmentReceipt = true,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.Appointment,
                            RespectiveId = appointment.AppointmentId,
                            TransactionId = transaction.AppointmentTransactionId
                            //MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                        };
                        apptReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(apptReceipt);

                        var patient = await this.patientService.FindAsync(appointment.PatientId);
                        if (patient.PaymentStatus != true)
                        {
                            var upadtePatientQuery = $@"Update ""AppointmentTransaction"" Set ""SalucroStatusCode""=1200 , ""VoucherNumber""='{voucherNumber}' where ""AppointmentId""={patient.PatientId}";
                            await this.unitOfWork.Current.ExecuteAsync(upadtePatientQuery);
                            var umrNo = await this.patientService.GetLatestUMRNo();
                            var patientQuery = "";
                            if (patient.TempPatient == true)
                            {
                                patientQuery = $@"UPDATE ""Patient"" SET ""PayTypeId"" = 18,""PaymentStatus"" = true,""TempPatient"" = false, ""UMRNo""='{umrNo}', ""ModifiedBy"" = {appointment.CreatedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""PatientId""= {patient.PatientId}";
                            }
                            else
                            {
                                patientQuery = $@"UPDATE ""Patient"" SET ""PayTypeId"" = 18,""PaymentStatus"" = true,""TempPatient"" = false, ""ModifiedBy"" = {appointment.CreatedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""PatientId""= {patient.PatientId}";
                            }
                            await this.unitOfWork.Current.ExecuteAsync(patientQuery);
                            var patTransaction = await this.appointmentTransactionsServices.FetchAsync(patient.PatientId);
                            var patReceipt = new Receipt()
                            {
                                Active = true,
                                Cost = Convert.ToDouble(patTransaction.SettledAmount),
                                CreatedBy = (int)appointment.CreatedBy,
                                CreatedDate = DateTime.Now,
                                IsAdvance = false,
                                IsRefunded = false,
                                PayTypeId = 18,
                                PaymentDetails = appointment.PaymentNumber,
                                ReceiptTypeId = ReceiptType.Cash,
                                ReceiptAreaTypeId = ReceiptAreaType.PatientRegistration,
                                RespectiveId = patient.PatientId,
                                TransactionId = patTransaction.AppointmentTransactionId
                                //MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                            };
                            patReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(patReceipt);
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                return 0;
            }

            return 1;
        }


        /// <inheritdoc />
        public async Task<AppointmentModel> FetchForInvoiceAsync(int appointmentId, string status)
        {
            var where = $@" WHERE 1 = 1 and apt.""AppointmentId""={appointmentId} ";
            var query = "";
            if (status == "Cancel")
            {
                where += $@" AND  RC.""ReceiptAreaTypeId""=5";

                query = $@"select pat.*,pat.""FullName"" as ""PatientName"",pat.""DateOfBirth"" as ""PatientDateOfBirth"", pat.""Age"" AS ""PatientAge"",pat.""Gender"" as ""PatientGender"",
                        pat.""PaymentStatus"" as ""PatientPaymentStatus"", pat.""Mobile"" as ""PatientMobile""
               ,IDP.""IdProofName"", Pr.""FullName"" AS ""ProviderName"", D.""DepartmentName"",Sp.""SpecializationName"",
                        APTP.""Name"" as ""AppointmentTypeName""
                      ,apt.*, apt.""PaymentNumber"" ,apt.""Amount"", apt.""Discount"",apt.""Total"",
                     PT.""PayTypeName"",ct.""ChargeName"" AS ""ChargeTypesName"",cunpra.""CurrencySymbol""
                    ,RC.""Cost"" as ""AptRefundAmt"",RC.""ReceiptId"",RC.""CreatedDate"" as ""ReceiptDate""
                    , A.""FullName"" as ""ReceiptCreatedByName"",apt.""IsHealthCard""
                    from ""Patient"" pat
                JOIN ""Appointment"" apt on apt.""PatientId"" = pat.""PatientId"" --- apt amt
                LEFT JOIN ""Receipt"" RC on RC.""RespectiveId"" = apt.""AppointmentId"" ---can amt
                Left join ""Account"" A on A.""AccountId""=RC.""CreatedBy""
                left JOIN ""Provider"" Pr on Pr.""ProviderId""=apt.""ProviderId""
                left Join ""Specialization"" Sp on Sp.""SpecializationId""=apt.""SpecializationId""
                LEFT JOIN ""Department"" D on D.""DepartmentId"" = pr.""DepartmentId""
                left JOIN ""ChargeTypes"" ct ON ct.""ChargeTypesId"" = apt.""ChargeTypesId""
                LEFT JOIN ""IdProof"" IDP on IDP.""IdProofId""	= pat.""IdProofId""
                LEFT JOIN ""AppointmentType"" APTP on APTP.""AppointmentTypeId"" = apt.""AppointmentTypeId""
                LEFT JOIN ""PayType"" PT on PT.""PayTypeId""=RC.""PayTypeId""
                LEFT JOIN ""ProviderAvailability"" PA ON PA.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND PA.""Active"" IS TRUE
				LEFT JOIN ""Location"" PAL ON PAL.""LocationId"" = PA.""LocationId"" AND PAL.""Active"" IS TRUE
                LEFT JOIN ""Country"" cunpra ON cunpra.""CountryId"" = PAL.""CountryId"" AND cunpra.""Active"" IS TRUE
                    {where}";
            }
            else
            {
                query = $@"select pat.*,pat.""FullName"" as ""PatientName"",pat.""DateOfBirth"" as ""PatientDateOfBirth"", pat.""Age"" AS ""PatientAge"",pat.""Gender"" as ""PatientGender"",
                        pat.""PaymentStatus"" as ""PatientPaymentStatus"", pat.""Mobile"" as ""PatientMobile""
               ,IDP.""IdProofName"", Pr.""FullName"" AS ""ProviderName"", D.""DepartmentName"",Sp.""SpecializationName"",
                APTP.""Name"" as ""AppointmentTypeName"" ,apt.*, apt.""PaymentNumber"" ,
				apt.""Amount"", apt.""Discount"",coalesce(SUM(RC.""Cost""),0) ""Total"",--MB.""NetTotal"",
				pat.""Amount"" ""PatAmount"", pat.""DiscountInRupees"" ""PatDiscount"",coalesce(SUM(R.""Cost""),0) ""PatientRegistrationAmount"",--M.""NetTotal"" ""PatNetTotal"",
                     PT.""PayTypeName"",ct.""ChargeName"" AS ""ChargeTypesName"",cunpra.""CurrencySymbol""
                   ,R.""ReceiptId"",R.""CreatedDate"" as ""ReceiptDate"",apt.""IsHealthCard"",
                    A.""FullName"" as ""ReceiptCreatedByName"",( case when pat.""AppointmentId"" = apt.""AppointmentId"" then apt.""AppointmentId"" else null end) as ""ReferenceId""
                    from ""Patient"" pat
                JOIN ""Appointment"" apt on apt.""PatientId"" = pat.""PatientId""
				left JOIN ""Receipt"" RC on RC.""RespectiveId"" = apt.""AppointmentId"" and RC.""ReceiptAreaTypeId""=4 and RC.""ReceiptTypeId""=1 --- apt amt
                left JOIN ""Receipt"" R on R.""RespectiveId"" = pat.""PatientId"" and R.""ReceiptAreaTypeId""=3 and R.""ReceiptTypeId""=1 --reg amt
                Left join ""Account"" A on A.""AccountId""=R.""CreatedBy""
                left JOIN ""Provider"" Pr on Pr.""ProviderId""=apt.""ProviderId""
                left Join ""Specialization"" Sp on Sp.""SpecializationId""=apt.""SpecializationId""
                LEFT JOIN ""Department"" D on D.""DepartmentId"" = pr.""DepartmentId""
                left JOIN ""ChargeTypes"" ct ON ct.""ChargeTypesId"" = apt.""ChargeTypesId""
                LEFT JOIN ""IdProof"" IDP on IDP.""IdProofId""	= pat.""IdProofId""
                LEFT JOIN ""AppointmentType"" APTP on APTP.""AppointmentTypeId"" = apt.""AppointmentTypeId""
                LEFT JOIN ""PayType"" PT on PT.""PayTypeId""=apt.""PayTypeId""
                LEFT JOIN ""ProviderAvailability"" PA ON PA.""ProviderAvailabilityId"" = apt.""ProviderAvailabilityId"" AND PA.""Active"" IS TRUE
				LEFT JOIN ""Location"" PAL ON PAL.""LocationId"" = PA.""LocationId"" AND PAL.""Active"" IS TRUE
                LEFT JOIN ""Country"" cunpra ON cunpra.""CountryId"" = PAL.""CountryId"" AND cunpra.""Active"" IS TRUE
                     {where}
					 group by pat.""PatientId"",IDP.""IdProofName"", Pr.""FullName"", D.""DepartmentName"",Sp.""SpecializationName"",
                 	APTP.""Name"" ,apt.""AppointmentId"", PT.""PayTypeName"",ct.""ChargeName"",cunpra.""CurrencySymbol"", R.""ReceiptId"",
                 	A.""FullName""";
            }
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<AppointmentModel>(query);
        }

        public async Task<int> CancelAppointmentAsync(AppointmentModel model, string type, string transaction, string transactionId, int? salucroStatusCode, string salucroTransactionId, int? modifiedBy, string reason)
        {
            var fortransaction = this.unitOfWork.BeginTransaction();
            //to get bill
            var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.ReceiptAreaTypeId == (int)ReceiptAreaType.Appointment && x.ModuleId == model.AppointmentId); //need to check more

            try
            {
                if (!string.IsNullOrEmpty(type))
                {
                    var appointmentTransaction = new AppointmentTransaction
                    {
                        AppointmentId = model.AppointmentId,
                        Active = true,
                        Transaction = transaction,
                        TransactionId = transactionId,
                        VoucherNumber = await this.appointmentTransactionsServices.GetVoucherNumber(),
                        BankReference = "",
                        BankCode = "",
                        PaymentModeId = 1,
                        PaymentId = 0,
                        TransactionDate = DateTime.Now,
                        SalucroStatusCode = salucroStatusCode,
                        SalucroTransactionId = salucroTransactionId,
                        SettledAmount = model.Total,
                        CreatedBy = (int)modifiedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = model.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Refund,
                        ReceiptAreaTypeId = (int)ReceiptAreaType.CancelAppointment,
                        PatientId = model.PatientId
                        // PayStatus-while partial in acancel

                    };
                    appointmentTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(appointmentTransaction, fortransaction);

                    if (appointmentTransaction.AppointmentTransactionId == 0)
                    {
                        fortransaction.Rollback();
                        return 0;
                    }
                    else
                    {
                        var appReceipt = new Receipt
                        {
                            Active = true,
                            Cost = Convert.ToDouble(model.Total),
                            CreatedBy = (int)model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)model.PayTypeId,
                            PaymentDetails = model.PaymentNumber,
                            IsAppointmentReceipt = true,
                            ReceiptTypeId = ReceiptType.Refund,
                            ReceiptAreaTypeId = ReceiptAreaType.CancelAppointment,
                            RespectiveId = model.AppointmentId,
                            TransactionId = appointmentTransaction.AppointmentTransactionId,
                            MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0

                        };
                        appReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(appReceipt, fortransaction);
                        if (appReceipt.ReceiptId == 0)
                        {
                            fortransaction.Rollback();
                            return 0;
                        }
                    }
                }
                else
                {
                    if (model.CancelType == "CAppC")
                    {
                        var appointmentTransaction = new AppointmentTransaction
                        {
                            AppointmentId = model.AppointmentId,
                            Transaction = transaction ?? "",
                            TransactionDate = DateTime.Now,
                            TransactionId = transactionId != null ? transactionId : await this.appointmentTransactionsServices.GetATransactionId(),
                            VoucherNumber = await this.appointmentTransactionsServices.GetVoucherNumber(),
                            BankReference = "",
                            BankCode = "",
                            Active = true,
                            PaymentModeId = 1,
                            PaymentId = 0,
                            SalucroStatusCode = salucroStatusCode,
                            SalucroTransactionId = salucroTransactionId,
                            SettledAmount = model.Total,
                            CreatedBy = (int)modifiedBy,
                            CreatedDate = DateTime.Now,
                            LocationId = model.LocationId,
                            ReceiptTypeId = (int)ReceiptType.Refund,
                            ReceiptAreaTypeId = (int)ReceiptAreaType.CancelAppointment,
                            PatientId = model.PatientId,
                            //PayStatus in cancel

                        };
                        appointmentTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(appointmentTransaction, fortransaction);
                        if (appointmentTransaction.AppointmentTransactionId == 0)
                        {
                            fortransaction.Rollback();
                            return 0;
                        }
                        else
                        {
                            var appReceipt = new Receipt
                            {
                                Active = true,
                                Cost = Convert.ToDouble(model.Total),
                                CreatedBy = (int)model.CreatedBy,
                                CreatedDate = DateTime.Now,
                                IsAdvance = false,
                                IsRefunded = false,
                                PayTypeId = (int)model.PayTypeId,
                                PaymentDetails = model.PaymentNumber,
                                IsAppointmentReceipt = true,
                                ReceiptTypeId = ReceiptType.Refund,
                                ReceiptAreaTypeId = ReceiptAreaType.CancelAppointment,
                                RespectiveId = model.AppointmentId,
                                TransactionId = appointmentTransaction.AppointmentTransactionId,
                                MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0

                            };
                            appReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(appReceipt, fortransaction);
                            if (appReceipt.ReceiptId == 0)
                            {
                                fortransaction.Rollback();
                                return 0;
                            }
                        }
                    }
                }
                //update bill refund
                if (getbillrecord != null)
                {
                    getbillrecord.Refund += (double)Convert.ToDouble(model.Total);
                    getbillrecord.Active = false;
                    await this.unitOfWork.MasterBill.UpdateAsync(getbillrecord);
                }
                var response = await this.CancelAsync(model.AppointmentId, (int)modifiedBy, reason);

                if (response == 0)
                {
                    fortransaction.Rollback();
                    return 0;
                }
            }
            catch (Exception e)
            {
                throw e;
            }
            fortransaction.Commit();
            return 1;
        }

        public async Task<int> RefundAppointmentCancelAmountAsync(AppointmentModel model)
        {

            var appointmentReceipt = await this.FetchForInvoiceAsync((int)model.AppointmentId, model.Status);

            model.Status = "Cancel";
            var appointmentCancelReceipt = await this.FetchForInvoiceAsync((int)model.AppointmentId, model.Status);

            if (appointmentReceipt != null && appointmentCancelReceipt == null)
            {
                try
                {
                    //to get bill
                    var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == appointmentReceipt.PatientId && x.ReceiptAreaTypeId == (int)ReceiptAreaType.Appointment && x.ModuleId == model.AppointmentId); //need to check more

                    var appointmentTransaction = new AppointmentTransaction
                    {
                        AppointmentId = model.AppointmentId,
                        Transaction = "",
                        TransactionDate = DateTime.Now,
                        TransactionId = await this.appointmentTransactionsServices.GetATransactionId(),
                        VoucherNumber = await this.appointmentTransactionsServices.GetVoucherNumber(),
                        BankReference = "",
                        BankCode = "",
                        Active = true,
                        PaymentModeId = 1,
                        PaymentId = 0,
                        SettledAmount = model.Amount,
                        CreatedBy = (int)model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = model.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Refund,
                        ReceiptAreaTypeId = (int)ReceiptAreaType.CancelAppointment,
                        PatientId = appointmentReceipt.PatientId
                    };
                    appointmentTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(appointmentTransaction);
                    if (appointmentTransaction.AppointmentTransactionId == 0)
                    {
                        return 0;
                    }
                    else
                    {
                        var appReceipt = new Receipt
                        {
                            Active = true,
                            Cost = Convert.ToDouble(model.Total),
                            CreatedBy = (int)model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            //  PayTypeId = (int)model.PayTypeId,
                            // PaymentDetails = model.PaymentNumber,
                            IsAppointmentReceipt = true,
                            ReceiptTypeId = ReceiptType.Refund,
                            ReceiptAreaTypeId = ReceiptAreaType.CancelAppointment,
                            RespectiveId = model.AppointmentId,
                            TransactionId = appointmentTransaction.AppointmentTransactionId,
                            MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0//to remind
                        };
                        appReceipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(appReceipt);
                        if (appReceipt.ReceiptId == 0)
                        {
                            return 0;
                        }
                    }
                }
                catch (Exception e) { }

            }

            return 1;
        }

        public async Task<IEnumerable<AppointmentModel>> FindPatientAppointmentAsync(PatientAppointmentFilterModel model)
        {
            var where = $@"where apt.""Status""<>'C'";
            if (model.PatientId != 0 && model.PatientId != null)
            {
                where += $@" and apt.""PatientId""={model.PatientId}";
            }
            if (model.AdmissionDate != null)
            {
                where += $@" and apt.""AppointmentDate"" >= '{model.AdmissionDate}'";
            }
            if (model.AdmissionTime != null)
            {
                where += $@" and apt.""AppointmentTime"" >='{model.AdmissionTime}'";

            }
            var query = $@" select apt.""AppointmentId"",apt.""AppointmentNo"",apt.""AppointmentDate"",apt.""AppointmentTime"",p.""FullName"" as ""PatientName"",pr.""FullName"" as ""ProviderName"" from ""Appointment"" apt
                            left join ""Patient"" p on p.""PatientId"" = apt.""PatientId""
left join ""Provider"" pr on pr.""ProviderId"" = apt.""ProviderId""
                            {where}   ";
            return await this.unitOfWork.Current.QueryAsync<AppointmentModel>(query);
        }

        public async Task<IEnumerable<AppointmentTransactionModel>> FetchTransactionDataAsync(int logId)
        {
            var query = $@"SELECT * FROM (select P.""PayTypeName"",AT.*, (case when AT.""Transaction""<>'' and AT.""Transaction"" is not null then AT.""Transaction""::json->'custom'::TEXT ELSE '0' END)::TEXT ""LogId"" from ""AppointmentTransaction"" AT
                left join ""Receipt"" R on R.""TransactionId""=AT.""AppointmentTransactionId""
                left join ""PayType"" P on P.""PayTypeId""=R.""PayTypeId"") A
				WHERE A.""LogId""='""{logId}""'::text";
            return await this.unitOfWork.Current.QueryAsync<AppointmentTransactionModel>(query);
        }

        public async Task<IEnumerable<AppointmentTransactionModel>> FetchTransactionAsync(int appointmentId, int type)
        {
            var receiptAreaType = 0;
            switch (type)
            {
                case 2:
                    receiptAreaType = (int)ReceiptAreaType.Appointment;
                    break;
                case 3:
                    receiptAreaType = (int)ReceiptAreaType.Pharmacy;
                    break;
                case 4:
                    receiptAreaType = (int)ReceiptAreaType.Labs;
                    break;
                case 9:
                case 5:
                    receiptAreaType = (int)ReceiptAreaType.ScanAppointment;
                    break;
                case 8:
                    receiptAreaType = (int)ReceiptAreaType.Services;
                    break;
            }
            var query = $@"SELECT P.""PayTypeName"",A.* from ""AppointmentTransaction"" A
                left join ""Receipt"" R on R.""TransactionId""=A.""AppointmentTransactionId""
                left join ""PayType"" P on P.""PayTypeId""=R.""PayTypeId""
				WHERE A.""AppointmentId""={appointmentId}
                and A.""ReceiptAreaTypeId"" ={receiptAreaType} and A.""ReceiptTypeId""=1 ";
            return await this.unitOfWork.Current.QueryAsync<AppointmentTransactionModel>(query);
        }

        public async Task<int> CompletePartialPaymentAsync(AppointmentModel model)
        {
            var fortransaction = this.unitOfWork.BeginTransaction();
            var receiptAreaType = 0;
            char? payStatus = 'P';
            switch (model.ModuleType)
            {
                case 2:
                    receiptAreaType = (int)ReceiptAreaType.Appointment;
                    var appointment = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == model.AppointmentId);
                    if (appointment != null && appointment.PaymentType == null)
                    {
                        appointment.PaymentType = payStatus;
                        appointment.PaymentStatus = true;
                        await this.unitOfWork.Appointments.UpdateAsync(appointment, fortransaction);
                    }
                    break;
                case 3:
                    receiptAreaType = (int)ReceiptAreaType.Pharmacy;
                    var phar = await this.unitOfWork.PharmacySaleHeaders.FindAsync(x => x.PharmacySaleHeaderId == model.AppointmentId);
                    if (phar != null && phar.PaymentType == null)
                    {
                        phar.PaymentType = payStatus;
                        phar.PaymentStatus = true;
                        await this.unitOfWork.PharmacySaleHeaders.UpdateAsync(phar, fortransaction);
                    }
                    break;
                case 4:
                    receiptAreaType = (int)ReceiptAreaType.Labs;
                    var lab = await this.unitOfWork.NewLabBookingHeaders.FindAsync(x => x.NewLabBookingHeaderId == model.AppointmentId);
                    if (lab != null && lab.PaymentType == null)
                    {
                        lab.PaymentType = payStatus;
                        await this.unitOfWork.NewLabBookingHeaders.UpdateAsync(lab, fortransaction);
                    }
                    break;
                case 9:
                case 5:
                    receiptAreaType = (int)ReceiptAreaType.ScanAppointment;
                    var scan = await this.unitOfWork.BookScanAppointments.FindAsync(x => x.BookScanAppointmentId == model.AppointmentId);
                    if (scan != null && scan.PaymentType == null)
                    {
                        scan.PaymentType = payStatus;
                        scan.PaymentStatus = true;
                        await this.unitOfWork.BookScanAppointments.UpdateAsync(scan, fortransaction);
                    }
                    break;
                case 8:
                    receiptAreaType = (int)ReceiptAreaType.Services;
                    break;
            }
            var bill = await this.unitOfWork.MasterBill.FindAsync(x => x.ModuleId == model.AppointmentId && x.ReceiptAreaTypeId == receiptAreaType && x.BillStatusTypeId == 2 && x.PatientId == model.PatientId);
            var commonTransaction = new AppointmentTransaction
            {
                AppointmentId = model.AppointmentId,
                Active = true,
                Transaction = model.Transaction ?? "",
                TransactionId = model.TransactionId ?? await this.appointmentTransactionsServices.GetATransactionId(),
                VoucherNumber = model.SalucroStatusCode == 1201 ? null : await this.appointmentTransactionsServices.GetVoucherNumber(),
                BankReference = "",
                BankCode = "",
                PaymentModeId = 1,
                PaymentId = 0,
                TransactionDate = DateTime.Now,
                SalucroStatusCode = model.SalucroStatusCode,
                SalucroTransactionId = model.SalucroTransactionId,
                SettledAmount = model.TotalAmount,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                LocationId = model.LocationId,
                ReceiptTypeId = (int)ReceiptType.Cash,
                ReceiptAreaTypeId = receiptAreaType,
                PatientId = model.PatientId,
                PayStatus = payStatus
            };
            commonTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTransaction, fortransaction);

            if (commonTransaction.AppointmentTransactionId == 0)
            {
                fortransaction.Rollback();
                return 0;
            }
            else
            {
                var receipt = new Receipt
                {
                    Active = true,
                    Cost = Convert.ToDouble(model.TotalAmount),
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    IsAdvance = false,
                    IsRefunded = false,
                    PayTypeId = (int)model.PayTypeId,
                    PaymentDetails = model.PaymentNumber,
                    IsAppointmentReceipt = (ReceiptAreaType)receiptAreaType == ReceiptAreaType.Appointment ? true : false,
                    ReceiptTypeId = ReceiptType.Cash,
                    ReceiptAreaTypeId = (ReceiptAreaType)receiptAreaType,
                    RespectiveId = model.AppointmentId,
                    TransactionId = commonTransaction.AppointmentTransactionId,
                    MasterBillId = bill.MasterBillId
                };
                receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt, fortransaction);
                if (receipt.ReceiptId == 0)
                {
                    fortransaction.Rollback();
                    return 0;
                }
                //begin-to update bill status as genereated.
                var allreceiptforbill = await this.unitOfWork.Receipt.FindAllAsync(x => x.MasterBillId == receipt.MasterBillId);
                allreceiptforbill.ToList();
                var receiptcostsum = 0.0;
                foreach (var item in allreceiptforbill.ToList())
                {
                    receiptcostsum += item.Cost;
                }
                var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == receipt.MasterBillId);
                if (receiptcostsum == getbill.NetTotal)
                {
                    if (receiptAreaType == 4)
                    {
                        var appt = await this.unitOfWork.Appointments.FindAsync(x => x.AppointmentId == model.AppointmentId);
                        appt.PaymentType = 'F';
                        appt.ModifiedDate = DateTime.Now;
                        appt.Total = (decimal)receiptcostsum;
                        await this.unitOfWork.Appointments.UpdateAsync(appt, fortransaction);
                    }
                    else if (receiptAreaType == 10)
                    {
                        var scanAppt = await this.unitOfWork.BookScanAppointments.FindAsync(x => x.BookScanAppointmentId == model.AppointmentId);
                        scanAppt.PaymentType = 'F';
                        scanAppt.ModifiedDate = DateTime.Now;
                        await this.unitOfWork.BookScanAppointments.UpdateAsync(scanAppt, fortransaction);
                    }
                    else if (receiptAreaType == 1)
                    {
                        var pharma = await this.unitOfWork.PharmacySaleHeaders.FindAsync(x => x.PharmacySaleHeaderId == model.AppointmentId);
                        pharma.PaymentType = 'F';
                        pharma.ModifiedDate = DateTime.Now;
                        await this.unitOfWork.PharmacySaleHeaders.UpdateAsync(pharma, fortransaction);
                    }
                    else if (receiptAreaType == 8)
                    {
                        var lab = await this.unitOfWork.NewLabBookingHeaders.FindAsync(x => x.NewLabBookingHeaderId == model.AppointmentId);
                        lab.PaymentType = 'F';
                        lab.ModifiedDate = DateTime.Now;
                        await this.unitOfWork.NewLabBookingHeaders.UpdateAsync(lab, fortransaction);
                    }
                    getbill.BillStatusTypeId = (int)BillStatusType.Generated; //
                    getbill.ModifiedBy = model.CreatedBy;
                    getbill.ModifiedDate = DateTime.Now;
                    await this.unitOfWork.MasterBill.UpdateAsync(getbill, fortransaction);

                    commonTransaction.PayStatus = 'F';
                    await this.unitOfWork.AppointmentTransactions.UpdateAsync(commonTransaction, fortransaction);

                }
                //end-to update bill status as genereated.
                fortransaction.Commit();
                return 1;
            }
        }

        /// <inheritdoc />
        public Task<IEnumerable<AppointmentModel>> FetchViewAsync(AppointmentFilterModel model)
        {
            var where = $@"where 1=1";

            if (model.PatientId != null)
            {
                where += $@" AND Ap.""PatientId"" = {model.PatientId}";
            }

            if (model.LocationId != null)
            {
                where += $@" AND Ap.""LocationId"" = {model.LocationId}";
            }

            if (!string.IsNullOrEmpty(model.AppointmentNo))
            {
                where += $@" AND Ap.""AppointmentNo"" ILIKE '%{model.AppointmentNo}%'";
            }
            if (model.Gender != null)
            {
                where += $@" AND Pa.""Gender"" = '{model.Gender}'";
            }
            if (!string.IsNullOrEmpty(model.Status))
            {
                where += $@" AND Ap.""Status"" = '{model.Status}'";
            }
            //else
            //{
            //    if (model.ResultsType == "Pending")
            //    {
            //        where += $@" AND Ap.""Status"" != 'C'";
            //    }

            //}
            if (model.Ids != null)
            {
                where += $@" AND Ap.""ProviderId"" in ({model.Ids}) ";
            }
            if (model.SIds != null)
            {
                where += $@" and Ap.""SpecializationId"" in ({model.SIds})";
            }
            if (model.ProviderId != null)
            {
                where += $@" AND Ap.""ProviderId"" = {model.ProviderId}";
            }
            if (model.PaymentType != null)
            {
                where += $@" and Ap.""PaymentType"" = '{model.PaymentType}' ";
            }
            if (model.SpecializationId != null)
            {
                where += $@" AND Ap.""SpecializationId"" = {model.SpecializationId}";
            }

            if (model.PaymentStatus != null)
            {
                where += $@" AND Ap.""PaymentStatus"" = {model.PaymentStatus}";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND Ap.""AppointmentDate""::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND Ap.""AppointmentDate""::DATE <= '{model.ToDate}'::DATE";
            }

            if (!string.IsNullOrEmpty(model.FromDate) && string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND Ap.""AppointmentDate""::DATE >= '%{model.FromDate}%'";
            }

            if (model.VisitTypeId != null)
            {
                where += $@" AND Ap.""VisitTypeId"" = {model.VisitTypeId}";
            }

            if (model.ConsultationTypeId != null)
            {
                where += $@" AND Ap.""ConsultationTypeId"" = {model.ConsultationTypeId}";
            }

            if (model.ChargeTypesId != null)
            {
                where += $@" AND Ap.""ChargeTypesId"" = {model.ChargeTypesId}";
            }

            var query = $@" SELECT Ap.""PaymentStatus"",Ap.""PaymentType"", Ap.""Status"", Ap.""IsSalucroAppointment"",Ap.""AppointmentId"",Ap.""ProviderId"",Ap.""SpecializationId"",s.""SpecializationName"",Po.""FullName"" ""ProviderName"",Ap.""LocationId"",Ap.""PatientId"",Ap.""DepartmentId"",Pa.""FullName"" as ""PatientName"",Ap.""CheckedIn""::text,Ap.""ProviderLocationId"",Ap.""VisitTypeId"",Ap.""PaymentNumber"",
                                    Ap.""ProviderAvailabilityId"",Ap.""ConsultationTypeId"",
                                    Ap.""CheckedOut""::text,  CONCAT(""AppointmentDate"", 'T', ""AppointmentTime"") as ""AppointmentStartDateTime"",Ad.""VisitorName""  as ""AppointmentTypeName"", TO_CHAR(Ap.""AppointmentDate"", 'MM/DD/YYYY') || ' ' || TO_CHAR(Ap.""AppointmentTime"", 'hh12:mi AM') as ""AppointmentDateTime"" ,
                                   Ap.""AppointmentTime"",
                                    CONCAT(""AppointmentDate"", 'T', ""AppointmentEndTime"") as ""AppointmentEndDateTime""
                                    , Ap.""TokenNumber"", Ap.""EncounterType""::text,
                          Pa.""Age"" as ""PatientAge"",Pa.""Gender""::text,Pa.""FatherOrHusband"",Pa.""UMRNo"",Pa.""Mobile"" ""PatientMobile"",Pa.""AadharNo"",Pa.""ReferredByName"",Ap.""AppointmentNo"",
                        Ap.""AppointmentDate"",Ap.""ChargeType"", Ap.""Discount"",Ap.""Total"",Ap.""Amount"",Po.""FullName"" as ""DoctorName"",
                        Dp.""DepartmentName"",Pa.""StreetAddress"",Pa.""AddressLine2"",Pa.""City"",Pa.""State"",Pa.""Zipcode"",Ce.""ChargeName"",Pe.""PayTypeName"",cun.""CountryCode"" ""PatientCountryCode""
                                    from ""Appointment"" Ap
                                    join ""Provider"" Po on Po.""ProviderId""=Ap.""ProviderId""
                                    join ""Specialization"" s on s.""SpecializationId"" = Ap.""SpecializationId""
                                    join ""Department"" Dp on Dp.""DepartmentId""=Po.""DepartmentId""
		                            join ""Patient"" Pa on Pa.""PatientId"" = Ap.""PatientId""
                                    LEFT JOIN ""Country"" cun ON cun.""CountryId"" = Pa.""CountryId"" AND cun.""Active"" IS TRUE
                                    left join ""IdProof"" Ip on Ip.""IdProofId"" = Pa.""IdProofId""
                                    join ""ChargeTypes"" Ce on Ce.""ChargeTypesId"" = Ap.""ChargeTypesId""
                                    join ""VisitType"" Ad on Ad.""VisitTypeId""= Ap.""VisitTypeId""
                                    left join ""PayType"" Pe on Pe.""PayTypeId""=Ap.""PayTypeId""
                {where} and Ap.""AppointmentTime"" is not null and Ap.""AppointmentEndTime"" is not null
                and Ap.""Status"" != 'C' and Ap.""QueueStatusId"" = '7' order by Ap.""AppointmentDate"",Ap.""AppointmentTime""";

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

        /// <inheritdoc />
        public async Task<int> CancelAllAsync(string appointmentIds, string reason)
        {
            //var joinedIds = string.Join(",", model(m => (int)m.a));
            var query = $@" UPDATE ""Appointment"" set ""Status"" = 'C', ""Reason"" = '{reason}' where ""AppointmentId"" in ({appointmentIds})";
            var updated = await this.unitOfWork.Current.ExecuteAsync(query);

            if (updated == 0)
            {
                return 0;
            }
            return updated;
        }

        public async Task<int> UpdateEmergencyTypeAsync(int appointmentId)
        {
            var query = $@"UPDATE ""Appointment"" SET ""IsEmergency"" = false, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""AppointmentId""= {appointmentId}";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }

        /// <inheritdoc />
        public async Task<int> RescheduleAllAsync(string appointmentIds, DateTime appointmentDate, TimeSpan appointmentTime, TimeSpan appointmentEndTime, string appointmentNotes, int modifiedBy, int providerId, int providerAvailabilityId, int consultationTypeId, int? departmentId, int locationId, string tokenNumbers, int? specializationId, string? appointmentTimings, string? appointmentEndTimings, int? visitTypeId, int? chargeTypesId, decimal amount, decimal total, decimal discount)
        {
            try
            {
                var appointmentId = appointmentIds.Split(",");
                var aptStartTimings = appointmentTimings.Split(",");
                var aptEndTimings = appointmentEndTimings.Split(",");
                var tokenNo = tokenNumbers.Split(",");
                int updatedId = 0;

                for (int i = 0; i < appointmentId.Length; i++)
                {
                    var appointment = await this.unitOfWork.Appointments.FindAsync(m => m.AppointmentId == Convert.ToInt64(appointmentId[i]));
                    //var appointment = await this.FindAppointmentAsync(Convert.ToInt32(appointmentId[i]), false);
                    //var query = $@" Select * from ""Appointment"" where ""AppointmentId"" = '{Convert.ToInt32(aptStartTimings[i])}'";
                    //var appointment = await this.unitOfWork.Current.QueryFirstAsync<Appointment>(query);

                    if (appointment == null || appointment.AppointmentId == 0)
                    {
                        return 0;
                    }

                    appointment.Status = "R";
                    appointment.OldAppointmentDate = appointment.AppointmentDate;
                    appointment.OldAppointmentTime = appointment.AppointmentTime;
                    appointment.AppointmentDate = appointmentDate;
                    appointment.AppointmentTime = TimeSpan.Parse(aptStartTimings[i]);
                    appointment.RescheduleReason = appointmentNotes;
                    appointment.ModifiedBy = modifiedBy;
                    appointment.ProviderId = providerId;
                    //appointment.ProviderLocationId = providerLocationId;
                    appointment.ProviderAvailabilityId = providerAvailabilityId;
                    appointment.ConsultationTypeId = consultationTypeId;
                    //appointment.DepartmentId = departmentId;
                    appointment.ModifiedDate = DateTime.UtcNow;
                    appointment.LocationId = locationId;
                    appointment.AppointmentTypeId = appointment.AppointmentTypeId;
                    appointment.TokenNumber = Convert.ToInt32(tokenNo[i]);
                    appointment.SpecializationId = specializationId;
                    appointment.AppointmentEndTime = TimeSpan.Parse(aptEndTimings[i]);
                    updatedId = await this.unitOfWork.Appointments.UpdateAsync(appointment);

                    if (updatedId == 0)
                    {
                        return 0;
                    }

                    var foundNotificationAppointmentId = await this.unitOfWork.WebNotifications.FindAsync(m => m.ReferenceId == appointment.AppointmentId);
                    if (foundNotificationAppointmentId != null)
                    {
                        var findvisitType = await this.unitOfWork.Visitors.FindAsync(m => m.VisitTypeId == visitTypeId);
                        var findProviderName = await this.unitOfWork.Providers.FindAsync(m => m.ProviderId == providerId);
                        var findExistingProviderName = await this.unitOfWork.Providers.FindAsync(m => m.ProviderId == appointment.ProviderId);

                        if (findExistingProviderName == null || findProviderName == null || findvisitType == null)
                        {
                            return 0;
                        }

                        var notification = new WebNotificationModel
                        {
                            CreatedDate = appointmentDate,
                            Message = appointment.ProviderId != providerId ? $@" Appointment Rescheduled from Dr.{findExistingProviderName.FullName} to Dr.{findProviderName.FullName} ." : $@"  Appointment  Rescheduled to {findProviderName.FullName}.",
                            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
                        };
                        var res = await this.webNotificationService.UpdateAsync(notification, appointment.AppointmentId);

                    }

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

    }

}


