namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Data.Common;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Transactions;
    using System.Xml.Linq;
    using Dapper;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Hims.Domain.Configurations;
    using Hims.Domain.Entities.Enums;
    using Hims.Domain.Helpers;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels.Filters;
    using Hims.Shared.UserModels.Queue;
    using Hims.Shared.UserModels.Scan.BookAppointment;
    using Hims.Shared.UserModels.Scan.ScanAppointment;
    using Hims.Shared.UserModels.Scan.ScanMachineAvailability;
    using Hims.Shared.UserModels.Slots;

    using Shared.EntityModels;
    using Shared.UserModels;
    using PatientModel = Shared.EntityModels.PatientModel;
    using Resource = Hims.Shared.UserModels.Discharge.Resource;

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

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

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

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

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

        /// <inheritdoc cref="IBookScanAppointmentService" />
        public BookScanAppointmentService(IUnitOfWork unitOfWork,
            IFtpUploadHelper ftpUploadHelper,
            IRunningEnvironment runningEnvironment,
            IAppointmentTransactionService appointmentTransactionsServices,
            IPatientService patientServices
            )
        {
            this.unitOfWork = unitOfWork;
            this.appointmentTransactionsServices = appointmentTransactionsServices;
            this.patientServices = patientServices;
            this.runningEnvironment = runningEnvironment;
            this.ftpUploadHelper = ftpUploadHelper;
        }

        public async Task<int> CancelAsync(InsertBookScanAppointment model)
        {
            using var transaction = this.unitOfWork.BeginTransaction();

            var returnScanAppointment = await this.unitOfWork.BookScanAppointments.FindAsync(m => m.BookScanAppointmentId == model.BookScanAppointmentId);
            var receiptsData = await this.unitOfWork.Receipt.FindAllAsync(x => x.RespectiveId == returnScanAppointment.BookScanAppointmentId && x.ReceiptAreaTypeId == ReceiptAreaType.ScanAppointment && x.ReceiptTypeId == ReceiptType.Cash);
            var amountToReturn = 0.0;
            foreach (var item in receiptsData)
            {
                amountToReturn += item.Cost;
            }
            if (returnScanAppointment == null)
            {
                return -1;
            }
            //returnScanAppointment.Amount = amountToReturn;
            returnScanAppointment.Active = false;
            returnScanAppointment.Status = 'C'.ToString();
            returnScanAppointment.Reason = model.Reason;
            returnScanAppointment.ModifiedBy = model.ModifiedBy;
            returnScanAppointment.ModifiedDate = DateTime.Now;
            var res = await this.unitOfWork.BookScanAppointments.UpdateAsync(returnScanAppointment, transaction);

            if (returnScanAppointment.BookScanAppointmentId == 0)
            {
                transaction.Rollback();
                return 0;
            }
            //var query = $@"UPDATE ""BookScanAppointment"" SET ""Active"" = FALSE, ""Status"" = 'C',""Reason"" = '{reason}', ""ModifiedBy"" = {modifiedBy}, ""ModifiedDate"" = NOW() AT TIME ZONE 'UTC' WHERE ""BookScanAppointmentId""= {bookScanAppointmentId}";
            //var returnScanAppointment =   await this.unitOfWork.Current.ExecuteAsync(query, transaction);

            // to get bill 
            var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == returnScanAppointment.PatientId && x.ReceiptAreaTypeId == (int)ReceiptAreaType.ScanAppointment && x.ModuleId == model.BookScanAppointmentId); //need to check more

            if (model.PaymentStatus && returnScanAppointment.BookScanAppointmentId > 0)
            {
                //transaction for the sale return
                var commonTransaction = new AppointmentTransaction
                {
                    AppointmentId = returnScanAppointment.BookScanAppointmentId,
                    Transaction = model.Transaction ?? "",
                    TransactionDate = DateTime.Now,
                    TransactionId = model.TransactionId ?? await this.appointmentTransactionsServices.GetATransactionId(),
                    VoucherNumber = await this.appointmentTransactionsServices.GetVoucherNumber(),
                    BankReference = "",
                    BankCode = "",
                    Active = true,
                    PaymentId = 0,
                    PaymentModeId = 1,
                    SettledAmount = (decimal)amountToReturn,
                    CreatedBy = (int)model.ModifiedBy,
                    CreatedDate = DateTime.Now,
                    LocationId = (int)returnScanAppointment.LocationId,
                    ReceiptTypeId = (int)ReceiptType.Refund,
                    ReceiptAreaTypeId = (int)ReceiptAreaType.ScanAppointmentReturn,
                    SalucroStatusCode = model.SalucroStatusCode,
                    SalucroTransactionId = model.SalucroTransactionId,
                    PatientId = returnScanAppointment.PatientId,
                    // PayStatus not impl
                };
                commonTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTransaction, transaction);
                if (commonTransaction.AppointmentTransactionId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }
                var receipt = new Receipt
                {
                    Active = true,
                    Cost = (double)amountToReturn,
                    CreatedBy = (int)model.ModifiedBy,
                    CreatedDate = DateTime.Now,
                    IsAdvance = false,
                    IsRefunded = false,
                    PayTypeId = (int)returnScanAppointment.PayTypeId,
                    PaymentDetails = returnScanAppointment.PaymentNumber,
                    ReceiptTypeId = ReceiptType.Refund,
                    ReceiptAreaTypeId = ReceiptAreaType.ScanAppointmentReturn,
                    RespectiveId = returnScanAppointment.BookScanAppointmentId,
                    TransactionId = commonTransaction.AppointmentTransactionId,
                    MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : 0
                };

                receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt, transaction);
                if (receipt.ReceiptId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }
                //update bill refund
                if (getbillrecord != null)
                {
                    getbillrecord.Refund += (double)amountToReturn;
                    getbillrecord.Active = false;
                    await this.unitOfWork.MasterBill.UpdateAsync(getbillrecord);
                }
            }
            transaction.Commit();
            return returnScanAppointment.BookScanAppointmentId;

        }

        /// <inheritdoc />
        public async Task<int> CancelAllAsync(string appointmentIds, string reason)
        {
            var query = $@" UPDATE ""BookScanAppointment"" set ""Status"" = 'C', ""Reason"" = '{reason}' where ""BookScanAppointmentId"" in ({appointmentIds})";
            var updated = await this.unitOfWork.Current.ExecuteAsync(query);
            if (updated == 0)
            {
                return 0;
            }
            return updated;
        }

        public async Task<IEnumerable<FetchBookScanAppointment>> FetchAsync(FilterModel model)
        {
            var where = " WHERE 1 = 1 ";
            var slotDuration = model.SlotDuration;

            if (model.BookScanAppointmentId > 0)
            {
                where += $@"  and  bs.""BookScanAppointmentId"" = {model.BookScanAppointmentId}";
            }
            if (model.LocationId > 0)
            {
                where += $@"  and  bs.""LocationId"" = {model.LocationId}";
            }

            if (!string.IsNullOrEmpty(model.ScanMachineMasterIds))
            {
                where += $@"  and bs.""ScanMachineMasterId"" in ({model.ScanMachineMasterIds})";
            }
            //if (model.ScanTestMasterId != null)
            //{
            //    where += $@" AND st.""ScanTestMasterId"" = '{model.ScanTestMasterId}'";
            //}
            if (model.AppointmentStatus == false)
            {
                where += $@" and bs.""Status"" not in ('C')";
            }
            if (!string.IsNullOrEmpty(model.AppointmentDate))
            {
                where += $@" AND bs.""AppointmentDate""::DATE = '%{model.AppointmentDate}%'";
            }
            var query = $@"select distinct P.""IsNewPatient"", bs.""IsDispatched"",p.""PaymentStatus"" as ""PatientPaymentStatus"",bs.""PaymentType"",P.""HWCPatientId"",bs.""PaymentStatus"",bs.""Status"", bs.""RequisitionNumber"",bs.""IsSalucroAppointment"",bs.""BookScanAppointmentId"",
                        bs.""PatientId"",a.""FullName"" as ""CreatedByName"",bs.""Reason"",st.""ScanTestName"",st.""Duration"" as ""SlotDuration"",sm.""MachineName"",bs.""ScanMachineMasterId"",CONCAT(""AppointmentDate"", 'T', ""AppointmentTime"") as ""AppointmentStartDateTime""
                        ,bs.""CreatedDate"",p.""Mobile"",CONCAT(""AppointmentDate"", 'T', ""AppointmentEndTime"") as ""AppointmentEndDateTime"",p.""FullName"" as ""PatientName"",p.""Age"",p.""Gender"",
						p.""UMRNo"",pt.""PayTypeName"",bs.""LocationId"",l.""Name"" as ""LocationName"",bs.""CreatedBy"",cc.""ChargeCategoryId"", cc.""ChargeCategoryName""
                        ,bs.""AppointmentTime""::text, bs.""AppointmentEndTime""::text, bs.""AppointmentDate""::text,st.""ScanTestMasterId"",bs.""Indication"",bs.""IsPatRegPaid"",
						p.""Amount"" as ""RegCharges"",
						bs.""ActualAmount"" as ""ScanAmount"",						
                        CASE WHEN bs.""IsPatRegPaid"" is true THEN (COALESCE(p.""DiscountInRupees"",0) + COALESCE(bs.""DiscountAmount"",0)) else COALESCE(bs.""DiscountAmount"",0) end as ""TotalDiscount"",
						CASE WHEN bs.""IsPatRegPaid"" is true THEN (COALESCE(p.""Total"",0) + COALESCE(bs.""Amount"",0)) else COALESCE(bs.""Amount"",0) end as ""NetAmount"",
						CASE WHEN bs.""IsPatRegPaid"" is true THEN COALESCE(p.""Total"",0)+(select COALESCE(sum(R.""Cost""),0) from ""Receipt"" R where R.""RespectiveId"" = bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10) 
						else (select COALESCE(sum(R.""Cost""),0) from ""Receipt"" R where R.""RespectiveId"" = bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10) end as ""PaidAmount"",
                        (select COALESCE(sum(R.""Cost""),0) from ""Receipt"" R where R.""RespectiveId"" = bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10) as ""PaidScanAmount"",
                        (SELECT 
                        CASE WHEN bs.""Status"" = 'C' THEN (select ""RowColor"" from ""AppointmentType"" where ""Name"" = 'Cancelled Appointment') ELSE 
	                        CASE WHEN bs.""IsDispatched"" IS TRUE THEN (select ""RowColor"" from ""AppointmentType"" where ""Name"" = 'Turned Up Patient') ELSE
	                            CASE WHEN P.""HWCPatientId"" IS NOT NULL and P.""HWCPatientId"" > 0 THEN (select ""RowColor"" from ""AppointmentType"" where ""Name"" = 'HWC Patient') ELSE 
	                                CASE WHEN P.""IsNewPatient"" IS TRUE THEN (select ""RowColor"" from ""AppointmentType"" where ""Name"" = 'New Appointment') ELSE 
	                                    CASE WHEN P.""IsNewPatient"" IS FALSE THEN (select ""RowColor"" from ""AppointmentType"" where ""Name"" = 'Walkin')
		                                    ELSE null
		                END							
	                        END
	                            END
	                                END
				                        END	) AS ""BackgroundColor""								
						from ""BookScanAppointment"" bs
                        left join ""ChargeCategory"" cc on cc.""ChargeCategoryId"" = bs.""ChargeCategoryId""
						left join ""ScanMachineMaster"" sm on sm.""ScanMachineMasterId"" = bs.""ScanMachineMasterId""
						left join ""ScanTestMaster"" st on st.""ScanTestMasterId"" = bs.""ScanTestMasterId""
						join ""Patient"" p on p.""PatientId"" = bs.""PatientId""
                    	left join ""PayType"" pt on pt.""PayTypeId"" = bs.""PayTypeId""
					    left Join ""Receipt"" R on R.""RespectiveId""=bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10
						left join ""Account"" a on ""AccountId"" = bs.""CreatedBy""
                        left join ""Location"" l on l.""LocationId"" = bs.""LocationId""
                        {where}";
            return await this.unitOfWork.Current.QueryAsync<FetchBookScanAppointment>(query);
        }

        public async Task<IEnumerable<FetchBookScanAppointment>> FetchFilterEvent(FilterModel model)
        {
            var where = " Where 1=1";
            if (!string.IsNullOrEmpty(model.Filter[0].FromDate))
            {
                where += $@" AND a.""AppointmentDate""::DATE = '%{model.Filter[0].FromDate}%'";
            }
            //if (model.Filter[0].PatientId != null)
            //{
            //    where += $@" AND a.""PatientId"" = {model.Filter[0].PatientId}";
            //}
            //if (model.Filter[0].PatientName != null)
            //{
            //    where += $@" AND a.""PatientName"" = {model.Filter[0].PatientName}";
            //}
            if (model.ScanTestMasterId != null)
            {
                where += $@" AND st.""ScanTestMasterId"" = '{model.ScanTestMasterId}'";
            }
            if (model.LocationId > 0)
            {
                where += $@"  and  a.""LocationId"" = {model.LocationId}";
            }
            if (!string.IsNullOrEmpty(model.ScanMachineMasterIds))
            {
                where += $@"  and a.""ScanMachineMasterId"" in ({model.ScanMachineMasterIds})";
            }
            var query = $@"select a.""IsSalucroAppointment"",a.""BookScanAppointmentId"",a.""Status"",a.""PatientId"",p.""FullName"" as ""PatientName"",st.""ScanTestMasterId"",
                            st.""ScanTestName"", a.""ScanMachineMasterId"",a.""AppointmentDate""::text,a.""AppointmentTime""::text,a.""AppointmentEndTime""::text,s.""MachineName"",
                            st.""Duration"" as ""SlotDuration"" from ""BookScanAppointment"" a
                            left Join ""ScanMachineMaster"" s on s.""ScanMachineMasterId"" = a.""ScanMachineMasterId""
                            left Join ""ScanTestMaster"" st on st.""ScanTestMasterId"" = a.""ScanTestMasterId""
                            left join ""Patient"" p on P.""PatientId"" = a.""PatientId""
                            {where} and a.""Status"" !='C' and a.""IsDispatched"" is false";

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


        public async Task<IEnumerable<FetchBookScanAppointment>> FetchFilterEventPatients(FilterModel model)
        {
            var where = " Where 1=1";
            if (model.Filter != null)
            {
                if (!string.IsNullOrEmpty(model.Filter[0].FromDate))
                {
                    where += $@" AND a.""AppointmentDate""::DATE = '%{model.Filter[0].FromDate}%'";
                }
            }
            if (!string.IsNullOrEmpty(model.AppointmentDate))
            {
                where += $@" AND a.""AppointmentDate""::DATE = '%{model.AppointmentDate}%'";
            }
            if (model.ScanTestMasterId != null)
            {
                where += $@" AND st.""ScanTestMasterId"" = '{model.ScanTestMasterId}'";
            }
            var query = $@"select distinct(a.""PatientId""),p.""FullName"" as ""PatientName"" from ""BookScanAppointment"" a
                            left Join ""ScanMachineMaster"" s on s.""ScanMachineMasterId"" = a.""ScanMachineMasterId""
                            left Join ""ScanTestMaster"" st on st.""ScanTestMasterId"" = a.""ScanTestMasterId""
                            left join ""Patient"" p on P.""PatientId"" = a.""PatientId""
                            {where} AND  a.""LocationId"" = {model.LocationId}  
                            AND a.""ScanMachineMasterId"" in ({model.ScanMachineMasterIds}) AND a.""Status"" !='C'";

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



        public async Task<IEnumerable<FetchBookScanAppointment>> FetchScanReport(FetchBookScanAppointment model)
        {
            var where = $@" where 1=1 ";

            if (model.FromDate != null)
            {
                where += $@" and bs.""CreatedDate"" >= '{model.FromDate}'";
            }
            if (model.PaymentStatus != null)
            {
                where += $@" and bs.""PaymentStatus"" = {model.PaymentStatus}";
            }
            if (model.Status != null)
            {
                where += $@" and bs.""Status"" = '{model.Status}' ";
            }
            if (model.PaymentType != null)
            {
                where += $@" and bs.""PaymentType"" = '{model.PaymentType}' ";
            }
            if (model.ToDate != null)
            {
                where += $@" and bs.""CreatedDate""  <= '{model.ToDate}' ";
            }
            if (model.PatientId != null)
            {
                where += $@" and bs.""PatientId"" = {model.PatientId}";
            }
            if (model.PayTypeId != null)
            {
                where += $@" and r.""PayTypeId"" = {model.PayTypeId}";
            }
            if (model.LocationId > 0)
            {
                where += $@" and  bs.""LocationId"" ={model.LocationId} ";
            }
            if (!string.IsNullOrEmpty(model.UMRNO))
            {
                where += $@" and p.""UMRNo"" = 'UMR{model.UMRNO}'";
            }
            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and bs.""RequisitionNumber"" = '{model.RequisitionNumber}'";
            }
            if (model.BookScanAppointmentId > 0)
            {
                where += $@" and bs.""BookScanAppointmentId"" = '{model.BookScanAppointmentId}'";
            }
            if (model.ReceiptId > 0)
            {
                where += $@" and R.""ReceiptId"" = {model.ReceiptId}";
            }
            if (model.ProviderId > 0)
            {
                where += $@" and bs.""ProviderId"" = {model.ProviderId}";
            }
            if (!string.IsNullOrEmpty(model.Type) && (model.Type == "employeeRevenue" || model.Type == "doctorRevenue"))
            {
                where += $@" and bs.""Status"" != 'C' and bs.""PaymentStatus"" = true";
            }
            var query = $@"select bs.""PaymentStatus"", bs.""PaymentType"" ""TypeOfPayment"",bs.""BookScanAppointmentId"", R.""ReceiptId"",st.""ScanTestName"",bs.""PatientId"",p.""FullName"" as ""PatientName"",p.""UMRNo"",p.""Age"",p.""Gender"",p.""Mobile"",bs.""LocationId"",l.""Name"" as ""LocationName"",
                           pt.""PayTypeName"",bs.""AppointmentTime""::text,bs.""AppointmentDate""::text,bs.""Status"",r.""PayTypeId"",ac.""FullName"" as ""CreatedByName"",bs.""CreatedDate"", bs.""RequisitionNumber"",(SELECT ""ScanDocumentId"" FROM ""ScanDocument"" WHERE ""BookScanAppointmentId"" = bs.""BookScanAppointmentId"" LIMIT 1)
                           ,DR.""FullName"" as ""ProviderName"",bs.""IsPatRegPaid"",
						   p.""Amount"" as ""RegCharges"",
						   bs.""ActualAmount"" as ""ScanAmount"",bs.""DiscountAmount"",	bs.""Amount"" as ""Amt"",					
                           CASE WHEN bs.""IsPatRegPaid"" is true THEN (COALESCE(p.""DiscountInRupees"",0) + COALESCE(bs.""DiscountAmount"",0)) else COALESCE(bs.""DiscountAmount"",0) end as ""TotalDiscount"",
						   CASE WHEN bs.""IsPatRegPaid"" is true THEN (COALESCE(p.""Total"",0) + COALESCE(bs.""Amount"",0)) else COALESCE(bs.""Amount"",0) end as ""NetAmount"",
						   CASE WHEN bs.""IsPatRegPaid"" is true THEN COALESCE(p.""Total"",0)+(select COALESCE(sum(R.""Cost""),0) from ""Receipt"" R where R.""RespectiveId"" = bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10) 
						   else (select COALESCE(sum(R.""Cost""),0) from ""Receipt"" R where R.""RespectiveId"" = bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10) end as ""PaidAmount"",
                           CASE WHEN bs.""IsPatRegPaid"" is true THEN (COALESCE(R.""Cost"",0) + COALESCE(p.""Total"",0)) else COALESCE(R.""Cost"",0) end as ""Amount"",R.""Cost"" as ""PaidAmt"",
						   CASE WHEN bs.""Status"" = 'C' THEN (select COALESCE(R.""Cost"",0) from ""Receipt"" R where R.""RespectiveId"" = bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=11) end as ""RefundAmount""
                    from ""BookScanAppointment"" bs					
					left join ""ScanTestMaster"" st on st.""ScanTestMasterId""=bs.""ScanTestMasterId""
                    left join ""Patient"" p on p.""PatientId"" = bs.""PatientId""
                    left join ""Location"" l on l.""LocationId"" = bs.""LocationId""                    
                    left join ""Account"" ac on ac.""AccountId"" = bs.""CreatedBy""
					left Join ""Receipt"" R on R.""RespectiveId""=bs.""BookScanAppointmentId"" and R.""ReceiptAreaTypeId""=10
                    left join ""PayType"" pt on pt.""PayTypeId"" = R.""PayTypeId""
                    left join ""Provider"" DR on DR.""ProviderId""=bs.""ProviderId""
                    {where}
                    group by bs.""BookScanAppointmentId"",st.""ScanTestName"",bs.""PatientId"",p.""FullName"",p.""UMRNo"",p.""Age"",p.""Gender"",p.""Mobile"",l.""Name"",pt.""PayTypeName"",ac.""FullName"",R.""ReceiptId"", DR.""FullName"",p.""Amount"",p.""DiscountInRupees"",p.""Total""
                    order by bs.""CreatedDate"" desc";
            if (model.PageSize > 0 && model.PageIndex > 0)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            }
            return await this.unitOfWork.Current.QueryAsync<FetchBookScanAppointment>(query);
        }

        public async Task<IEnumerable<FetchPatientFutureAppointment>> FetchPatientFutureAppointments(FetchPatientFutureAppointment model)
        {
            var where = $@" where 1=1 and ""Status"" != 'C'";
            //if (model.LocationId > 0)
            //{
            //    where += $@" and  bs.""LocationId"" ={model.LocationId}";
            //}
            if (model.PatientId > 0)
            {
                where += $@" and ""PatientId"" = {model.PatientId}";
            }
            var dateTimeWhere = string.Empty;
            if (!string.IsNullOrEmpty(model.AppointmentDate))
            {
                dateTimeWhere = $@" AND ""AppointmentDate""::DATE >= '{model.AppointmentDate}'::DATE";
            }
            if (!string.IsNullOrEmpty(model.AppointmentTime))
            {
                dateTimeWhere = $@" AND ((""AppointmentDate""::DATE = '{model.AppointmentDate}'::DATE AND ""AppointmentTime""::Time >= '{model.AppointmentTime}'::TIME) 
                                    OR ""AppointmentDate""::DATE > '{model.AppointmentDate}'::DATE)";
            }
            where += dateTimeWhere;
            var query = $@"SELECT * FROM 
                            (SELECT bs.""PatientId"",bs.""Status"",bs.""AppointmentDate""::text,bs.""AppointmentTime""::text,l.""Name"" as ""LocationName"",stm.""ScanTestName"",smm.""MachineName"",null as ""ProviderName""
                                FROM ""BookScanAppointment"" bs
                                left join ""Location"" l on l.""LocationId"" = bs.""LocationId""
                                left join ""ScanTestMaster"" stm on stm.""ScanTestMasterId""=bs.""ScanTestMasterId""
                                left join ""ScanMachineMaster"" smm on smm.""ScanMachineMasterId"" = bs.""ScanMachineMasterId""
                                {where}
                           UNION ALL
                            SELECT ap.""PatientId"",ap.""Status"",ap.""AppointmentDate""::text,ap.""AppointmentTime""::text,l.""Name"" as ""LocationName"",null as ""ScanTestName"",null as ""MachineName"",pr.""FullName"" as ""ProviderName""
                                FROM ""Appointment"" ap
                                left join ""Location"" l on l.""LocationId"" = ap.""LocationId""
                                left join ""Provider"" pr on pr.""ProviderId"" = ap.""ProviderId""
                                {where}
                           ) as apt
                           order by apt.""AppointmentDate""::text,apt.""AppointmentTime""::text";
            return await this.unitOfWork.Current.QueryAsync<FetchPatientFutureAppointment>(query);
        }

        public async Task<IEnumerable<FetchBookScanAppointment>> FetchScanScroll(FetchBookScanAppointment model)
        {
            var where = $@" where 1=1 and bs.""PaymentStatus"" = true and bs.""Status"" != 'C' and bs.""PaymentType"" = 'F' ";
            if (model.FromDate != null)
            {
                where += $@" and bs.""AppointmentDate"" >= '{model.FromDate}'";
            }
            if (model.ToDate != null)
            {
                where += $@" and bs.""AppointmentDate""  <= '{model.ToDate}' ";
            }
            if (model.LocationId > 0)
            {
                where += $@" and  bs.""LocationId"" ={model.LocationId} ";
            }
            var query = $@"select bs.""BookScanAppointmentId"",bs.""AppointmentTime""::text,l.""Name"" as ""LocationName"",sm.""ScanMachineMasterId"",sm.""MachineName"",bs.""RequisitionNumber"",p.""FullName"" as ""PatientName"",p.""UMRNo"",p.""Age""
                                 ,p.""Gender"",st.""ScanTestName"",bs.""AppointmentDate""::text,bs.""ScanAppointmentType"",bs.""PndtReport"",bs.""IsDispatched"",pr.""FullName"" as ""providerName""
                    from ""BookScanAppointment"" bs					
					left join ""ScanTestMaster"" st on st.""ScanTestMasterId""=bs.""ScanTestMasterId""
					left join ""ScanMachineMaster"" sm on sm.""ScanMachineMasterId"" = bs.""ScanMachineMasterId""
                    left join ""Patient"" p on p.""PatientId"" = bs.""PatientId""
                    left join ""Location"" l on l.""LocationId"" = bs.""LocationId""
					left join ""Provider"" pr on pr.""ProviderId"" = bs.""ProviderId""
                    {where} 
                    group by bs.""BookScanAppointmentId"",st.""ScanTestName"",p.""FullName"",p.""UMRNo"",p.""Age"",p.""Gender"",l.""Name"",sm.""MachineName"",sm.""ScanMachineMasterId"",pr.""FullName""
                    order by bs.""AppointmentDate"" desc;";
            return await this.unitOfWork.Current.QueryAsync<FetchBookScanAppointment>(query);
        }
        public async Task<IEnumerable<FetchBookScanAppointment>> FetchPndtReportAsync(FetchBookScanAppointment model)
        {
            var where = $@" where 1=1 and bs.""PaymentStatus"" = true and bs.""PndtReport"" is true and bs.""IsDispatched"" is true";
            if (model.FromDate != null)
            {
                where += $@" and bs.""AppointmentDate"" >= '{model.FromDate}'";
            }
            if (model.ToDate != null)
            {
                where += $@" and bs.""AppointmentDate""  <= '{model.ToDate}' ";
            }
            if (model.LocationId > 0)
            {
                where += $@" and  bs.""LocationId"" ={model.LocationId} ";
            }
            var query = $@"select bs.""AppointmentDate""::text,P.""PatientId"",p.""FullName"" as ""PatientName"",p.""FatherOrHusband"",p.""UMRNo"",p.""Age"",bs.""Gravida"",bs.""PeriodOfGestation"",
                                  bs.""EDD"",st.""ScanTestName"",CONCAT(p.""StreetAddress"",', ',p.""AddressLine2"",', ',p.""City"",', ',p.""State"",' , ',p.""Zipcode"") AS ""FullAddress"",pr.""FullName"" as ""providerName""
                    from ""BookScanAppointment"" bs					
					left join ""ScanTestMaster"" st on st.""ScanTestMasterId""=bs.""ScanTestMasterId""
                    left join ""Patient"" p on p.""PatientId"" = bs.""PatientId""
					left join ""PatientEmergency"" pe on pe.""PatientId"" = bs.""PatientId""
                    left join ""Location"" l on l.""LocationId"" = bs.""LocationId""
					left join ""Provider"" pr on pr.""ProviderId"" = bs.""ProviderId""
                    {where} group by bs.""BookScanAppointmentId"",st.""ScanTestName"",P.""PatientId"",pe.""FullName"",p.""FullName"",p.""Age"",p.""UMRNo"",pr.""FullName""
                    order by bs.""AppointmentDate"" desc;";
            return await this.unitOfWork.Current.QueryAsync<FetchBookScanAppointment>(query);
        }
        public async Task<IEnumerable<FetchBookScanAppointment>> FetchScanOutPatients(FetchBookScanAppointment model)
        {
            var where = $@" where 1=1 ";

            if (model.PaymentStatus != null)
            {
                where += $@" and bs.""PaymentStatus"" IS {model.PaymentStatus}";
            }
            if (model.Status != null)
            {
                where += $@" and bs.""Status"" = '{model.Status}' ";
            }
            if (model.PaymentType != null)
            {
                where += $@" and bs.""PaymentType"" = '{model.PaymentType}' ";
            }
            if (model.FromDate != null)
            {
                where += $@" and bs.""AppointmentDate"" >= '{model.FromDate}'";
            }
            if (model.ToDate != null)
            {
                where += $@" and bs.""AppointmentDate""  <= '{model.ToDate}' ";
            }
            if (model.PatientId != null)
            {
                where += $@" and bs.""PatientId"" = {model.PatientId}";
            }
            if (model.LocationId > 0)
            {
                where += $@" and  bs.""LocationId"" ={model.LocationId} ";
            }
            if (model.ScanMachineMasterId != null)
            {
                where += $@" and  sm.""ScanMachineMasterId"" ={model.ScanMachineMasterId} ";
            }
            if (model.ScanTestMasterId != null)
            {
                where += $@" and  st.""ScanTestMasterId"" ={model.ScanTestMasterId} ";
            }
            if (model.Type != null && model.Type == "bulk")
            {
                where += $@" and bs.""Status"" != 'C' and bs.""IsDispatched"" IS FALSE";
            }
            var query = $@"select count(*) over () as ""TotalItems"",bs.""BookScanAppointmentId"",bs.""PaymentStatus"",bs.""PaymentType"" as ""typeOfPayment"",st.""ScanTestMasterId"",st.""ScanTestName"",st.""Duration"" as ""SlotDuration"",
                    sm.""ScanMachineMasterId"",sm.""MachineName"",bs.""PatientId"",p.""FullName"" as ""PatientName"",p.""UMRNo"",p.""Age"",p.""Gender"",p.""Mobile"",bs.""LocationId"",
                    l.""Name"" as ""LocationName"",bs.""AppointmentTime""::text,bs.""AppointmentEndTime""::text,bs.""AppointmentDate""::text,bs.""Status"",bs.""Amount"",bs.""RequisitionNumber""
                    from ""BookScanAppointment"" bs
					left join ""ScanTestMaster"" st on st.""ScanTestMasterId""=bs.""ScanTestMasterId""
					left join ""ScanMachineMaster"" sm on sm.""ScanMachineMasterId""=bs.""ScanMachineMasterId""
                    left join ""Patient"" p on p.""PatientId"" = bs.""PatientId""
                    left join ""Location"" l on l.""LocationId"" = bs.""LocationId""
                    {where}
                    order by bs.""CreatedDate"" desc";

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

            model.PageIndex -= 1;
            query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            return await this.unitOfWork.Current.QueryAsync<FetchBookScanAppointment>(query);
        }

        public async Task<int> InsertAsync(InsertBookScanAppointment model)
        {
            using var transaction = this.unitOfWork.BeginTransaction();
            try
            {
                dynamic paymentType;
                if (model.PaymentStatus)
                {
                    if (model.TypeOfPayment == "PartialPayment" || (model.TypeOfPayment == "MultiPaymodes" && model.PaidAmount < model.Amount))
                    {
                        paymentType = 'P';
                    }
                    else
                    {
                        paymentType = 'F';
                    }
                }
                else
                {
                    paymentType = null;
                }
                var bookingScanAppointment = new BookScanAppointment
                {
                    CreatedBy = model.CreatedBy,
                    CreatedDate = DateTime.Now,
                    Active = true,
                    PatientId = model.PatientId,
                    PaymentStatus = model.PaymentStatus,
                    PayTypeId = model.PayTypeId,
                    LocationId = model.LocationId,
                    ScanMachineMasterId = model.ScanMachineMasterId,
                    AppointmentDate = model.AppointmentDate,
                    AppointmentTime = TimeSpan.Parse(model.AppointmentTime),
                    AppointmentEndTime = TimeSpan.Parse(model.AppointmentEndTime),
                    PaymentNumber = model.PaymentNumber,
                    ScanTestMasterId = model.ScanTestMasterId,
                    Status = "B",
                    Indication = model.Indication,
                    AuthorityId = model.AuthorityId == 0 ? null : model.AuthorityId,
                    ReasonId = model.ReasonId == 0 ? null : model.ReasonId,
                    ChargeCategoryId = model.ChargeCategoryId,
                    IsSalucroAppointment = model.IsSalucroAppointment,
                    RequisitionNumber = await this.GetRequisitionNumber(),
                    PaymentType = paymentType,
                    ScanAppointmentType = "OP", // If appointments coming from Admissions, send ScanAppointmentType from frontend as IP.
                    ProviderId = model.ProviderId,
                    BookedStatus = model.BookedStatus,
                    IsPatRegPaid = (model.PaymentStatus && model.Charges > 0) ? true : false,
                    Amount = (double)model.AfterDiscount,
                    DiscountPercentage = (int?)(model.AppointmentDiscountInPercentage == 0 ? null : model.AppointmentDiscountInPercentage),
                    DiscountAmount = model.AppointmentDiscountInRupees == 0 ? null : (double?)model.AppointmentDiscountInRupees,
                    ActualAmount = model.TotalAmt,
                };
                bookingScanAppointment.BookScanAppointmentId = await this.unitOfWork.BookScanAppointments.InsertAsync(bookingScanAppointment, transaction);

                if (bookingScanAppointment.BookScanAppointmentId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }

                //begin-MasterBill
                var billId = 0;
                var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.ScanAppointment && x.ModuleId == bookingScanAppointment.BookScanAppointmentId); //need to check more
                if (getbillrecord == null)
                {
                    var onebill = new MasterBill
                    {
                        ReceiptAreaTypeId = (int)ReceiptAreaType.ScanAppointment,//main module
                                                                                 // ModuleId = (int)ReceiptAreaType.Labs, //sub module
                        ModuleId = bookingScanAppointment.BookScanAppointmentId, // 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 = (int)model.PatientId,
                        Total = (double)model.TotalAmt,
                        Discount = model.AppointmentDiscountInRupees != null ? (double)model.AppointmentDiscountInRupees : 0d,
                        NetTotal = (double)model.AfterDiscount,//replace amount with total coz calculation is coming wrong                        
                        Rounding = (double?)(model.AfterDiscount - 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 (bookingScanAppointment.BookScanAppointmentId > 0 && model.PaymentStatus)
                {
                    //transaction for the Scan Appointment
                    var commonTransaction = new AppointmentTransaction
                    {
                        AppointmentId = bookingScanAppointment.BookScanAppointmentId,
                        Transaction = model.Transaction ?? "",
                        TransactionDate = DateTime.Now,
                        TransactionId = model.TransactionId ?? await appointmentTransactionsServices.GetATransactionId(),
                        VoucherNumber = model.SalucroStatusCode == 1201 ? null : await appointmentTransactionsServices.GetVoucherNumber(),
                        BankReference = "",
                        BankCode = "",
                        Active = true,
                        PaymentId = 0,
                        PaymentModeId = 1,
                        SettledAmount = Convert.ToDecimal(model.PaidAmount),
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = model.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Cash,
                        ReceiptAreaTypeId = (int)ReceiptAreaType.ScanAppointment,
                        SalucroStatusCode = model.SalucroStatusCode,
                        SalucroTransactionId = model.SalucroTransactionId,
                        PatientId = model.PatientId,
                        PayStatus = paymentType
                    };
                    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
                        {
                            Active = true,
                            Cost = (double)model.PaidAmount,
                            CreatedBy = (int)model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)model.PayTypeId,
                            PaymentDetails = model.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.ScanAppointment,
                            RespectiveId = bookingScanAppointment.BookScanAppointmentId,
                            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.
                    }
                }

                var getRegistrationCharge = await this.unitOfWork.PatientRegistrationCharges.FindAsync(x => x.Active && x.LocationId == model.LocationId);
                var checkReceipt = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"SELECT COUNT(""ReceiptId"") FROM ""Receipt"" WHERE ""RespectiveId"" = {model.PatientId} and ""ReceiptAreaTypeId""=3 ");
                //begin-MasterBill
                var billId2 = 0;
                var getbillrecord2 = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.ScanAppointment && x.ModuleId == bookingScanAppointment.BookScanAppointmentId); //need to check more

                if (getbillrecord2 == null && checkReceipt == 0 && getRegistrationCharge != null)
                {
                    var onebill = new MasterBill
                    {
                        ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,//main module
                        // ModuleId = (int)ReceiptAreaType.Labs, //sub module
                        ModuleId = model.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 = (int)model.PatientId,
                        Total = (double)getRegistrationCharge.Charge,
                        Discount = model.PatientDiscountInRupees != null ? (double)model.PatientDiscountInRupees : 0d,
                        NetTotal = (double)model.PatientTotal,//replace amount with total coz calculation is coming wrong                        
                        //Rounding = (int)model.Amount - model.Amount,
                        LocationId = model.LocationId
                    };
                    onebill.MasterBillId = await this.unitOfWork.MasterBill.InsertAsync(onebill, transaction);
                    billId2 = onebill.MasterBillId;
                    if (onebill.MasterBillId == 0)
                    {
                        transaction.Rollback();
                        return -5;
                    }
                }
                //end-MasterBill
                if (getRegistrationCharge != null && model.PaymentStatus == (bool)true && checkReceipt == 0)
                {
                    //transaction for registration
                    var commonTransaction = new AppointmentTransaction
                    {
                        AppointmentId = model.PatientId, // respective Id                     
                        Transaction = model.Transaction ?? "",
                        SalucroStatusCode = model.SalucroStatusCode,
                        SalucroTransactionId = model.SalucroTransactionId,
                        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,
                        CreatedBy = (int)model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = (int)model.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Cash, // credit
                        ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,
                        PatientId = model.PatientId,
                        SettledAmount = model.PatientTotal,
                        // PayStatus not impl
                    };
                    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
                        {
                            Active = true,
                            CreatedBy = (int)model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)model.PayTypeId,
                            PaymentDetails = model.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.PatientRegistration,
                            RespectiveId = model.PatientId,
                            TransactionId = commonTransaction.AppointmentTransactionId,
                            MasterBillId = getbillrecord2 != null ? getbillrecord2.MasterBillId : billId2,
                            Cost = (double)model.PatientTotal,
                        };

                        receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt);
                        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 receiptcostsum2 = 0.0;
                        foreach (var item in allreceiptforbill.ToList())
                        {
                            receiptcostsum2 += item.Cost;
                        }
                        var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == receipt.MasterBillId);
                        if (receiptcostsum2 == 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.
                    }
                }

                transaction.Commit();
                return bookingScanAppointment.BookScanAppointmentId;
            }

            catch (Exception ex)
            {
                transaction.Rollback();
                throw;
            }
        }

        public async Task<int> RescheduleAsync(int bookScanAppointmentId, int modifiedBy, DateTime appointmentDate, TimeSpan appointmentTime, TimeSpan appointmentEndTime, int scanMachineMasterId)
        {
            var appointment = await this.unitOfWork.BookScanAppointments.FindAsync(m => m.BookScanAppointmentId == bookScanAppointmentId);
            appointment.ScanMachineMasterId = scanMachineMasterId;
            appointment.ModifiedDate = DateTime.UtcNow;
            appointment.ModifiedBy = modifiedBy;
            appointment.OldAppointmentDate = appointment.AppointmentDate;
            appointment.OldAppointmentTime = appointment.AppointmentTime;
            appointment.AppointmentDate = appointmentDate;
            appointment.AppointmentTime = appointmentTime;
            appointment.AppointmentEndTime = appointmentEndTime;
            appointment.Status = "R";
            return await this.unitOfWork.BookScanAppointments.UpdateAsync(appointment);
        }

        public async Task<int> BulkRescheduleAsync(RescheduleScanAppointmentRequest model)
        {
            try
            {
                var appointmentId = model.AppointmentIds.Split(",");
                var aptStartTimings = model.AppointmentTime.Split(",");
                var aptEndTimings = model.AppointmentEndTime.Split(",");
                int updatedId = 0;

                for (int i = 0; i < appointmentId.Length; i++)
                {
                    var appointment = await this.unitOfWork.BookScanAppointments.FindAsync(m => m.BookScanAppointmentId == Convert.ToInt64(appointmentId[i]));
                    appointment.ScanMachineMasterId = model.ScanMachineMasterId;
                    appointment.ModifiedDate = DateTime.UtcNow;
                    appointment.ModifiedBy = model.ModifiedBy;
                    appointment.OldAppointmentDate = appointment.AppointmentDate;
                    appointment.OldAppointmentTime = appointment.AppointmentTime;
                    appointment.AppointmentDate = model.AppointmentDate;
                    appointment.AppointmentTime = TimeSpan.Parse(aptStartTimings[i]);
                    appointment.AppointmentEndTime = TimeSpan.Parse(aptEndTimings[i]);
                    appointment.LocationId = model.LocationId;
                    appointment.RescheduleReason = model.RescheduleReason;
                    appointment.Status = "R";
                    updatedId = await this.unitOfWork.BookScanAppointments.UpdateAsync(appointment);
                    if (updatedId == 0) { return 0; }
                }
                return updatedId;
            }
            catch (Exception e)
            {
                return 0;
            }
        }

        public async Task<int> UpdateDetailsAsync(InsertBookScanAppointment model)
        {
            var appointment = await this.unitOfWork.BookScanAppointments.FindAsync(m => m.BookScanAppointmentId == model.BookScanAppointmentId);
            if (model != null && model.EDD != null)
            {
                Convert.ToDateTime(model.EDD);
            }
            else
            {
                model.EDD = null;
            }
            if (model.IsDispatched)
            {
                appointment.Gravida = model.Gravida;
                appointment.PeriodOfGestation = model.PeriodOfGestation;
                appointment.Obstetric = model.Obstetric;
                appointment.EDD = model.EDD;
                appointment.AccompaniedBy = model.AccompaniedBy;
                appointment.Findings = model.Findings;
                appointment.Remarks = model.Remarks;
                appointment.Reasons = model.Reasons;
                appointment.Dispatched = model.Dispatched;
                appointment.BabyDetails = model.BabyDetails;
                appointment.IsDispatched = model.IsDispatched;
            }
            else if (model.PndtReport)
            {
                appointment.PndtReport = model.PndtReport;
                appointment.ScanScrollResult = model.ScanScrollResult;
            }
            return await this.unitOfWork.BookScanAppointments.UpdateAsync(appointment);
        }

        public async Task<RescheduleScanAppointmentDetails> FetchScanAppointmentDetails(int bookScanAppointmentId)
        {
            var query = $@"SELECT p.""PatientId"", p.""FullName"" AS ""PatientName"", p.""Mobile"", bsa.""PaymentStatus"", bsa.""RequisitionNumber""
                            ,bsa.""AppointmentDate"", bsa.""AppointmentTime""::text, bsa.""LocationId"", smm.""MachineName""
                            from ""BookScanAppointment"" bsa
                            left join ""Patient"" p on p.""PatientId"" = bsa.""PatientId""
							left join ""ScanMachineMaster"" smm ON smm.""ScanMachineMasterId"" = bsa.""ScanMachineMasterId""
                            where ""BookScanAppointmentId"" = {bookScanAppointmentId}";
            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<RescheduleScanAppointmentDetails>(query);
        }

        /// <summary>Gets the latest requisition number.</summary>
        /// <returns></returns>
        private async Task<string> GetRequisitionNumber()
        {
            var previous = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>($@"select ""RequisitionNumber"" from ""BookScanAppointment"" order by ""BookScanAppointmentId"" desc limit 1");
            if (previous == null)
            {
                return $@"{DateTime.Now.ToString("yyyy")}1";
            }
            else
            {
                var year = previous[..4];
                var getCurrentYear = DateTime.Now.ToString("yyyy");
                if (year != getCurrentYear)
                {
                    return $@"{getCurrentYear}1";
                }
                var sequenceNumber = previous.Replace(year, "");
                return $@"{year}{Convert.ToInt64(sequenceNumber) + 1}";
            }
        }



        /// <inheritdoc />
        public async Task<IEnumerable<int>> AddScanDocumentAsync(IEnumerable<ScanDocumentModel> model)
        {
            var scanDocuments = model.Select(item => new ScanDocument
            {
                Active = true,
                BookScanAppointmentId = item.BookScanAppointmentId,
                UploadedBy = item.UploadedBy,
                DocumentName = item.DocumentName,
                ContentType = item.ContentType,
                Size = item.Size,
                Description = item.Description,
                DocumentUrl = item.DocumentUrl,
                ThumbnailUrl = item.ThumbnailUrl,
                UploadedDate = DateTime.UtcNow
            });
            var responseIds = new List<int>();
            foreach (var document in scanDocuments)
            {
                var response = await this.unitOfWork.ScanDocuments.InsertAsync(document);
                responseIds.Add(response);
            }
            return responseIds;
        }
        /// <inheritdoc />
        public Task<IEnumerable<ScanDocumentModel>> FetchScanDocumentAsync(int BookScanAppointmentId)
        {
            var where = string.Empty;
            if (BookScanAppointmentId != 0)
            {
                where = $@" WHERE sd.""Active"" IS TRUE AND sd.""BookScanAppointmentId"" = {BookScanAppointmentId}";
            }
            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"", bs.""PatientId"",sd.""BookScanAppointmentId"", sd.""ScanDocumentId"", sd.""DocumentName"", CASE WHEN sd.""Description"" IS NULL THEN '' ELSE sd.""Description"" END ""Description"", sd.""ContentType"", sd.""Size"",sd.""IsRead"",
                                sd.""UploadedDate"", sd.""UploadedBy"",
                                (CASE WHEN sd.""DocumentUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/ScanReports/',sd.""BookScanAppointmentId"", '/', sd.""DocumentUrl"") ELSE NULL END) AS ""DocumentUrl""
                                FROM ""ScanDocument"" sd
                                left join ""BookScanAppointment"" bs on bs.""BookScanAppointmentId""=sd.""BookScanAppointmentId""
                                {where} ORDER BY sd.""BookScanAppointmentId"" DESC";
            return this.unitOfWork.Current.QueryAsync<ScanDocumentModel>(query);
        }


        public Task<IEnumerable<ScanDocumentModel>> FetchPacsImagesAsync(int patientId)
        {
            var where = string.Empty;
            if (patientId != 0)
            {
                where = $@" WHERE  ba.""PatientId"" = {patientId}";
            }
            //            var query = $@"select sc.* ,ba.""PatientId"" from ""ScanDocument"" sc
            //left join  ""BookScanAppointment"" ba on ba.""BookScanAppointmentId""=sc.""BookScanAppointmentId""
            //                                {where} ";

            var query = $@"SELECT COUNT(*) OVER () AS ""TotalItems"",ba.""PatientId"", sd.""BookScanAppointmentId"", sd.""ScanDocumentId"", sd.""DocumentName"", CASE WHEN sd.""Description"" IS NULL THEN '' ELSE sd.""Description"" END ""Description"", sd.""ContentType"", sd.""Size"",sd.""IsRead"",
                                sd.""UploadedDate"", sd.""UploadedBy"",
                                (CASE WHEN sd.""DocumentUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/ScanReports/',sd.""BookScanAppointmentId"", '/', sd.""DocumentUrl"") ELSE NULL END) AS ""DocumentUrl""
                                FROM ""ScanDocument"" sd
left join  ""BookScanAppointment"" ba on ba.""BookScanAppointmentId""=sd.""BookScanAppointmentId""
                                {where} ";
            return this.unitOfWork.Current.QueryAsync<ScanDocumentModel>(query);
        }
        public async Task<int> UpdatePatientDetailsPaymentAsync(InsertBookScanAppointment request, ModifyPatientDetails model)
        {
            using var transaction = this.unitOfWork.BeginTransaction();
            var response = -1;
            if (request != null)
            {
                if (request.Amount >= 0 && request.BookScanAppointmentId > 0)
                {
                    var appointment = await this.unitOfWork.BookScanAppointments.FindAsync(x => x.BookScanAppointmentId == request.BookScanAppointmentId);
                    appointment.BookScanAppointmentId = (int)request.BookScanAppointmentId;
                    appointment.PatientId = request.PatientId;
                    appointment.ScanMachineMasterId = appointment.ScanMachineMasterId;
                    appointment.ScanTestMasterId = appointment.ScanTestMasterId;
                    appointment.Active = true;
                    appointment.ModifiedBy = request.ModifiedBy;
                    appointment.ModifiedDate = DateTime.Now;
                    appointment.PaymentStatus = request.PaymentStatus;
                    appointment.PayTypeId = (int)request.PayTypeId;
                    appointment.LocationId = request.LocationId;
                    appointment.PaymentNumber = request.PaymentNumber;
                    appointment.Indication = request.Indication;
                    appointment.AuthorityId = request.AuthorityId == 0 ? null : request.AuthorityId;
                    appointment.ReasonId = request.ReasonId == 0 ? null : request.ReasonId;
                    appointment.ChargeCategoryId = request.ChargeCategoryId;
                    appointment.IsSalucroAppointment = request.IsSalucroAppointment;
                    appointment.PaymentType = request.TypeOfPayment == "PartialPayment" || (request.TypeOfPayment == "MultiPaymodes" && (double)request.Amount > 0) ? 'P' : 'F'; //Modify Amount when MultiPaymodes comes.//
                    appointment.Amount = (double)request.AfterDiscount;
                    appointment.DiscountPercentage = (int?)(request.AppointmentDiscountInPercentage == 0 ? null : request.AppointmentDiscountInPercentage);
                    appointment.DiscountAmount = request.AppointmentDiscountInRupees == 0 ? null : (double?)request.AppointmentDiscountInRupees;
                    appointment.ActualAmount = request.TotalAmt;
                    appointment.IsPatRegPaid = (request.PaymentStatus && request.Charges > 0) ? true : false;
                    response = await this.unitOfWork.BookScanAppointments.UpdateAsync(appointment, transaction);
                }
                if (response == 0)
                {
                    transaction.Rollback();
                    return 0;
                }

                //begin-MasterBill
                var billId = 0;
                var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.ScanAppointment && x.ModuleId == request.BookScanAppointmentId); //need to check more

                if (getbillrecord != null)
                {
                    var onebill = new MasterBill
                    {
                        MasterBillId = getbillrecord.MasterBillId,
                        ReceiptAreaTypeId = getbillrecord.ReceiptAreaTypeId,//main module
                        ModuleId = getbillrecord.ModuleId, // module-main table id.
                        BillDate = getbillrecord.BillDate,
                        BillNumber = getbillrecord.BillNumber,
                        BillStatusTypeId = getbillrecord.BillStatusTypeId,
                        CreatedBy = getbillrecord.CreatedBy,
                        CreatedDate = getbillrecord.CreatedDate,
                        Active = getbillrecord.Active,
                        PatientId = getbillrecord.PatientId,
                        ModifiedBy = (int)request.ModifiedBy,
                        ModifiedDate = DateTime.Now,
                        LocationId = (int)request.LocationId,
                        Total = (double)request.TotalAmt,
                        Discount = request.AppointmentDiscountInRupees != null ? (double)request.AppointmentDiscountInRupees : 0d,
                        NetTotal = (double)request.AfterDiscount,
                        Rounding = (double?)(request.AfterDiscount - request.AfterDiscount),
                    };
                    onebill.MasterBillId = await this.unitOfWork.MasterBill.UpdateAsync(onebill, transaction);
                    billId = onebill.MasterBillId;
                    if (onebill.MasterBillId == 0)
                    {
                        transaction.Rollback();
                        return -5;
                    }
                }
                //end-MasterBill
                if (request.BookScanAppointmentId > 0 && request.PaymentStatus)
                {
                    //transaction for the Scan Appointment//
                    var commonTransaction = new AppointmentTransaction
                    {
                        AppointmentId = (int)request.BookScanAppointmentId,
                        Transaction = request.Transaction ?? "",
                        TransactionDate = DateTime.Now,
                        TransactionId = request.TransactionId ?? await appointmentTransactionsServices.GetATransactionId(),
                        VoucherNumber = request.SalucroStatusCode == 1201 ? null : await appointmentTransactionsServices.GetVoucherNumber(),
                        BankReference = "",
                        BankCode = "",
                        Active = true,
                        PaymentId = 0,
                        PaymentModeId = 1,
                        SettledAmount = Convert.ToDecimal(request.PaidAmount),
                        CreatedBy = request.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = (int)request.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Cash,
                        ReceiptAreaTypeId = (int)ReceiptAreaType.ScanAppointment,
                        SalucroStatusCode = request.SalucroStatusCode,
                        SalucroTransactionId = request.SalucroTransactionId,
                        PatientId = request.PatientId,
                        PayStatus = request.TypeOfPayment == "PartialPayment" || (request.TypeOfPayment == "MultiPaymodes" && (double)request.Amount > 0) ? 'P' : 'F'
                    };
                    commonTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTransaction, transaction);
                    if (commonTransaction.AppointmentTransactionId == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                    if (request.SalucroStatusCode != 1201)
                    {
                        var receipt = new Receipt
                        {
                            Active = true,
                            Cost = (double)request.PaidAmount,
                            CreatedBy = (int)request.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)request.PayTypeId,
                            PaymentDetails = request.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.ScanAppointment,
                            RespectiveId = request.BookScanAppointmentId,
                            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 (model != null)
            {
                if (model.PatientId > 0)
                {
                    var patient = await this.unitOfWork.Patients.FindAsync(x => x.PatientId == model.PatientId);
                    if (patient != null)
                    {
                        var patientModel = new PatientModel
                        {
                            PatientId = model.PatientId,
                            ProfileImageUrl = model.ProfileImageUrl
                        };
                        model.ThumbnailUrl = model.ThumbnailUrl == "" ? null : model.ThumbnailUrl;
                        if (!string.IsNullOrEmpty(patientModel.ProfileImageUrl))
                        {
                            var filePath = $@"{this.runningEnvironment.CurrentEnvironment}/{patient.Guid}/ProfileImage";

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

                            try
                            {
                                var uploadResponse = await this.ftpUploadHelper.UploadProfileImageAsync(patientModel.ProfileImageUrl, filePath);
                                if (uploadResponse > 0)
                                {
                                    patientModel.ProfileImageUrl = $@"ProfileImage/{dbPath}";
                                    patientModel.ThumbnailUrl = $@"ProfileImage/{dbPath}";
                                    if (!string.IsNullOrEmpty(patient.ProfileImageUrl))
                                    {
                                        var imageFullPath = $@"{this.runningEnvironment.CurrentEnvironment}/{patient.Guid}/{patient.ProfileImageUrl}";
                                        await this.ftpUploadHelper.DeleteFile(imageFullPath);
                                    }
                                }
                            }
                            catch (Exception)
                            {
                                patientModel.ProfileImageUrl = null;
                                patientModel.ThumbnailUrl = null;
                            }
                        }
                        patient.ProfileImageUrl = patientModel.ProfileImageUrl;
                        patient.ThumbnailUrl = patientModel.ThumbnailUrl == "" ? null : patientModel.ThumbnailUrl;
                        if (response == 0)
                        {
                            transaction.Rollback();
                            return 0;
                        }

                        patient.Salutation = model.Salutation != null ? model.Salutation : patient.Salutation;
                        patient.FirstName = model.FirstName != null ? model.FirstName : patient.FirstName;
                        patient.MiddleName = model.MiddleName;
                        patient.LastName = model.LastName;
                        patient.FullName = model.FirstName + ' ' + model.LastName;
                        patient.FatherOrHusband = model.RelativeDetails[0].FullName;
                        patient.DateOfBirth = model.DateOfBirth;
                        patient.Age = model.Age;
                        patient.Gender = model.Gender;
                        patient.MaritalStatus = model.MaritalStatus;
                        patient.Email = model.Email;
                        patient.Mobile = model.Mobile;
                        patient.StreetAddress = model.StreetAddress;
                        patient.AddressLine2 = model.AddressLine2;
                        patient.City = model.City;
                        patient.State = model.State;
                        patient.Zipcode = model.Zipcode;
                        patient.CountryId = model.CountryId;
                        patient.AadharNo = model.AadharNo;
                        patient.ReferredBy = model.ReferredBy;
                        patient.PatientReferredById = model.PatientReferredById;
                        patient.ReferredByName = model.ReferredByName;
                        patient.HWCPatientId = model.HWCPatientId;
                        patient.Education = model.Education;
                        patient.Occupation = model.Occupation;
                        patient.Nationality = model.Nationality;
                        patient.Religion = model.Religion;
                        patient.IdProofId = model.IdProofId;
                        patient.IdProofValue = model.IdProofValue;
                        patient.BloodGroup = model.BloodGroup;
                        patient.HowDidYouKnowId = model.HowDidYouKnowId;
                        patient.EducationId = model.EducationId;
                        patient.OccupationId = model.OccupationId;
                        patient.RelationType = model.RelationType;
                        patient.OccupationDetail = model.OccupationDetail;
                        if ((patient.PaymentStatus == false && model.PaymentStatus == true) || (patient.PaymentStatus == null && model.PaymentStatus == true))
                        {
                            patient.UMRNo = patient.UMRNo.StartsWith('U') ? patient.UMRNo : await this.patientServices.GetLatestUMRNo();
                            patient.ModifiedBy = (int)model.ModifiedBy;
                            patient.ModifiedDate = DateTime.Now;
                            patient.PaymentStatus = model.PaymentStatus;
                            patient.PayTypeId = model.PayTypeId > 0 ? model.PayTypeId : null;
                            patient.PaymentNumber = model.PaymentNumber != null || model.PaymentNumber == "" ? model.PaymentNumber : null;
                            patient.Amount = model.Amount != null ? model.Amount : 0;
                            patient.Total = (decimal?)(model.PatientTotal != null ? model.PatientTotal : 0);
                            patient.DiscountInPercentage = (decimal)(model.PatientDiscountInPercentage != null ? model.PatientDiscountInPercentage : 0);
                            patient.DiscountInRupees = (decimal)(model.PatientDiscountInRupees != null ? model.PatientDiscountInRupees : 0);
                        }
                        response = await this.unitOfWork.Patients.UpdateAsync(patient, transaction);
                    }
                }
                if (response == 0)
                {
                    transaction.Rollback();
                    return 0;
                }

                var query = $@"DELETE FROM ""PatientFamily"" WHERE ""PatientId"" = '{model.PatientId}'";
                await this.unitOfWork.Current.ExecuteAsync(query, null, transaction);

                if (model.RelativeDetails[0].FullName != null && model.RelativeDetails[0].Relation != null)
                {
                    var updated = 0;
                    foreach (var item in model.RelativeDetails)
                    {
                        if (item.FullName != null && item.Relation != null)
                        {
                            var patientFamily = new PatientFamily
                            {
                                PatientId = model.PatientId,
                                FullName = item.FullName,
                                Relation = item.Relation,
                                Age = item.Age != null ? (int)item.Age : 0,
                                Gender = item.RelativeGender,
                                Active = true,
                                CreatedBy = Convert.ToInt32(model.ModifiedBy),
                                CreatedDate = DateTime.UtcNow,
                                ContactNo = item.ContactNo,
                                Education = item.Education,
                                Occupation = item.Occupation,
                                DOB = item.DOB,
                                OccupationDetails = item.OccupationDetails
                            };
                            var responseData = await this.unitOfWork.PatientFamily.InsertAsync(patientFamily, transaction);
                            if (responseData != 0)
                            {
                                updated++;
                            }
                        }
                    }
                    if (updated != model.RelativeDetails.Count)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }

                // Patient's Account
                var account = await this.unitOfWork.Accounts.FindAsync(m => m.RoleId == (int)Roles.Patient && m.ReferenceId == model.PatientId, transaction);
                if (account == null || account.AccountId == 0)
                {
                    transaction.Rollback();
                    return 0;
                }
                model.FullName = model.FirstName + ' ' + model.LastName;
                if (account.Email != model.Email || account.Mobile != model.Mobile || account.CountryId != model.CountryId || account.FullName != (model.FullName))
                {
                    account.Email = model.Email;
                    account.Mobile = model.Mobile;
                    account.CountryId = model.CountryId;
                    account.FullName = model.FullName;
                    var updated = await this.unitOfWork.Accounts.UpdateAsync(account, transaction);
                    if (updated == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }
                var getRegistrationCharge = await this.unitOfWork.PatientRegistrationCharges.FindAsync(x => x.Active && x.LocationId == model.LocationId);
                var checkReceipt = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>($@"SELECT COUNT(""ReceiptId"") FROM ""Receipt"" WHERE ""RespectiveId"" = {model.PatientId} and ""ReceiptAreaTypeId""=3 ");
                ////begin-MasterBill
                var billId2 = 0;
                var getbillrecord2 = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.ScanAppointment && x.ModuleId == model.PatientId); //need to check more

                if (getbillrecord2 == null && checkReceipt == 0)
                {
                    var onebill = new MasterBill
                    {
                        ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,//main module
                        // ModuleId = (int)ReceiptAreaType.Labs, //sub module
                        ModuleId = model.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 = (int)model.PatientId,
                        LocationId = (int)model.LocationId,
                        Total = (double)model.Amount,
                        Discount = request.PatientDiscountInRupees != null ? (double)request.PatientDiscountInRupees : 0d,
                        NetTotal = (double)request.PatientTotal,
                    };
                    onebill.MasterBillId = await this.unitOfWork.MasterBill.InsertAsync(onebill, transaction);
                    billId2 = onebill.MasterBillId;
                    if (onebill.MasterBillId == 0)
                    {
                        transaction.Rollback();
                        return -5;
                    }
                }
                //end-MasterBill
                if (getRegistrationCharge != null && model.PaymentStatus == (bool)true && checkReceipt == 0)
                {
                    //transaction for registration //
                    var commonTransaction = new AppointmentTransaction
                    {
                        AppointmentId = model.PatientId, // respective Id                     
                        Transaction = model.Transaction ?? "",
                        SalucroStatusCode = model.SalucroStatusCode,
                        SalucroTransactionId = model.SalucroTransactionId,
                        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,
                        CreatedBy = (int)model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = (int)model.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Cash, // credit
                        ReceiptAreaTypeId = (int)ReceiptAreaType.PatientRegistration,
                        PatientId = model.PatientId,
                        SettledAmount = request.PatientTotal,
                        //PayStatus not impl
                    };
                    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
                        {
                            Active = true,
                            CreatedBy = (int)model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)model.PayTypeId,
                            PaymentDetails = model.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.PatientRegistration,
                            RespectiveId = model.PatientId,
                            TransactionId = commonTransaction.AppointmentTransactionId,
                            MasterBillId = getbillrecord2 != null ? getbillrecord2.MasterBillId : billId2,
                            Cost = (double)request.PatientTotal,
                        };

                        receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt);
                        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 receiptcostsum2 = 0.0;
                        foreach (var item in allreceiptforbill.ToList())
                        {
                            receiptcostsum2 += item.Cost;
                        }
                        var getbill = await this.unitOfWork.MasterBill.FindAsync(x => x.MasterBillId == receipt.MasterBillId);
                        if (receiptcostsum2 == 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.
                    }
                }
            }
            transaction.Commit();
            return response;
        }
    }
}