namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    using Dapper;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Hims.Domain.Configurations;
    using Hims.Domain.Entities.Enums;
    using Hims.Domain.Entities.Labs;
    using Hims.Shared.Library.Enums;
    using Hims.Shared.UserModels.ServiceOrder;
    using Shared.EntityModels;
    using Shared.UserModels.Labs;

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

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

        /// <summary>
        /// The payment map helper service
        /// </summary>
        private readonly IPaymentMapHelperService paymentMapHelperService;

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

        /// <inheritdoc cref="ILabTransactionService" />
        public LabTransactionServices(IUnitOfWork unitOfWork, IAppointmentTransactionService appointmentTransactionsServices, IPaymentMapHelperService paymentMapHelperService, IRunningEnvironment runningEnvironment)
        {
            this.unitOfWork = unitOfWork;
            this.runningEnvironment = runningEnvironment;
            this.appointmentTransactionsServices = appointmentTransactionsServices;
            this.paymentMapHelperService = paymentMapHelperService;
        }

        /// <inheritdoc/>
        public async Task<int> AddLabBillAsync(LabBookingModel model, List<InsertLabServiceHelperModel> labServicesFromServiceOrder)
        {
            model.TotalAmount = model.TotalAmount != null ? model.TotalAmount : 0;
            var transaction = this.unitOfWork.BeginTransaction();
            var admissionPackageId = 0;

            if (model.PackageId != null && model.PackageId > 0)
            {
                var found = await this.unitOfWork.AdmissionPackage.FindAsync(x => x.AdmissionId == model.AdmissionId && x.AppointmentId == model.AppointmentId, transaction);
                if (found == null)
                {
                    var admissionPackage = new AdmissionPackage
                    {
                        Active = true,
                        CreatedDate = DateTime.Now,
                        CreatedBy = model.CreatedBy,
                        AdmissionId = model.AdmissionId,
                        AppointmentId = model.AppointmentId,
                        PackageId = model.PackageId ?? 0
                    };

                    admissionPackage.AdmissionPackageId = await this.unitOfWork.AdmissionPackage.InsertAsync(admissionPackage, transaction);
                    admissionPackageId = admissionPackage.AdmissionPackageId;
                    if (admissionPackageId == 0)
                    {
                        transaction.Rollback();
                        return -1;
                    }
                }
                else
                {
                    admissionPackageId = found.AdmissionPackageId;
                }
            }


            dynamic paymentType;
            if (model.TypeOfPayment == "PartialPayment" || (model.TypeOfPayment == "MultiPaymodes" && model.TotalAmount < model.OverallNetAmount))
            {
                paymentType = 'P';
            }
            else
            {
                paymentType = 'F';
            }

            var billId = 0;
            var billingHeader = new NewLabBookingHeader
            {
                Active = true,
                CreatedBy = model.CreatedBy,
                DoctorId = model.DoctorId,
                DoctorName = model.DoctorName,
                CreatedDate = DateTime.Now,
                EmployeeId = model.EmployeeId,
                LocationId = model.LocationId,
                Mobile = model.Mobile,
                OverallDiscount = model.OverallDiscount,
                OverallDiscountPercentage = model.OverallDiscountPercentage,
                OverallNetAmount = model.OverallNetAmount,
                OverallTotalAmount = model.OverallTotalAmount,
                PatientId = model.PatientId,
                PatientName = model.PatientName,
                PaymentNumber = model.PaymentNumber,
                PayTypeId = model.PayTypeId,
                RequisitionNumber = await this.GetLatestRequisitionNumber(),
                Type = model.Type,
                AppointmentId = model.AppointmentId,
                IsSalucroBill = model.IsSalucroBill,
                AdmissionId = model.AdmissionId,
                PaymentType = paymentType
            };

            billingHeader.NewLabBookingHeaderId = await this.unitOfWork.NewLabBookingHeaders.InsertAsync(billingHeader, transaction);
            if (billingHeader.NewLabBookingHeaderId == 0)
            {
                transaction.Rollback();
                return -1;
            }

            var getStatus = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "Booked");
            var getStatusPending = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "Pending");
            if (getStatus == null)
            {
                transaction.Rollback();
                return -2;
            }
            if (labServicesFromServiceOrder.Count > 0)
            {
                foreach (var lab in labServicesFromServiceOrder)
                {
                    var labServiceRecord = new LabServices
                    {
                        Active = true,
                        CreatedDate = DateTime.Now,
                        CreatedBy = model.CreatedBy,
                        AdmissionId = model.AdmissionId,
                        AppointmentId = model.AppointmentId,
                        Cost = lab.Cost,
                        LabMainDetailId = lab.LabMainDetailId,
                        Unit = lab.Unit,
                        Notes = lab.Notes,
                        AdmissionPackageId = admissionPackageId > 0 ? (int?)admissionPackageId : null,
                        PackageModuleDetailId = lab.PackageModuleDetailId,
                        UsedCost = lab.UsedCost,
                        UsedQuantity = lab.UsedQuantity,
                        DiscountType = lab.DiscountType,
                        DiscountPercentage = lab.DiscountPercentage ?? 0,
                        DiscountAmount = lab.DiscountAmount ?? 0,
                        Discount = ((lab.DiscountPercentage ?? 0) > 0 || (lab.DiscountAmount ?? 0) > 0) ? (lab.Discount ?? 0) : 0,
                    };

                    labServiceRecord.LabServicesId = await this.unitOfWork.LabServices.InsertAsync(labServiceRecord);
                    var labBookingDetails = new NewLabBookingDetail
                    {
                        ChargeCategoryId = lab.ChargeCategoryId,
                        DiscountAmount = 0,
                        DiscountPercentage = 0,
                        LabBookingStatusId = getStatus.LabBookingStatusId,
                        NetAmount = 0,
                        NewLabBookingHeaderId = billingHeader.NewLabBookingHeaderId,
                        LabMainDetailId = lab.LabMainDetailId,
                        LabServicesId = labServiceRecord.LabServicesId
                    };
                    var details = await this.unitOfWork.NewLabBookingDetails.InsertAsync(labBookingDetails, transaction);
                    if (details == 0)
                    {
                        transaction.Rollback();
                        return -3;
                    }

                    var toSampleCollecction = new LabSampleCollection
                    {
                        NewLabBookingDetailId = details
                    };

                    toSampleCollecction.LabSampleCollectionId = await this.unitOfWork.LabSampleCollections.InsertAsync(toSampleCollecction, transaction);
                    if (toSampleCollecction.LabSampleCollectionId == 0)
                    {
                        transaction.Rollback();
                        return -3;
                    }

                    var findNumSamples = await this.unitOfWork.LabMainDetails.FindAsync(x => x.LabMainDetailId == lab.LabMainDetailId);
                    if (findNumSamples != null)
                    {
                        var numOfSamples = findNumSamples.NoOfSamplesCollect == 0 ? 1 : findNumSamples.NoOfSamplesCollect;
                        for (var i = 1; i <= numOfSamples; i++)
                        {
                            var sampleDetail = new LabSampleCollectionDetail
                            {
                                LabSampleCollectionId = toSampleCollecction.LabSampleCollectionId,
                                SampleName = $@"Sample {i}",
                                LabBookingStatusId = getStatusPending.LabBookingStatusId
                            };

                            sampleDetail.LabSampleCollectionDetailId = await this.unitOfWork.LabSampleCollectionDetails.InsertAsync(sampleDetail, transaction);
                            if (sampleDetail.LabSampleCollectionDetailId == 0) { transaction.Rollback(); return -3; }
                        }
                    }

                }
            }
            else
            {
                foreach (var l in model.Labs)
                {
                    var detail = new NewLabBookingDetail
                    {
                        ChargeCategoryId = l.ChargeCategoryId,
                        DiscountAmount = l.DiscountAmount,
                        DiscountPercentage = l.DiscountPercentage,
                        LabBookingStatusId = getStatus.LabBookingStatusId,
                        NetAmount = l.NetAmount,
                        NewLabBookingHeaderId = billingHeader.NewLabBookingHeaderId,
                        TotalAmount = l.TotalAmount,
                        LabMainDetailId = l.LabMainDetailId,
                        ExternalLab = l.IsExternalLab,
                        Emergency = l.Emergency,
                        HomeSample = l.HomeSample
                    };

                    detail.NewLabBookingDetailId = await this.unitOfWork.NewLabBookingDetails.InsertAsync(detail, transaction);
                    if (detail.NewLabBookingDetailId == 0)
                    {
                        transaction.Rollback();
                        return -3;
                    }

                    var toSampleCollecction = new LabSampleCollection
                    {
                        NewLabBookingDetailId = detail.NewLabBookingDetailId
                    };

                    toSampleCollecction.LabSampleCollectionId = await this.unitOfWork.LabSampleCollections.InsertAsync(toSampleCollecction, transaction);
                    if (toSampleCollecction.LabSampleCollectionId == 0)
                    {
                        transaction.Rollback();
                        return -3;
                    }

                    var findNumSamples = await this.unitOfWork.LabMainDetails.FindAsync(x => x.LabMainDetailId == detail.LabMainDetailId);
                    if (findNumSamples == null)
                    {
                        transaction.Rollback();
                        return -3;
                    }

                    var numOfSamples = findNumSamples.NoOfSamplesCollect == 0 ? 1 : findNumSamples.NoOfSamplesCollect;
                    for (var i = 1; i <= numOfSamples; i++)
                    {
                        var sampleDetail = new LabSampleCollectionDetail
                        {
                            LabSampleCollectionId = toSampleCollecction.LabSampleCollectionId,
                            SampleName = $@"Sample {i}",
                            LabBookingStatusId = getStatusPending.LabBookingStatusId
                        };

                        sampleDetail.LabSampleCollectionDetailId = await this.unitOfWork.LabSampleCollectionDetails.InsertAsync(sampleDetail, transaction);
                        if (sampleDetail.LabSampleCollectionDetailId == 0) { transaction.Rollback(); return -3; }
                    }
                }
            }

            var timeline = new LabBookingTimeLine
            {
                Comment = $@"Lab has been booked",
                CommentedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                LabBookingStatusId = getStatus.LabBookingStatusId,
                NewLabBookingHeaderId = billingHeader.NewLabBookingHeaderId
            };

            timeline.LabBookingTimeLineId = await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline, transaction);
            if (timeline.LabBookingTimeLineId == 0)
            {
                transaction.Rollback();
                return -4;
            }

            if (model.ReceiptSaving != false)
            {
                if (billingHeader.NewLabBookingHeaderId > 0)
                {
                    if (model.PaymentInitiationLogId != null && model.PaymentInitiationLogId != 0)
                    {
                        PaymentMapHelperModel paymentHelper = new PaymentMapHelperModel { PaymentInitiationLogId = ((int)model.PaymentInitiationLogId), BillId = billingHeader.NewLabBookingHeaderId };
                        paymentHelper.PaymentMapHelperId = await this.paymentMapHelperService.AddAsync(paymentHelper);
                        if (paymentHelper.PaymentMapHelperId == 0)
                        {
                            transaction.Rollback();
                            return -6;
                        }
                    }

                    //begin-MasterBill
                    var getbillrecord = await this.unitOfWork.MasterBill.FindAsync(x => x.PatientId == model.PatientId && x.BillStatusTypeId == 2 && x.ReceiptAreaTypeId == (int)ReceiptAreaType.Labs && x.ModuleId == billingHeader.NewLabBookingHeaderId); //need to check more

                    if (getbillrecord == null)
                    {
                        var onebill = new MasterBill
                        {
                            ReceiptAreaTypeId = (int)ReceiptAreaType.Labs,//main module  Type
                            ModuleId = billingHeader.NewLabBookingHeaderId, // 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 = model.OverallTotalAmount,
                            Discount = (double)model.OverallDiscount,
                            NetTotal = model.OverallNetAmount,
                            Rounding = (int)model.OverallNetAmount - model.OverallNetAmount,
                            LocationId = (int)model.LocationId
                        };
                        onebill.MasterBillId = await this.unitOfWork.MasterBill.InsertAsync(onebill, transaction);
                        billId = onebill.MasterBillId;
                        if (onebill.MasterBillId == 0)
                        {
                            transaction.Rollback();
                            return -5;
                        }
                    }
                    //begin-MasterBill

                    //transaction for the sale bill
                    var commonTransaction = new AppointmentTransaction
                    {
                        AppointmentId = billingHeader.NewLabBookingHeaderId,
                        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 = (decimal)model.TotalAmount,
                        CreatedBy = (int)model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LocationId = (int)model.LocationId,
                        ReceiptTypeId = (int)ReceiptType.Cash,
                        ReceiptAreaTypeId = (int)ReceiptAreaType.Labs,
                        SalucroStatusCode = model.SalucroStatusCode,
                        SalucroTransactionId = model.SalucroTransactionId,
                        PatientId = model.PatientId,
                        PayStatus = billingHeader.PaymentType,
                    };
                    commonTransaction.AppointmentTransactionId = await this.unitOfWork.AppointmentTransactions.InsertAsync(commonTransaction, transaction);
                    if (commonTransaction.AppointmentTransactionId == 0)
                    {
                        transaction.Rollback();
                        return -4;
                    }

                    if (model.SalucroStatusCode != 1201)
                    {
                        var receipt = new Receipt
                        {
                            Active = true,
                            Cost = (double)model.TotalAmount,
                            CreatedBy = (int)model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            IsAdvance = false,
                            IsRefunded = false,
                            PayTypeId = (int)model.PayTypeId,
                            PaymentDetails = model.PaymentNumber,
                            ReceiptTypeId = ReceiptType.Cash,
                            ReceiptAreaTypeId = ReceiptAreaType.Labs,
                            RespectiveId = billingHeader.NewLabBookingHeaderId,
                            TransactionId = commonTransaction.AppointmentTransactionId,
                            MasterBillId = getbillrecord != null ? getbillrecord.MasterBillId : billId
                        };

                        receipt.ReceiptId = await this.unitOfWork.Receipt.InsertAsync(receipt);
                        if (receipt.ReceiptId == 0)
                        {
                            transaction.Rollback();
                            return -5;
                        }

                        //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.
                    }
                }

            }
            transaction.Commit();
            return billingHeader.NewLabBookingHeaderId;
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabBookingModel>> FetchAddedLabBillAsync(LabBookingModel model)
        {
            var where = "where 1=1";
            if (model.LocationId > 0)
            {
                where += $@" and nlbh.""LocationId"" = {model.LocationId}";
            }
            if (model.NewLabBookingHeaderId > 0)
            {
                where += $@" and nlbh.""NewLabBookingHeaderId"" = {model.NewLabBookingHeaderId}";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and nlbh.""CreatedDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and nlbh.""CreatedDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" = '{model.RequisitionNumber}'";
            }

            if (model.IsShowSampleCollected != null)
            {
                if ((bool)model.IsShowSampleCollected)
                {
                    where += $@" and  lbs.""Status"" not in ('Booked','Cancelled' )";
                }
                else
                {
                    where += $@" and (lbs.""Status"" = 'Booked' or lbs.""Status"" = 'PartiallyCollected')";
                }
            }

            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }

            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }

            if (model.PatientId > 0)
            {
                where += $@" and nlbh.""PatientId"" = {model.PatientId}";
            }

            if (!string.IsNullOrEmpty(model.BookingType))
            {
                if (model.BookingType == "ip")
                {
                    where += $@" and nlbh.""AdmissionId"" is not null ";
                }
                else
                {
                    where += $@" and nlbh.""AdmissionId"" is null ";
                }
            }

            var mainQuery = $@"Select COUNT(*) OVER () AS ""TotalItems"",* from (SELECT distinct nlbh.""NewLabBookingHeaderId"", nlbh.""RequisitionNumber"", nlbh.""Type"", nlbh.""PatientId"", nlbh.""DoctorId"", nlbh.""EmployeeId"",
                                       nlbh.""LocationId"", nlbh.""OverallTotalAmount"", nlbh.""OverallDiscount"", nlbh.""OverallNetAmount"", nlbh.""OverallDiscountPercentage"", nlbh.""PayTypeId"",
                                    nlbh.""PaymentNumber"", nlbh.""CreatedBy"", nlbh.""CreatedDate"", nlbh.""ModifiedBy"", nlbh.""ModifiedDate"", nlbh.""Active""  ,
                                    c.""FullName"" as ""CreatedByName"",m.""FullName"" as ""ModifiedByName"",COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",
                                    COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
                                    (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}/', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",
                                    e.""FullName"" as ""EmployeeName"",pt.""PayTypeName"" ,l.""Name"" as ""LocationName"",p.""UMRNo"",p.""Gender"",p.""Age"",p.""DateOfBirth"", CASE WHEN nlbh.""AdmissionId"" is not null
                 THEN 'IP' else 'OP' END ""BookingType""
                                   FROM ""NewLabBookingHeader"" nlbh
                                   join ""Account"" c on c.""AccountId"" = nlbh.""CreatedBy""
                                   left join ""PayType"" pt ON pt.""PayTypeId"" = nlbh.""PayTypeId""
                                   join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
                                   join ""NewLabBookingDetail"" nlbd ON nlbd.""NewLabBookingHeaderId"" = nlbh.""NewLabBookingHeaderId""
                                   join ""LabBookingStatus"" lbs on lbs.""LabBookingStatusId"" = nlbd.""LabBookingStatusId""
                                   join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
                                   join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
	                               left join ""Account"" m on m.""AccountId"" = nlbh.""ModifiedBy""
	                               join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                               left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                               left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
                                    {where} order by nlbh.""CreatedDate"" DESC) A";


            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                mainQuery += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }

            var headerResponse = await this.unitOfWork.Current.QueryAsync<LabBookingModel>(mainQuery);
            foreach (var header in headerResponse)
            {
                header.Labs = new List<NewLabBookingDetailModel>();

                var detailQuery = $@"SELECT nlbd.""NewLabBookingDetailId"", nlbd.""NewLabBookingHeaderId"", nlbd.""LabMainDetailId"", nlbd.""ChargeCategoryId"", nlbd.""LabBookingStatusId"", nlbd.""DiscountPercentage"",
		                                    nlbd.""DiscountAmount"", nlbd.""TotalAmount"", nlbd.""NetAmount"", lbs.""Status"",lbs.""RowColor"",nlbd.""Emergency"",
		                                    lmd.""TestName"",lmd.""TestCode"" ,lmd.""IsExternalLab"", lmd.""IsInternalLab"", ld.""DepartmentName"" ,cc.""ChargeCategoryName""
		                                    FROM ""NewLabBookingDetail"" nlbd
		                                    join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                                    join ""LabMainDetail"" lmd ON lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                                    join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
		                                    join ""ChargeCategory"" cc on cc.""ChargeCategoryId"" = nlbd.""ChargeCategoryId""
		                                    where nlbd.""NewLabBookingHeaderId"" = {header.NewLabBookingHeaderId}";
                header.Labs = (await this.unitOfWork.Current.QueryAsync<NewLabBookingDetailModel>(detailQuery)).ToList();
            }

            return headerResponse;
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabSampleHandlerModel>> FetchLabsForSampleCollectionAsync(LabSampleHandlerModel model)
        {
            var where = "where 1=1";

            if (model.NewLabBookingHeaderId > 0)
            {
                where += $@" and nlbh.""NewLabBookingHeaderId"" = {model.NewLabBookingHeaderId} and lbs.""Status"" != 'Cancelled'";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and nlbh.""CreatedDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and nlbh.""CreatedDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" ilike '%{model.RequisitionNumber}%'";
            }
            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }
            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }
            if (model.LabBookingStatusId != null)
            {
                where += $@" and  nlbd.""LabBookingStatusId"" = {model.LabBookingStatusId}";
            }

            if (model.IsShowSampleCollected != null)
            {
                where += (bool)model.IsShowSampleCollected ? $@" and lbs.""Status"" = 'SampleCollected'" : string.Empty;
            }

            if (model.IsInternalLab)
            {
                where += $@" and lmd.""IsInternalLab"" is true";
            }

            if (((bool)model.HomeSample))
            {
                where += $@"and lbs.""Status"" != 'Cancelled' and nlbd.""HomeSample"" is true";
            }
            if (((bool)model.HomeSample) && !string.IsNullOrEmpty(model.MobileView))
            {
                if (model.MobileView == "billed")
                {
                    where += $@" and lscd.""SubSampleCollectedBy"" is null";
                }
                else if (model.MobileView == "collected")
                {
                    where += $@" and lscd.""SubSampleCollectedBy"" is not null";
                }
            }

            var query = $@"SELECT count(nlbh.*) over () as ""TotalItems"",nlbh.""NewLabBookingHeaderId"", nlbh.""RequisitionNumber"", nlbh.""Type"", nlbh.""PatientId"", nlbh.""DoctorId"", nlbh.""EmployeeId"",
                                       nlbh.""LocationId"", nlbh.""OverallTotalAmount"", nlbh.""OverallDiscount"", nlbh.""OverallNetAmount"", nlbh.""OverallDiscountPercentage"", nlbh.""PayTypeId"",
                                    nlbh.""PaymentNumber"", nlbh.""CreatedBy"", nlbh.""CreatedDate"", nlbh.""ModifiedBy"", nlbh.""ModifiedDate"", nlbh.""Active""  ,
                                    c.""FullName"" as ""CreatedByName"",m.""FullName"" as ""ModifiedByName"",COALESCE (nlbh.""PatientName"" ,p.""FullName"" ) as ""PatientName"",
                                    COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
                                    (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}/', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",
                                    e.""FullName"" as ""EmployeeName"",pt.""PayTypeName"" ,l.""Name"" as ""LocationName"",p.""UMRNo"",p.""Gender"",p.""Age"",
                                    nlbd.""NewLabBookingDetailId"", nlbd.""LabMainDetailId"", nlbd.""ChargeCategoryId"", nlbd.""LabBookingStatusId"", nlbd.""DiscountPercentage"",
		                            nlbd.""DiscountAmount"", nlbd.""TotalAmount"", nlbd.""NetAmount"", lbs.""Status"",
		                            lmd.""TestName"",lmd.""TestCode"", lmd.""IsExternalLab"", lmd.""IsInternalLab"" , ld.""DepartmentName"" ,cc.""ChargeCategoryName"" ,lst.""TypeName"",
		                            lsc.""LabSampleCollectionId"" ,lsc.""SampleCollectedBy"" ,lsc.""CollectionDate"" ,lsc.""IsBarcodeGenerated"" ,lbs.""RowColor"",
		                            lsc.""BarcodeGeneratedBy"" , lsc.""BarcodeDate"" , sc.""FullName""  as ""SampleCollectedByName"",lmd.""SampleUsage"",lmd.""ConsentFormRequired"",nlbd.""Emergency"",nlbd.""HomeSample"",
		                            bc.""FullName"" as ""BarcodeGeneratedByName"",lscd.""Comment"",lv.""LabVacutainerName"", CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType""
                                    ,lscd.""LabSampleCollectionDetailId"", lscd.""SubSampleCollectedBy"", lscd.""SubCollectionDate"",
                                    lscd.""SubIsBarcodeGenerated"", lscd.""SubBarcodeGeneratedBy"", lscd.""SubBarcodeDate"", lscd.""LocationId"", lscd.""SampleName"",lscd.""UncollectComment"",
                                    subC.""FullName"" as ""SubSampleCollectedByName"", subB.""FullName"" as ""SubBarcodeGeneratedByName"", subL.""Name"" as ""SubSampleCollectionLocation"",
                                    LMD.""NoOfSamplesCollect"" ,LMD.""NoOfSamplesCollectText"" , lbsd.""Status"" as ""SubStatus"",
                                    (case when lsc.""ConsentFormUrl"" is not null then CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/',lsc.""ConsentFormUrl"" ) ELSE NULL END) as ""ConsentFormUrl""
		                            FROM ""NewLabBookingHeader"" nlbh
                                   join ""NewLabBookingDetail"" nlbd on nlbd.""NewLabBookingHeaderId"" = nlbh.""NewLabBookingHeaderId""
                                   join ""Account"" c on c.""AccountId"" = nlbh.""CreatedBy""
                                   left join ""PayType"" pt ON pt.""PayTypeId"" = nlbh.""PayTypeId""
                                   join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
                                   join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                           join ""LabMainDetail"" lmd ON lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                           join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
		                           join ""ChargeCategory"" cc on cc.""ChargeCategoryId"" = nlbd.""ChargeCategoryId""
		                           left join ""LabSampleType"" lst on lst.""LabSampleTypeId"" = lmd.""LabSampleTypeId""
                                   left join ""LabVacutainer"" lv on lv.""LabVacutainerId"" = lmd.""LabVacutainerId""
	                               left join ""Account"" m on m.""AccountId"" = nlbh.""ModifiedBy""
	                               left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                               left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                               left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
                                   left join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
                                   left join ""Account"" sc on sc.""AccountId"" = lsc.""SampleCollectedBy""
                                   left join ""Account"" bc on bc.""AccountId"" = lsc.""BarcodeGeneratedBy""
                                   left join ""LabSampleCollectionDetail"" lscd on lscd.""LabSampleCollectionId"" = lsc.""LabSampleCollectionId""
                                   LEFT join ""LabBookingStatus"" lbsd ON lbsd.""LabBookingStatusId"" = lscd.""LabBookingStatusId""
                                   left join ""Account"" subC on subC.""AccountId"" = lscd.""SubSampleCollectedBy""
                                   left join ""Account"" subB ON subB.""AccountId"" = lscd.""SubBarcodeGeneratedBy""
                                   left join ""Location"" subL on subL.""LocationId"" = lscd.""LocationId""
                                   {where}
	                               order by nlbh.""CreatedDate"" desc";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }

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

        /// <inheritdoc/>
        public async Task<int> CollectSampleAndGenerateBarcodeAsync(LabSampleHandlerModel model, int locationId)
        {
            var status = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "SampleCollected");
            if (status == null)
            {
                return 0;
            }

            var verified = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "Verified" && x.Active);

            if (verified == null)
            {
                return 0;
            }

            if (model.NewLabBookingHeaderId > 0)
            {
                var getAllLab = (await this.unitOfWork.NewLabBookingDetails.FindAllAsync(d => d.NewLabBookingHeaderId == model.NewLabBookingHeaderId && d.LabBookingStatusId != verified.LabBookingStatusId)).ToList();
                if (getAllLab.Count == 0)
                {
                    return -2;
                }
                var x = 0;
                for (int i = 0; i < getAllLab.Count; i++)
                {
                    NewLabBookingDetail lab = getAllLab[i];
                    var checkIfSampleCollected = await this.unitOfWork.LabSampleCollections.FindAsync(x => x.NewLabBookingDetailId == lab.NewLabBookingDetailId);
                    if (checkIfSampleCollected == null)
                    {
                        var labsample = new LabSampleCollection
                        {
                            NewLabBookingDetailId = lab.NewLabBookingDetailId,
                            BarcodeDate = DateTime.Now,
                            BarcodeGeneratedBy = model.CreatedBy,
                            CollectionDate = DateTime.Now,
                            IsBarcodeGenerated = true,
                            SampleCollectedBy = model.CreatedBy,
                            LocationId = locationId
                        };

                        x = await this.unitOfWork.LabSampleCollections.InsertAsync(labsample);
                        lab.LabBookingStatusId = status.LabBookingStatusId;
                        if (x == 0)
                        {
                            return -1;
                        }
                        await this.unitOfWork.NewLabBookingDetails.UpdateAsync(lab);
                    }
                }
                if (x > 0)
                {
                    var timeLine = new LabBookingTimeLine
                    {
                        Comment = $@"Sample collected for all labs",
                        CommentedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LabBookingStatusId = status.LabBookingStatusId,
                        NewLabBookingHeaderId = model.NewLabBookingHeaderId,

                    };

                    await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeLine);
                }
            }
            else if (model.NewLabBookingDetailId > 0)
            {
                var getDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == model.NewLabBookingDetailId);
                if (getDetail == null)
                {
                    return -2;
                }
                var checkIfSampleCollected = await this.unitOfWork.LabSampleCollections.FindAsync(x => x.NewLabBookingDetailId == model.NewLabBookingDetailId);
                if (checkIfSampleCollected == null)
                {
                    var labsample = new LabSampleCollection
                    {
                        NewLabBookingDetailId = model.NewLabBookingDetailId,
                        BarcodeDate = DateTime.Now,
                        BarcodeGeneratedBy = model.CreatedBy,
                        CollectionDate = DateTime.Now,
                        IsBarcodeGenerated = true,
                        SampleCollectedBy = model.CreatedBy,
                        LocationId = locationId
                    };

                    var response = await this.unitOfWork.LabSampleCollections.InsertAsync(labsample);
                    getDetail.LabBookingStatusId = status.LabBookingStatusId;
                    if (response == 0)
                    {
                        return -1;
                    }
                    await this.unitOfWork.NewLabBookingDetails.UpdateAsync(getDetail);
                    var getMainLabDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == getDetail.LabMainDetailId);
                    var timeLine = new LabBookingTimeLine
                    {
                        Comment = $@"Sample collected for lab {getMainLabDetail.TestName}",
                        CommentedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        LabBookingStatusId = status.LabBookingStatusId,
                        NewLabBookingHeaderId = getDetail.NewLabBookingHeaderId,
                        NewLabBookingDetailId = getDetail.NewLabBookingDetailId
                    };

                    await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeLine);
                    return response;
                }
                else
                {
                    return -3;
                }
            }

            return 1;
        }

        /// <inheritdoc/>
        public async Task<int> TransferCollectedSampleAsync(LabTransferModel model)
        {
            var getStatus = await this.unitOfWork.LabBookingStatus.FindAsync(s => s.Status == "SampleTransfered");
            if (getStatus == null)
            {
                return -1;
            }

            var location = await this.unitOfWork.Locations.FindAsync(l => l.LocationId == model.TransferedLocationId);
            if (location == null)
            {
                return -1;
            }

            var transaction = this.unitOfWork.BeginTransaction();

            var transferHeader = new LabTransferHeader
            {
                TransferedBy = model.TransferedBy,
                TransferedDate = DateTime.Now,
                TransferedLocationId = model.TransferedLocationId,
                TransferredTemperatureComments = model.TransferredTemperatureComments,
                TransferredTemperature = model.TransferredTemperature,

                TransferNumber = await this.GetLatestTransferNumberAsync()
            };

            transferHeader.LabTransferHeaderId = await this.unitOfWork.LabTransferHeaders.InsertAsync(transferHeader, transaction);
            if (transferHeader.LabTransferHeaderId == 0)
            {
                transaction.Rollback();
                return -2;
            }

            var bookingIds = new List<int>();

            foreach (var (lab, transferDetail) in from lab in model.Labs
                                                  let transferDetail = new LabTransferDetail
                                                  {
                                                      LabTransferHeaderId = transferHeader.LabTransferHeaderId,
                                                      NewLabBookingDetailId = lab.NewLabBookingDetailId,
                                                      LabSampleCollectionDetailId = lab.LabSampleCollectionDetailId
                                                  }
                                                  select (lab, transferDetail))
            {
                transferDetail.LabTransferDetailId = await this.unitOfWork.LabTransferDetails.InsertAsync(transferDetail, transaction);
                if (transferDetail.LabTransferDetailId == 0)
                {
                    transaction.Rollback();
                    return -3;
                }

                var checkInArray = bookingIds.Find(x => x == lab.LabSampleCollectionId);
                if (checkInArray == 0)
                {
                    bookingIds.Add((int)lab.LabSampleCollectionId);
                }

                var findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(d => d.LabSampleCollectionDetailId == lab.LabSampleCollectionDetailId);
                if (findSub == null)
                {
                    transaction.Rollback();
                    return -4;
                }

                findSub.LabBookingStatusId = getStatus.LabBookingStatusId;
                var updateSub = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub, transaction);
                if (updateSub == 0)
                {
                    transaction.Rollback();
                    return -4;
                }

                if (lab.NewLabBookingHeaderId != null && !string.IsNullOrEmpty(lab.TestName))
                {
                    string temp = "";
                    if (model.TransferredTemperature != null)
                    {
                        temp = $@"with {model.TransferredTemperature}°C";
                    }
                    var timeline = new LabBookingTimeLine
                    {
                        CommentedBy = model.TransferedBy,
                        Comment = $@"Transfered the sample of {lab.TestName}-{findSub.SampleName} to {location.Name.ToUpper()} {temp}",
                        CreatedDate = DateTime.Now,
                        LabBookingStatusId = getStatus.LabBookingStatusId,
                        NewLabBookingHeaderId = (int)lab.NewLabBookingHeaderId,
                        NewLabBookingDetailId = lab.NewLabBookingDetailId
                    };
                    await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline, transaction);
                }
            }

            transaction.Commit();
            foreach (var id in bookingIds)
            {
                var getCollected = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "SampleCollected");
                var query = $@"select count(*) from ""LabSampleCollectionDetail""  where   ""LabSampleCollectionId"" = {id} and ""LabBookingStatusId"" = {getStatus.LabBookingStatusId}";
                var count = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
                if (count == 0)
                {
                    var updateQuery = $@"update ""NewLabBookingDetail"" set  ""LabBookingStatusId"" = {getStatus.LabBookingStatusId} where  ""NewLabBookingDetailId"" = (select ""NewLabBookingDetailId"" from ""LabSampleCollection"" where ""LabSampleCollectionId"" = {id} )";
                    await this.unitOfWork.Current.ExecuteAsync(updateQuery);
                }
            }
            return transferHeader.LabTransferHeaderId;
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabTransferModel>> FetchTransferedLabsAsync(LabTransferModel model)
        {
            var where = "where 1=1";

            if (model.CreatedLabLocationId != null)
            {
                where += $@" and nlbh.""LocationId"" = {model.CreatedLabLocationId} ";
            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" ilike '%{model.RequisitionNumber}%'";
            }

            if (!string.IsNullOrEmpty(model.TransferNumber))
            {
                where += $@" and lower(lth.""TransferNumber"") ilike '%{model.TransferNumber.Trim().ToLower()}%'";
            }

            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }

            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }
            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and lth.""TransferedDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and lth.""TransferedDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (model.TransferedLocationId > 0)
            {
                where += $@" and lth.""TransferedLocationId"" = {model.TransferedLocationId} ";
            }

            if (!string.IsNullOrEmpty(model.ReceivedFromDate))
            {
                where += $@" and lts.""ReceivedDate""::date >= '{Convert.ToDateTime(model.ReceivedFromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ReceivedToDate))
            {
                where += $@" and lts.""ReceivedDate""::date <= '{Convert.ToDateTime(model.ReceivedToDate):yyyy-MM-dd}'::date";
            }

            if (model.NewLabBookingDetailId != null)
            {
                where += $@" and nlbd.""NewLabBookingDetailId"" = {model.NewLabBookingDetailId}";
            }

            if (model.Status != null)
            {
                if (model.Status == "SampleTransfered")
                {
                    where += $@" and 2=2 ";
                }
                else if (model.Status == "SampleReceivePage")
                {
                    where += $@" and (lbsd.""Status"" = 'SampleRecieved' or lbsd.""Status"" = 'SampleRejected' or lbsd.""Status"" = 'DepartmentReceived') and lts.""ReceivedBy"" is not null ";
                }
                else if (model.Status == "DataEntryPage")
                {
                    where += $@" and (lbsd.""Status"" = 'ParameterAdded' or lbsd.""Status"" = 'SampleVerified')
                                 and lbs.""Status"" <> 'TechnicianVerified' and lbs.""Status"" <> 'Verified' and lbs.""Status"" <> 'RemovedDoctor' and lbs.""Status"" <> 'DoctorAssigned' 
                                 and lbs.""Status"" <> 'UnHold' and lbs.""Status"" <> 'Hold' and  lbs.""Status"" <> 'DoctorVerified' ";
                }
                else
                {
                    where += $@" and (lbsd.""Status"" = 'SampleRecieved' or lbsd.""Status"" = 'SampleVerified' or lbsd.""Status"" = 'SampleRejected') and lth.""ReceivedBy"" is not null ";
                }

            }

            if (model.LabBookingStatusId != null)
            {
                where += $@" and nlbd .""LabBookingStatusId"" = {model.LabBookingStatusId}";
            }

            //Here I've Removed  and lbs.""Status"" = 'Verified' this PatientID
            if (model.PatientId > 0)
            {
                where += $@" and nlbh.""PatientId"" = {model.PatientId}";
            }

            if (!string.IsNullOrEmpty(model.BookingType))
            {
                if (model.BookingType == "ip")
                {
                    where += $@" and nlbh.""AdmissionId"" is not null ";
                }
                else
                {
                    where += $@" and nlbh.""AdmissionId"" is null ";
                }
            }

            if (model.LabSampleCollectionDetailId != null)
            {
                where += $@" and lscd.""LabSampleCollectionDetailId"" = {model.LabSampleCollectionDetailId} ";
            }

            var query = $@"SELECT count(lts.*) over() as ""TotalItems"",lth.""TransferNumber"",lth.""TransferedBy"",lth.""TransferedDate"", lts.""ReceivedBy"" ,lts.""ReceivedDate"",lth.""TransferedLocationId"",
			                            tb.""FullName"" as ""TransferByName"",rb.""FullName"" as ""RecievedByName"", lmd.""TestName"" ,lmd.""TestCode"", lmd.""SampleUsage"", lbs.""Status"" ,
			                            COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",nlbh.""RequisitionNumber"" ,
			                            COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
			                            e.""FullName"" as ""EmployeeName"",l.""Name"" as ""FromLocation"",p.""UMRNo"",p.""Gender"",p.""Age"",
			                            lsc.""SampleCollectedBy"" ,lsc.""CollectionDate"" ,lsc.""IsBarcodeGenerated"" ,lbs.""RowColor"",nlbh.""PaymentType"",
			                            lsc.""BarcodeGeneratedBy"" , lsc.""BarcodeDate"" , sc.""FullName""  as ""SampleCollectedByName"", ld.""DepartmentName"",
			                            bc.""FullName"" as ""BarcodeGeneratedByName"", lt.""Name"" as ""TransferedToLocation"",nlbh.""CreatedDate"" as ""BookedDate"",nlbh.""PatientId"",
                                        nlbd.""NewLabBookingDetailId"",nlbh.""NewLabBookingHeaderId"",p.""DateOfBirth"",COALESCE (nlbd.""Comment"",lscd.""Comment"") as ""Comment"",lscl.""Name"" as ""SampleCollectionLocation"",nlbd.""Emergency"",
                                        nlbd.""TechnicianComment"" ,nlbd.""TechnicianVerificationDate"" , tec.""FullName"" as ""TechnicianName"", CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType"",nlbd.""Emergency""
                                        ,lscd.""LabSampleCollectionDetailId"", lscd.""SubSampleCollectedBy"", lscd.""SubCollectionDate"",
                                    lscd.""SubIsBarcodeGenerated"", lscd.""SubBarcodeGeneratedBy"", lscd.""SubBarcodeDate"", lscd.""LocationId"", lscd.""SampleName"",
                                    subC.""FullName"" as ""SubSampleCollectedByName"", subB.""FullName"" as ""SubBarcodeGeneratedByName"", subL.""Name"" as ""SubSampleCollectionLocation"",
                                    LMD.""NoOfSamplesCollect"" ,LMD.""NoOfSamplesCollectText"" , lbsd.""Status"" as ""SubStatus"",lmd.""AssignDoctorRequired"",lt.""IsNablRequired"",lmd.""NablRequired""
                                        FROM ""LabTransferDetail"" lts
		                              join ""LabTransferHeader"" lth ON lth.""LabTransferHeaderId"" = lts.""LabTransferHeaderId""
		                              join ""Location"" lt on lt.""LocationId"" = lth.""TransferedLocationId""
		                              join ""Account"" tb on tb.""AccountId"" = lth.""TransferedBy""
		                              left join ""Account"" rb on rb.""AccountId"" = lts.""ReceivedBy""
		                              join ""NewLabBookingDetail"" nlbd ON nlbd.""NewLabBookingDetailId"" = lts.""NewLabBookingDetailId""
		                              join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                              join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
		                              join ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlbd.""NewLabBookingHeaderId""
		                              join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
		                              join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                              left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                                  left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                                  left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
	                                  left join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
	                                  left join ""Location"" lscl on lscl.""LocationId"" = lsc.""LocationId""
	                                  left join ""Account"" sc on sc.""AccountId"" = lsc.""SampleCollectedBy""
	                                  left join ""Account"" bc on bc.""AccountId"" = lsc.""BarcodeGeneratedBy""
	                                  left join ""Account"" tec on tec.""AccountId"" = nlbd.""TechnicianId""
	                                  left join ""LabSampleCollectionDetail"" lscd on  lscd.""LabSampleCollectionDetailId"" = lts.""LabSampleCollectionDetailId""
	                                   LEFT join ""LabBookingStatus"" lbsd ON lbsd.""LabBookingStatusId"" = lscd.""LabBookingStatusId""
	                                   left join ""Account"" subC on subC.""AccountId"" = lscd.""SubSampleCollectedBy""
	                                   left join ""Account"" subB ON subB.""AccountId"" = lscd.""SubBarcodeGeneratedBy""
	                                   left join ""Location"" subL on subL.""LocationId"" = lscd.""LocationId""
                                        {where}
			                            order by lts.""ReceivedDate"" desc ";
            if(model.IsExcelImport==true){
                return await this.unitOfWork.Current.QueryAsync<LabTransferModel>(query);
            }

            if (model.PageIndex != null && model.PageSize != null)
            {
                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<LabTransferModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabReceiveModel>> FetchLabReceiveSampleAsync(LabReceiveModel model)
        {
            var where = $@"where 1=1 and lth.""ReceivedBy"" is null";
            if (!string.IsNullOrEmpty(model.TransferNumber))
            {
                where += $@" and lower(lth.""TransferNumber"") = '{model.TransferNumber.Trim().ToLower()}'";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and lth.""TransferedDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and lth.""TransferedDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (model.TransferedLocationId > 0)
            {
                where += $@" and lth.""TransferedLocationId"" = {model.TransferedLocationId}";
            }

            var transferHeaderQuery = $@"SELECT  count(lth.*) over() as ""TotalItems"", lth.""LabTransferHeaderId"", lth.""TransferNumber"", lth.""TransferedBy"", lth.""TransferedDate"", lth.""TransferedLocationId"", lth.""ReceivedBy"", lth.""ReceivedDate"",
			                                tb.""FullName"" as ""TransferedByName"", rb.""FullName"" as ""ReceivedByName"", l.""Name"" as ""TransferedToLocation"",lth.""TransferredTemperature"",lth.""TransferredTemperatureComments""
                                            FROM ""LabTransferHeader"" lth
			                                join ""Account"" tb on tb.""AccountId"" = lth.""TransferedBy""
			                                join ""Location"" l ON l.""LocationId"" = lth.""TransferedLocationId""
			                                left join ""Account"" rb on rb.""AccountId"" = lth.""ReceivedBy""
                                            {where}
			                                order by lth.""TransferedDate"" desc";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                transferHeaderQuery += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }

            var headerResponse = await this.unitOfWork.Current.QueryAsync<LabReceiveModel>(transferHeaderQuery);
            foreach (var header in headerResponse)
            {
                header.Labs = new List<LabReceiveDetailModel>();
                var subWhere = $@" 1=1 and ";
                if (!string.IsNullOrEmpty(model.ToDate))
                {
                    if (model.PageName == "SampleReceivePage")
                    {
                        subWhere += $@" ltd.""ReceivedBy"" is null and ";
                    }
                }
                if (!string.IsNullOrEmpty(model.RequisitionNumber))
                {
                    subWhere += $@" nlbh.""RequisitionNumber"" ilike '{model.RequisitionNumber}' and ";
                }
                if (!string.IsNullOrEmpty(model.DepartmentName))
                {
                    subWhere += $@"  (lower(ld.""DepartmentName"") = '{model.DepartmentName.ToLower()}') and ";
                }

                if (!string.IsNullOrEmpty(model.TestName))
                {
                    subWhere += $@" (lower(lmd.""TestName"") = '{model.TestName.ToLower()}' or lower(lmd.""TestCode"") = '{model.TestName.ToLower()}') and ";
                }
                if (model.PatientId > 0)
                {
                    subWhere += $@" nlbh.""PatientId"" = {model.PatientId} and ";
                }

                if (!string.IsNullOrEmpty(model.BookingType))
                {
                    if (model.BookingType == "ip")
                    {
                        subWhere += $@" nlbh.""AdmissionId"" is not null and ";
                    }
                    else
                    {
                        subWhere += $@" nlbh.""AdmissionId"" is null and ";
                    }
                }
                var query = $@"SELECT ltd.""LabTransferDetailId"", ltd.""LabTransferHeaderId"", ltd.""NewLabBookingDetailId"",ltd.""LabSampleCollectionDetailId"",ld.""DepartmentName"",
		                                lmd.""TestName"" ,lmd.""TestCode"" ,nlbh.""RequisitionNumber"", nlbh.""LocationId"",l.""Name"" as ""CreatedLocationName"",
		                                nlbh.""CreatedDate"" as ""BookedDate"",nlbd.""NewLabBookingHeaderId"" ,lsc.""CollectionDate"" ,lbs.""RowColor"",
		                                lscd.""SubCollectionDate"" , lscd.""SampleName"",p.""FullName"" as ""PatientName"",p.""UMRNo"",p.""Mobile""
                                        FROM ""LabTransferDetail"" ltd
		                                join ""NewLabBookingDetail"" nlbd ON nlbd.""NewLabBookingDetailId"" = ltd.""NewLabBookingDetailId""
		                                join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
		                                join ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlbd.""NewLabBookingHeaderId""
                                        join ""Patient"" p on p.""PatientId"" = nlbh.""PatientId""
		                                join ""Location"" l on l.""LocationId"" = nlbh.""LocationId""
                                        join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd.""LabBookingStatusId""
		                                join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
                                        join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
                                        join ""LabSampleCollectionDetail"" lscd on lscd.""LabSampleCollectionDetailId"" = ltd.""LabSampleCollectionDetailId""
		                                where {subWhere}ltd.""LabTransferHeaderId"" = {header.LabTransferHeaderId}";
                header.Labs = (await this.unitOfWork.Current.QueryAsync<LabReceiveDetailModel>(query)).ToList();
            }

            return headerResponse;
        }

        /// <inheritdoc/>
        public async Task<int> OnReceiveSampleAsync(LabTransferModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var getTransferHeader = await this.unitOfWork.LabTransferHeaders.FindAsync(x => x.LabTransferHeaderId == model.LabTransferHeaderId);
            if (getTransferHeader == null)
            {
                transaction.Rollback();
                return -1;
            }

            var getTransferDetailsold = await this.unitOfWork.LabTransferDetails.FindAllAsync(d => d.LabTransferHeaderId == model.LabTransferHeaderId && d.ReceivedBy == null);
            var getTransferDetails = getTransferDetailsold.ToList();

            if (getTransferDetails.Count == 0)
            {
                transaction.Rollback();
                return -1;
            }

            var findReceivedStatus = await this.unitOfWork.LabBookingStatus.FindAsync(b => b.Status == "SampleRecieved");
            if (findReceivedStatus == null)
            {
                transaction.Rollback();
                return -2;
            }

            getTransferHeader.ReceivedBy = model.ReceivedBy;
            getTransferHeader.ReceivedDate = DateTime.Now;
            getTransferHeader.ReceivedTemperature = model.ReceivedTemperature;
            getTransferHeader.ReceivedTemperatureComments = model.ReceivedTemperatureComments;

            var updateResponse = await this.unitOfWork.LabTransferHeaders.UpdateAsync(getTransferHeader, transaction);
            if (updateResponse == 0)
            {
                transaction.Rollback();
                return -3;
            }
            //var SelectedSamplesList = SelectedSamples.ToList();
            for (int i = 0; i < getTransferDetails.Count; i++)
            {
                getTransferDetails[i].ReceivedBy = model.ReceivedBy;
                getTransferDetails[i].ReceivedDate = DateTime.Now;
            }
            var result = await this.unitOfWork.LabTransferDetails.BulkUpdateAsync(getTransferDetails, transaction);
            if (!result)
            {
                transaction.Rollback();
                return -19;
            }
            var sampleId = new List<int>();

            foreach (var item in getTransferDetails)
            {
                string temp = "";
                if (model.ReceivedTemperature != null)
                {
                    temp = $@" with {model.ReceivedTemperature}°C";
                }
                var findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(d => d.LabSampleCollectionDetailId == item.LabSampleCollectionDetailId);
                if (findSub == null)
                {
                    transaction.Rollback();
                    return -1;
                }

                findSub.LabBookingStatusId = findReceivedStatus.LabBookingStatusId;
                var updateSub = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub, transaction);
                if (updateSub == 0)
                {
                    transaction.Rollback();
                    return -3;
                }

                var checkIf = sampleId.Find(i => i == findSub.LabSampleCollectionId);
                if (checkIf == 0)
                {
                    sampleId.Add(findSub.LabSampleCollectionId);
                }

                var getLabBookingDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == item.NewLabBookingDetailId);
                var getLabDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == getLabBookingDetail.LabMainDetailId);

                var timeline = new LabBookingTimeLine
                {
                    CommentedBy = (int)model.ReceivedBy,
                    Comment = $@"Received samples for lab {getLabDetail.TestName}-{findSub.SampleName}{temp}",
                    CreatedDate = DateTime.Now,
                    LabBookingStatusId = findReceivedStatus.LabBookingStatusId,
                    NewLabBookingHeaderId = getLabBookingDetail.NewLabBookingHeaderId,
                    NewLabBookingDetailId = getLabBookingDetail.NewLabBookingDetailId
                };
                await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline, transaction);




                //getLabBookingDetail.LabBookingStatusId = findReceivedStatus.LabBookingStatusId;

                //var updateDetail = await this.unitOfWork.NewLabBookingDetails.UpdateAsync(getLabBookingDetail);
                //if (updateDetail == 0)
                //{
                //    return -4;
                //}
            }

            foreach (var sampleCollectionId in sampleId)
            {
                var query = $@"select count(*) from ""LabSampleCollectionDetail""  where   ""LabSampleCollectionId"" = {sampleCollectionId} and ""LabBookingStatusId"" != {findReceivedStatus.LabBookingStatusId}";
                var count = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query, transaction);
                if (count == 0)
                {
                    var updateQuery = $@"update ""NewLabBookingDetail"" set  ""LabBookingStatusId"" = {findReceivedStatus.LabBookingStatusId} where  ""NewLabBookingDetailId"" = (select ""NewLabBookingDetailId"" from ""LabSampleCollection"" where ""LabSampleCollectionId"" = {sampleCollectionId} )";
                    await this.unitOfWork.Current.ExecuteAsync(updateQuery, transaction);
                }
            }
            transaction.Commit();
            return model.LabTransferHeaderId;
        }

        /// <inheritdoc/>
        public async Task<LabParameterInputModel> FetchParametersRequiredForInputAsync(LabTransferModel model)
        {
            var newLabBookingDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == model.NewLabBookingDetailId);
            if (newLabBookingDetail == null)
            {
                return null;
            }

            var newLabBookingHeader = await this.unitOfWork.NewLabBookingHeaders.FindAsync(h => h.NewLabBookingHeaderId == newLabBookingDetail.NewLabBookingHeaderId);
            if (newLabBookingHeader == null)
            {
                return null;
            }

            var getPatientDetails = await this.unitOfWork.Patients.FindAsync(p => p.PatientId == newLabBookingHeader.PatientId);
            if (getPatientDetails == null)
            {
                return null;
            }
            var ageType = string.Empty;
            var fromAge = 0;
            var gendervalue = string.Empty;
            switch (getPatientDetails.Gender.ToString().ToUpper())
            {
                case "M":
                    gendervalue = "Male";
                    break;
                case "F":
                    gendervalue = "Female";
                    break;
                case "O":
                    gendervalue = "Other";
                    break;
            }

            if (getPatientDetails.DateOfBirth != null)
            {
                var age = this.CalculateAge(Convert.ToDateTime(getPatientDetails.DateOfBirth), DateTime.Now);
                if (age.Years > 0)
                {
                    ageType = "Years";
                    fromAge = age.Years;
                }
                else if (age.Months > 0)
                {
                    ageType = "Months";
                    fromAge = age.Months;
                }
                else if (age.Days > 0)
                {
                    ageType = "Days";
                    fromAge = age.Days;
                }
            }
            else
            {
                ageType = "Years";
                fromAge = Convert.ToInt32(getPatientDetails.Age);
            }
            var getLabMainDetailQuery = $@"SELECT lmd.""LabMainDetailId"", lmd.""TestName"", lmd.""LabDepartmentId"", lmd.""TestCode"", lmd.""LabSampleTypeId"",
                                        lmd.""Active"",ld.""DepartmentName"" ,lst.""TypeName""
	                            FROM ""LabMainDetail"" lmd
	                            join ""LabDepartment"" ld ON ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
	                            left join ""LabSampleType"" lst ON lst.""LabSampleTypeId"" = lmd.""LabSampleTypeId""
	                            where lmd.""LabMainDetailId"" = {newLabBookingDetail.LabMainDetailId}
	                            order by lmd.""CreatedDate"" desc ";

            var getLabMainDetail = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LabParameterInputModel>(getLabMainDetailQuery);
            if (getLabMainDetail == null)
            {
                return null;
            }


            var getAssingedLabTemplates = await this.unitOfWork.LabMainDetailTemplates.FindAllAsync(t => t.LabMainDetailId == getLabMainDetail.LabMainDetailId);
            if (getAssingedLabTemplates.ToList().Count == 0)
            {
                return null;
            }

            var assignedTemplatesSort = getAssingedLabTemplates.OrderBy(x => x.Priority);

            getLabMainDetail.Templates = new List<LabTemplateHeaderForInput>();

            foreach (var templates in assignedTemplatesSort)
            {

                var templateHeaderQuery = $@"SELECT lth.""LabTemplateHeaderId"", lth.""TemplateName"", lth.""TemplateId"", lth.""Active"",
	                                                   lth.""IsMethod"", lth.""IsInterpretation"",
	                                                   case when ltov.""MethodText"" is not null then ltov.""MethodText"" else lth.""MethodText"" end as ""MethodText"",
	                                                   case when ltov.""InterpretationText"" is not null then ltov.""InterpretationText"" else lth.""InterpretationText"" end as ""InterpretationText"",
	                                                   ltov.""LabTemplateObservedValueId""
		                                                FROM ""LabTemplateHeader"" lth
		                                                left join ""LabTemplateObservedValue"" ltov on ltov.""LabTemplateHeaderId"" = lth.""LabTemplateHeaderId""
		                                                and ltov.""NewLabBookingDetailId"" = {newLabBookingDetail.NewLabBookingDetailId} and ltov.""LabMainDetailId"" = {getLabMainDetail.LabMainDetailId} and ltov.""Active"" is true
		                                                where lth.""LabTemplateHeaderId"" = {templates.LabTemplateHeaderId}";

                var getTemplateHeader = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LabTemplateHeaderForInput>(templateHeaderQuery);
                if (getTemplateHeader == null)
                {
                    return null;
                }

                var getTemplateDetail = await this.unitOfWork.LabTemplateDetails.FindAllAsync(d => d.LabTemplateHeaderId == getTemplateHeader.LabTemplateHeaderId);
                if (getTemplateDetail.ToList().Count == 0)
                {
                    return null;
                }

                getTemplateHeader.Components = new List<LabComponentHeaderForInput>();
                getTemplateHeader.Parameters = new List<LabParameterInputHeaderModel>();
                var orderByTemplateDetail = getTemplateDetail.OrderBy(d => d.Priority);
                var parameterCount = 0;
                foreach (var templateDetail in orderByTemplateDetail)
                {
                    var getComponentHeader = new LabComponentHeaderForInput();
                    var getParametersHeader = new LabParameterInputHeaderModel();
                    var orderByParametersDetails = new List<LabComponentDetail>();
                    if (templateDetail.LabComponentHeaderId != null)
                    {
                        var queryComponentHeader = $@"SELECT * FROM ""LabComponentHeader"" where ""LabComponentHeaderId"" = {templateDetail.LabComponentHeaderId}";

                        getComponentHeader = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LabComponentHeaderForInput>(queryComponentHeader);
                        if (getComponentHeader == null)
                        {
                            return null;
                        }

                        var findAllParametersDetails = await this.unitOfWork.LabComponentDetails.FindAllAsync(d => d.LabComponentHeaderId == getComponentHeader.LabComponentHeaderId);
                        if (findAllParametersDetails.ToList().Count == 0)
                        {
                            return null;
                        }

                        getComponentHeader.Parameters = new List<LabParameterInputHeaderModel>();
                        orderByParametersDetails = (findAllParametersDetails.OrderBy(d => d.Priority)).ToList();
                    }
                    else if (templateDetail.LabParameterHeaderId != null)
                    {
                        var tempClass = new LabComponentDetail
                        {
                            LabParameterHeaderId = (int)templateDetail.LabParameterHeaderId,
                            LabComponentHeaderId = 0
                        };
                        orderByParametersDetails.Add(tempClass);
                    }
                    foreach (var parameters in orderByParametersDetails)
                    {

                        var extraCondition = string.Empty;
                        if (parameters.LabComponentHeaderId != 0)
                        {
                            extraCondition = $@"and lpov.""LabComponentHeaderId"" = {parameters.LabComponentHeaderId} and lpov.""Active"" is true";
                        }
                        else if (!string.IsNullOrEmpty(model.FromTech) && model.FromTech == "tech")
                        {
                            extraCondition = $@" and lpov.""Active"" is true";

                        }
                        var queryParameterHeader = $@"select lph.""LabParameterHeaderId"",lph.""ParameterName"",lph.""DisplayName"",lph.""ReferenceOutput"",lph.""Text"",
                                                     lph.""LabParameterMethodId"", lpm.""MethodName"",lpov.""LabParameterObservedValueId"",lpov.""ObservedValue"",
                                                        lpov.""LabParameterDetailId"",lpov.""Active""
  			                                         from ""LabParameterHeader"" lph
                                                     left join ""LabParameterMethod"" lpm on lpm.""LabParameterMethodId"" = lph.""LabParameterMethodId""
													 left join ""LabParameterObservedValue"" lpov on lpov.""LabParameterHeaderId"" = lph.""LabParameterHeaderId""
                                                        and lpov.""NewLabBookingDetailId"" = {newLabBookingDetail.NewLabBookingDetailId} and lpov.""LabTemplateHeaderId"" = {getTemplateHeader.LabTemplateHeaderId}
                                                        {extraCondition}
                                                     where lph.""LabParameterHeaderId"" = {parameters.LabParameterHeaderId} ";

                        var getParameterHeader = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LabParameterInputHeaderModel>(queryParameterHeader);
                        if (getParameterHeader == null)
                        {
                            return null;
                        }
                        ++parameterCount;
                        getParameterHeader.DisplayOrder = parameterCount;

                        if (getParameterHeader.ReferenceOutput != "text")
                        {

                            getParameterHeader.AllParameterDetail = new List<LabParameterDetailModel>();
                            getParameterHeader.Selected = new LabParameterDetailModel();

                            var getAllDetailQuery = $@"select lpd.""LabParameterDetailId"",lpd.""LabParameterHeaderId"",lpd.""Gender"",lpd.""FromAge"",lpd.""FromAgeType"",lpd.""ToAge"",
		                            lpd.""ToAgeType"",lpd.""MinValue"",lpd.""MaxValue"",lpd.""MinCriticalValue"",lpd.""MaxCriticalValue"",lpd.""UnitId"",
		                            lv.""Name"" as ""UnitName"", lpd.""RangeText""
			                            from ""LabParameterDetail"" lpd
			                            left join ""LookupValue"" lv on lv.""LookupValueId"" = lpd.""UnitId""
			                            where lpd.""LabParameterHeaderId"" = {parameters.LabParameterHeaderId}";
                            getParameterHeader.AllParameterDetail = (await this.unitOfWork.Current.QueryAsync<LabParameterDetailModel>(getAllDetailQuery)).ToList();
                            try
                            {
                                var functionQuery = $@" Select * from ""fetch_LabParameterDetails_on_conditions""('{ageType}',{parameters.LabParameterHeaderId},{fromAge},'{gendervalue}')";
                                var getFunctionResponse = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<LabParameterDetailModel>(functionQuery);
                                if (getFunctionResponse != null)
                                {
                                    getParameterHeader.LabParameterDetailId = getFunctionResponse.LabParameterDetailId;
                                    getParameterHeader.Selected = getParameterHeader.AllParameterDetail.Find(x => x.LabParameterDetailId == getParameterHeader.LabParameterDetailId);
                                }
                                else
                                {
                                    if (getParameterHeader.LabParameterDetailId != null)
                                    {
                                        getParameterHeader.Selected = getParameterHeader.AllParameterDetail.Find(x => x.LabParameterDetailId == getParameterHeader.LabParameterDetailId);
                                    }
                                    else
                                    {
                                        getParameterHeader.LabParameterDetailId = getParameterHeader.AllParameterDetail[0].LabParameterDetailId;
                                        getParameterHeader.Selected = getParameterHeader.AllParameterDetail[0];
                                    }
                                }
                            }
                            catch (Exception)
                            {
                                // ignore
                            }
                        }

                        if (templateDetail.LabParameterHeaderId != null)
                        {
                            getParametersHeader = getParameterHeader;
                        }
                        else
                        {
                            getComponentHeader.Parameters.Add(getParameterHeader);
                        }
                    }

                    if (templateDetail.LabParameterHeaderId != null)
                    {
                        getTemplateHeader.Parameters.Add(getParametersHeader);
                    }
                    else
                    {
                        getTemplateHeader.Components.Add(getComponentHeader);
                    }
                }
                getLabMainDetail.Templates.Add(getTemplateHeader);
                parameterCount = 0;
            }

            return getLabMainDetail;
        }

        /// <inheritdoc/>
        public async Task<int> AddParametersToLabs(InputObservedValueModel model)
        {
            var observedValues = model.Parameters.Select(x => new LabParameterObservedValue
            {
                Active = true,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                LabComponentHeaderId = x.LabComponentHeaderId > 0 ? x.LabComponentHeaderId : (int?)null,
                LabParameterDetailId = x.LabParameterDetailId,
                LabTemplateHeaderId = x.LabTemplateHeaderId,
                NewLabBookingDetailId = model.NewLabBookingDetailId,
                LabParameterHeaderId = x.LabParameterHeaderId,
                ObservedValue = x.ObservedValue
            });

            var response = await this.unitOfWork.LabParameterObservedValues.BulkInsertAsync(observedValues);
            if (response > 0)
            {
                var statuses = (await this.unitOfWork.LabBookingStatus.FindAllAsync()).ToList();
                var count = 0;
                var getPreviousId = model.Parameters.Where(x => x.LabParameterObservedValueId != null).ToList();
                if (getPreviousId.Count > 0)
                {
                    var concatedIds = string.Join(",", getPreviousId.Select(x => x.LabParameterObservedValueId.ToString()));
                    if (!string.IsNullOrEmpty(concatedIds))
                    {
                        var updateQuery = $@"UPDATE ""LabParameterObservedValue"" SET  ""Active""= false WHERE ""LabParameterObservedValueId"" in ({concatedIds})";
                        await this.unitOfWork.Current.ExecuteAsync(updateQuery);
                        count += 1;
                    }
                }

                var findSub = new LabSampleCollectionDetail();
                if (model.LabSampleCollectionDetailId != null)
                {
                    findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(s => s.LabSampleCollectionDetailId == model.LabSampleCollectionDetailId);
                    if (findSub != null)
                    {
                        findSub.LabBookingStatusId = statuses.Find(x => x.Status == "ParameterAdded").LabBookingStatusId;
                        var subUpdateRes = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub);
                        if (subUpdateRes == 0)
                        {
                            return 0;
                        }
                    }
                }

                var getLabBookingDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == model.NewLabBookingDetailId);
                var getLabDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == getLabBookingDetail.LabMainDetailId);

                var findReceivedStatus = statuses.Find(x => x.Status == "ParameterAdded");
                var timeline = new LabBookingTimeLine
                {
                    CommentedBy = (int)model.CreatedBy,
                    Comment = $@"Parameters {(count > 0 ? "updated" : "added")} for lab {getLabDetail.TestName} ",
                    CreatedDate = DateTime.Now,
                    LabBookingStatusId = findReceivedStatus.LabBookingStatusId,
                    NewLabBookingHeaderId = getLabBookingDetail.NewLabBookingHeaderId,
                    NewLabBookingDetailId = getLabBookingDetail.NewLabBookingDetailId
                };
                await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline);

                if (findSub != null && findSub.LabSampleCollectionDetailId > 0)
                {
                    var checkQuerry = $@"select count(*) from ""LabSampleCollectionDetail"" where ""LabSampleCollectionId"" = {findSub.LabSampleCollectionId}
                                        and ""LabBookingStatusId"" not in ({findReceivedStatus.LabBookingStatusId},{(statuses.Find(s => s.Status == "SampleRejected")).LabBookingStatusId})";
                    var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(checkQuerry);
                    if (checkIf == 0)
                    {
                        getLabBookingDetail.LabBookingStatusId = findReceivedStatus.LabBookingStatusId;
                    }
                }

                getLabBookingDetail.TechnicianComment = null;
                getLabBookingDetail.TechnicianId = null;
                getLabBookingDetail.TechnicianVerificationDate = null;
                await this.unitOfWork.NewLabBookingDetails.UpdateAsync(getLabBookingDetail);
            }

            return response;
        }

        /// <inheritdoc/>
        public async Task<int> AddTemplateDetailsToLabs(TemplateInputModel model)
        {
            var templates = model.Templates.Select(t => new LabTemplateObservedValue
            {
                Active = true,
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                InterpretationText = !string.IsNullOrEmpty(t.InterpretationText) ? t.InterpretationText.Trim() : null,
                MethodText = !string.IsNullOrEmpty(t.MethodText) ? t.MethodText.Trim() : null,
                LabMainDetailId = t.LabMainDetailId,
                LabTemplateHeaderId = t.LabTemplateHeaderId,
                NewLabBookingDetailId = model.NewLabBookingDetailId
            });

            var response = await this.unitOfWork.LabTemplateObservedValues.BulkInsertAsync(templates);

            if (response > 0)
            {
                var statuses = (await this.unitOfWork.LabBookingStatus.FindAllAsync()).ToList();
                var count = 0;
                var getPreviousId = model.Templates.Where(x => x.LabTemplateObservedValueId != null && x.LabTemplateObservedValueId > 0).ToList();
                if (getPreviousId.Count > 0)
                {
                    var concatedIds = string.Join(",", getPreviousId.Select(x => x.LabTemplateObservedValueId.ToString()));
                    if (!string.IsNullOrEmpty(concatedIds))
                    {
                        var updateQuery = $@"UPDATE ""LabTemplateObservedValue"" SET  ""Active""= false WHERE ""LabTemplateObservedValueId"" in ({concatedIds})";
                        await this.unitOfWork.Current.ExecuteAsync(updateQuery);
                        count += 1;
                    }
                }

                var findSub = new LabSampleCollectionDetail();
                if (model.LabSampleCollectionDetailId != null)
                {
                    findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(s => s.LabSampleCollectionDetailId == model.LabSampleCollectionDetailId);
                    if (findSub != null)
                    {
                        findSub.LabBookingStatusId = statuses.Find(x => x.Status == "ParameterAdded").LabBookingStatusId;
                        var subUpdateRes = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub);
                        if (subUpdateRes == 0)
                        {
                            return 0;
                        }
                    }
                }

                var getLabBookingDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == model.NewLabBookingDetailId);
                var getLabDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == getLabBookingDetail.LabMainDetailId);

                var findReceivedStatus = statuses.Find(x => x.Status == "ParameterAdded");
                var timeline = new LabBookingTimeLine
                {
                    CommentedBy = (int)model.CreatedBy,
                    Comment = $@"Templates {(count > 0 ? "updated" : "added")} for lab {getLabDetail.TestName}",
                    CreatedDate = DateTime.Now,
                    LabBookingStatusId = findReceivedStatus.LabBookingStatusId,
                    NewLabBookingHeaderId = getLabBookingDetail.NewLabBookingHeaderId,
                    NewLabBookingDetailId = getLabBookingDetail.NewLabBookingDetailId
                };
                await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline);
                if (findSub != null && findSub.LabSampleCollectionDetailId > 0)
                {
                    var checkQuerry = $@"select count(*) from ""LabSampleCollectionDetail"" where ""LabSampleCollectionId"" = {findSub.LabSampleCollectionId}
                                        and ""LabBookingStatusId"" not in ({findReceivedStatus.LabBookingStatusId},{(statuses.Find(s => s.Status == "SampleRejected")).LabBookingStatusId})";
                    var checkIf = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(checkQuerry);
                    if (checkIf == 0)
                    {
                        getLabBookingDetail.LabBookingStatusId = findReceivedStatus.LabBookingStatusId;
                    }
                }
                getLabBookingDetail.TechnicianComment = null;
                getLabBookingDetail.TechnicianId = null;
                getLabBookingDetail.TechnicianVerificationDate = null;
                await this.unitOfWork.NewLabBookingDetails.UpdateAsync(getLabBookingDetail);
            }

            return response;
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabBookingStatusModel>> FetchLabStatusTimeline(int? newLabBookingHeaderId, int? newLabBookingDetailId)
        {
            var where = "where 1=1";
            var id = 0;
            if (newLabBookingHeaderId != null)
            {
                id = Convert.ToInt32(newLabBookingHeaderId);
                where += $@" and lbt.""NewLabBookingHeaderId"" = {id}";
            }
            else
            {
                var getLabDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(b => b.NewLabBookingDetailId == Convert.ToInt32(newLabBookingDetailId));
                id = getLabDetail.NewLabBookingHeaderId;
                where += $@" and lbt.""NewLabBookingHeaderId"" = {id} and ""NewLabBookingDetailId"" = {Convert.ToInt32(newLabBookingDetailId)}";
            }

            var query = $@"select lbt.""LabBookingTimeLineId"", lbt.""NewLabBookingHeaderId"", lbt.""LabBookingStatusId"", lbt.""Comment"", lbt.""CommentedBy"", lbt.""CreatedDate"",
		                            lbs.""Status"", a.""FullName"" as ""CommentedByName"",r.""RoleName""
	                            from  ""LabBookingTimeLine"" lbt
	                            join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId""  = lbt.""LabBookingStatusId""
	                            join ""Account"" a ON a.""AccountId"" = lbt.""CommentedBy""
	                            join ""Role"" r on r.""RoleId"" = a.""RoleId""
	                            {where}
	                            order by lbt.""CreatedDate"" asc ";

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

        public async Task<int> CollectSampleAndGenerateBarcodeAsyncNew(List<LabSampleHandlerModel> model, int locationId)
        {
            int response = 0;
            var status = (await this.unitOfWork.LabBookingStatus.FindAllAsync()).ToList();
            if (status.Count == 0)
            {
                return 0;
            }

            var bookingIds = new List<int>();

            for (int k = 0; k < model.Count; k++)
            {
                var getDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == model[k].NewLabBookingDetailId);
                if (getDetail == null)
                {
                    return -2;
                }

                var checkIfSampleCollected = await this.unitOfWork.LabSampleCollections.FindAsync(x => x.LabSampleCollectionId == model[k].LabSampleCollectionId);
                if (checkIfSampleCollected != null)
                {
                    var checkInArray = bookingIds.Find(x => x == checkIfSampleCollected.LabSampleCollectionId);
                    if (checkInArray == 0)
                    {
                        bookingIds.Add(checkIfSampleCollected.LabSampleCollectionId);
                    }
                    var findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(c => c.LabSampleCollectionDetailId == model[k].LabSampleCollectionDetailId);
                    if (findSub != null)
                    {
                        findSub.SubSampleCollectedBy = model[k].CreatedBy;
                        findSub.SubBarcodeGeneratedBy = model[k].CreatedBy;
                        findSub.SubIsBarcodeGenerated = true;
                        findSub.SubBarcodeDate = DateTime.Now;
                        findSub.SubCollectionDate = DateTime.Now;
                        findSub.LocationId = locationId;
                        findSub.LabBookingStatusId = (status.Find(s => s.Status == "SampleCollected")).LabBookingStatusId;
                        var update = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub);
                    }

                    checkIfSampleCollected.BarcodeDate = DateTime.Now;
                    checkIfSampleCollected.BarcodeGeneratedBy = model[k].CreatedBy;
                    checkIfSampleCollected.CollectionDate = DateTime.Now;
                    checkIfSampleCollected.IsBarcodeGenerated = true;
                    checkIfSampleCollected.SampleCollectedBy = model[k].CreatedBy;
                    checkIfSampleCollected.LocationId = locationId;

                    response = await this.unitOfWork.LabSampleCollections.UpdateAsync(checkIfSampleCollected);

                    if (response == 0)
                    {
                        return -1;
                    }
                    getDetail.LabBookingStatusId = (status.Find(x => x.Status == "PartiallyCollected")).LabBookingStatusId;

                    await this.unitOfWork.NewLabBookingDetails.UpdateAsync(getDetail);
                    var getMainLabDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == getDetail.LabMainDetailId);
                    var timeLine = new LabBookingTimeLine
                    {
                        Comment = $@"Sample collected for lab {getMainLabDetail.TestName} {findSub.SampleName}",
                        CommentedBy = model[k].CreatedBy,
                        CreatedDate = DateTime.Now,
                        LabBookingStatusId = (status.Find(x => x.Status == "SampleCollected")).LabBookingStatusId,
                        NewLabBookingHeaderId = getDetail.NewLabBookingHeaderId,
                        NewLabBookingDetailId = getDetail.NewLabBookingDetailId
                    };

                    await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeLine);
                    //return response;
                }
                else
                {
                    return -3;
                }
            }

            foreach (var id in bookingIds)
            {
                var query = $@"select count(*) from ""LabSampleCollectionDetail""  where   ""LabSampleCollectionId"" = {id} and ""SubSampleCollectedBy"" is null";
                var count = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query);
                if (count == 0)
                {
                    var getComplete = status.Find(x => x.Status == "Collected");
                    var updateQuery = $@"update ""NewLabBookingDetail"" set  ""LabBookingStatusId"" = {getComplete.LabBookingStatusId} where  ""NewLabBookingDetailId"" = (select ""NewLabBookingDetailId"" from ""LabSampleCollection"" where ""LabSampleCollectionId"" = {id} )";
                    await this.unitOfWork.Current.ExecuteAsync(updateQuery);
                }
            }

            return 1;
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabTransferModel>> FetchTransferedTrackRecords(LabTransferModel model)
        {
            var where = "where 1=1";

            if (model.CreatedLabLocationId != null)
            {
                where += $@" and nlbh.""LocationId"" = {model.CreatedLabLocationId} ";
            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" = '{model.RequisitionNumber}'";
            }

            if (!string.IsNullOrEmpty(model.TransferNumber))
            {
                where += $@" and lower(lth.""TransferNumber"") = '{model.TransferNumber.Trim().ToLower()}'";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and lth.""TransferedDate"" >= '{model.FromDate}'";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and lth.""TransferedDate"" <= '{model.ToDate}'";
            }

            var query = $@"SELECT count(lts.*) over() as ""TotalItems"",lth.""TransferNumber"",lth.""TransferedBy"",lth.""TransferedDate"", lth.""ReceivedBy"" ,lth.""ReceivedDate"",lth.""TransferedLocationId"",
			                            tb.""FullName"" as ""TransferByName"",rb.""FullName"" as ""RecievedByName"", lmd.""TestName"" ,lmd.""TestCode"", lbs.""Status"" ,
			                            COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",nlbh.""RequisitionNumber"" ,
			                            COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
			                            e.""FullName"" as ""EmployeeName"",l.""Name"" as ""FromLocation"",p.""UMRNo"",p.""Gender"",p.""Age"",
			                            lsc.""SampleCollectedBy"" ,lsc.""CollectionDate"" ,lsc.""IsBarcodeGenerated"" ,
			                            lsc.""BarcodeGeneratedBy"" , lsc.""BarcodeDate"" , sc.""FullName""  as ""SampleCollectedByName"",
			                            bc.""FullName"" as ""BarcodeGeneratedByName"", lt.""Name"" as ""TransferedToLocation"",nlbh.""CreatedDate"" as ""BookedDate"",nlbh.""PatientId"",
                                        nlbd.""NewLabBookingDetailId"",nlbh.""NewLabBookingHeaderId"",p.""DateOfBirth""
                                      FROM ""LabTransferDetail"" lts
		                              join ""LabTransferHeader"" lth ON lth.""LabTransferHeaderId"" = lts.""LabTransferHeaderId""
		                              join ""Location"" lt on lt.""LocationId"" = lth.""TransferedLocationId""
		                              join ""Account"" tb on tb.""AccountId"" = lth.""TransferedBy""
		                              left join ""Account"" rb on rb.""AccountId"" = lth.""ReceivedBy""
		                              join ""NewLabBookingDetail"" nlbd ON nlbd.""NewLabBookingDetailId"" = lts.""NewLabBookingDetailId""
		                              join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                              join ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlbd.""NewLabBookingHeaderId""
		                              join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
		                              join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                              left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                                  left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                                  left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
	                                  left join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
	                                  left join ""Account"" sc on sc.""AccountId"" = lsc.""SampleCollectedBy""
	                                  left join ""Account"" bc on bc.""AccountId"" = lsc.""BarcodeGeneratedBy""
                                        {where}
			                            order by lth.""TransferedDate"" desc";

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

        /// <inheritdoc/>
        public async Task<IEnumerable<PatientLabBillModel>> FetchPatientLabBillAsync(PatientLabBillModel model)
        {
            var where = "where 1=1";

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" = '{model.RequisitionNumber}'";
            }

            if (model.PatientId > 0)
            {
                where += $@" and nlbh.""PatientId"" = {model.PatientId}";
            }

            var query = $@"(select Count(*) OVER() AS ""TotalItems"" ,nlbh.""NewLabBookingHeaderId"" as ""HeaderId"",nlbh.""RequisitionNumber"",nlbh.""CreatedDate"",nlbh.""OverallNetAmount"" as ""Amount"",'Billed' as ""BillType"",p.""FullName"" as ""PatientName"", p.""UMRNo"",prv.""FullName"" as ""DoctorName"" from ""NewLabBookingHeader"" nlbh
                            join ""Patient"" p on p.""PatientId"" = nlbh.""PatientId""
                            join ""Provider"" prv on prv.""ProviderId"" =nlbh.""DoctorId""
                            {where})
                            union all
                            (select Count(*) OVER() AS ""TotalItems"" ,nlcbh.""NewLabCancelBookingHeaderId"" as ""HeaderId"",nlbh.""RequisitionNumber"",nlcbh.""CreatedDate"",nlcbh.""TotalReturnAmount"" as ""Amount"",'Cancelled' as ""BillType"",p.""FullName"" as ""PatientName"", p.""UMRNo"",prv.""FullName"" as ""DoctorName"" from ""NewLabCancelBookingHeader"" nlcbh
                            join ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlcbh.""NewLabBookingHeaderId""
                            join ""Patient"" p on p.""PatientId"" = nlbh.""PatientId""
                            join ""Provider"" prv on prv.""ProviderId"" =nlbh.""DoctorId""
                            {where}) order by ""CreatedDate"" desc";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            }
            var Responses = await this.unitOfWork.Current.QueryAsync<PatientLabBillModel>(query);
            return Responses;
        }

        /// <inheritdoc/>
        public async Task<int> UploadLabReportAsync(NewLabBookingDetailModel model)
        {
            var parameterStatus = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "ParameterAdded" && x.Active);
            if (parameterStatus == null)
            {
                return 0;
            }
            var status = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "Verified" && x.Active);
            if (status == null)
            {
                return 0;
            }

            var find = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == model.NewLabBookingDetailId);
            if (find == null)
            {
                return -1;
            }
            var labMainDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == find.LabMainDetailId);

            find.ReportUrl = model.ReportUrl;
            find.UploadedBy = model.UploadedBy;
            find.UploadedDate = DateTime.Now;
            if (labMainDetail.IsExternalLab)
            {
                find.LabBookingStatusId = status.LabBookingStatusId;
            }


            var response = await this.unitOfWork.NewLabBookingDetails.UpdateAsync(find);
            if (response > 0)
            {
                var timeLine = new LabBookingTimeLine
                {
                    Comment = $@"Report uploaded for lab {model.TestName}",
                    CommentedBy = (int)model.UploadedBy,
                    CreatedDate = DateTime.Now,
                    LabBookingStatusId = labMainDetail.IsExternalLab ? status.LabBookingStatusId : parameterStatus.LabBookingStatusId,
                    NewLabBookingHeaderId = find.NewLabBookingHeaderId,
                    NewLabBookingDetailId = find.NewLabBookingDetailId
                };
                await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeLine);
            }

            return response;
        }

        /// <inheritdoc/>
        public async Task<NewLabBookingDetailModel> FetchNewLabBookingDetailAsync(NewLabBookingDetailModel model)
        {
            var query = $@"SELECT nlbd.""NewLabBookingDetailId"", nlbd.""NewLabBookingHeaderId"",
                            (case when nlbd.""ReportUrl"" is not null then CONCAT('{this.runningEnvironment.CurrentEnvironment}', '/',nlbd.""ReportUrl"" ) ELSE NULL END) as ""ReportUrl"",
                            nlbd.""ExternalLab"", nlbd.""UploadedBy"", nlbd.""UploadedDate"", a.""FullName"" as ""UploadedByName"",lmd.""IsExternalLab""
                             FROM ""NewLabBookingDetail"" nlbd
                             left join ""Account"" a on a.""AccountId"" = nlbd.""UploadedBy""
                             join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
                             where nlbd.""NewLabBookingDetailId"" = {model.NewLabBookingDetailId}
                             limit 1";

            return await this.unitOfWork.Current.QueryFirstOrDefaultAsync<NewLabBookingDetailModel>(query);
        }

        /// <inheritdoc/>
        public async Task<LabTransferHeader> FetchTransferHeader(int transferHaderId)
        {
            var getMainLabDetail = await this.unitOfWork.LabTransferHeaders.FindAsync(l => l.LabTransferHeaderId == transferHaderId);
            return getMainLabDetail;
        }


        /// <inheritdoc/>
        public async Task<IEnumerable<LabSampleHandlerModel>> FetchLabsForSampleTransferAsync(LabSampleHandlerModel model)
        {
            var where = "where 1=1";

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

            if (model.NewLabBookingHeaderId > 0)
            {
                where += $@" and nlbh.""NewLabBookingHeaderId"" = {model.NewLabBookingHeaderId} and lbs.""Status"" != 'Cancelled'";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and lsc.""CollectionDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and lsc.""CollectionDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" ilike '%{model.RequisitionNumber}%'";
            }
            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }
            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }
            if (model.LabBookingStatusId != null)
            {
                where += $@" and  nlbd.""LabBookingStatusId"" = {model.LabBookingStatusId}";
            }

            if (model.IsShowSampleCollected != null)
            {
                where += (bool)model.IsShowSampleCollected ? $@" and lbsd.""Status"" = 'SampleCollected'" : string.Empty;
            }

            if (model.IsInternalLab)
            {
                where += $@" and lmd.""IsInternalLab"" is true";
            }

            if (model.IsExternalLab)
            {
                where += $@" and lmd.""IsExternalLab"" is true";
            }

            if (!string.IsNullOrEmpty(model.BookingType))
            {
                if (model.BookingType == "ip")
                {
                    where += $@" and nlbh.""AdmissionId"" is not null ";
                }
                else
                {
                    where += $@" and nlbh.""AdmissionId"" is null ";
                }
            }
            var query = $@"SELECT count(nlbh.*) over () as ""TotalItems"",nlbh.""NewLabBookingHeaderId"", nlbh.""RequisitionNumber"", nlbh.""Type"", nlbh.""PatientId"", nlbh.""DoctorId"", nlbh.""EmployeeId"",
                                       nlbh.""LocationId"", nlbh.""OverallTotalAmount"", nlbh.""OverallDiscount"", nlbh.""OverallNetAmount"", nlbh.""OverallDiscountPercentage"", nlbh.""PayTypeId"",
                                    nlbh.""PaymentNumber"", nlbh.""CreatedBy"", nlbh.""CreatedDate"", nlbh.""ModifiedBy"", nlbh.""ModifiedDate"", nlbh.""Active""  ,
                                    c.""FullName"" as ""CreatedByName"",m.""FullName"" as ""ModifiedByName"",COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",
                                    COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
                                    (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('{this.runningEnvironment.CurrentEnvironment}/', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",
                                    e.""FullName"" as ""EmployeeName"",pt.""PayTypeName"" ,l.""Name"" as ""LocationName"",p.""UMRNo"",p.""Gender"",p.""Age"",
                                    nlbd.""NewLabBookingDetailId"", nlbd.""LabMainDetailId"", nlbd.""ChargeCategoryId"", nlbd.""LabBookingStatusId"", nlbd.""DiscountPercentage"",
		                            nlbd.""DiscountAmount"", nlbd.""TotalAmount"", nlbd.""NetAmount"", lbs.""Status"",
		                            lmd.""TestName"",lmd.""TestCode"", lmd.""IsExternalLab"", lmd.""IsInternalLab"" , ld.""DepartmentName"" ,cc.""ChargeCategoryName"" ,lst.""TypeName"",
		                            lsc.""LabSampleCollectionId"" ,lsc.""SampleCollectedBy"" ,lsc.""CollectionDate"" ,lsc.""IsBarcodeGenerated"" ,lbs.""RowColor"",
		                            lsc.""BarcodeGeneratedBy"" , lsc.""BarcodeDate"" , sc.""FullName""  as ""SampleCollectedByName"",lmd.""SampleUsage"",lmd.""ConsentFormRequired"",
		                            bc.""FullName"" as ""BarcodeGeneratedByName"",nlbd.""Comment"", CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType"",nlbd.""Emergency""
                                 	,lscd.""LabSampleCollectionDetailId"", lscd.""SubSampleCollectedBy"", lscd.""SubCollectionDate"",
                                    lscd.""SubIsBarcodeGenerated"", lscd.""SubBarcodeGeneratedBy"", lscd.""SubBarcodeDate"", lscd.""LocationId"", lscd.""SampleName"",
                                    subC.""FullName"" as ""SubSampleCollectedByName"", subB.""FullName"" as ""SubBarcodeGeneratedByName"", subL.""Name"" as ""SubSampleCollectionLocation"",
                                    LMD.""NoOfSamplesCollect"" ,LMD.""NoOfSamplesCollectText"" , lbsd.""Status"" as ""SubStatus""
		                            FROM ""NewLabBookingHeader"" nlbh
                                   join ""NewLabBookingDetail"" nlbd on nlbd.""NewLabBookingHeaderId"" = nlbh.""NewLabBookingHeaderId""
                                   join ""Account"" c on c.""AccountId"" = nlbh.""CreatedBy""
                                   left join ""PayType"" pt ON pt.""PayTypeId"" = nlbh.""PayTypeId""
                                   join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
                                   join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                           join ""LabMainDetail"" lmd ON lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                           join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
		                           join ""ChargeCategory"" cc on cc.""ChargeCategoryId"" = nlbd.""ChargeCategoryId""
		                           left join ""LabSampleType"" lst on lst.""LabSampleTypeId"" = lmd.""LabSampleTypeId""
	                               left join ""Account"" m on m.""AccountId"" = nlbh.""ModifiedBy""
	                               left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                               left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                               left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
                                   left join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
                                   left join ""LabSampleCollectionDetail"" lscd on lscd.""LabSampleCollectionId"" = lsc.""LabSampleCollectionId""
                                   LEFT join ""LabBookingStatus"" lbsd ON lbsd.""LabBookingStatusId"" = lscd.""LabBookingStatusId""
                                   left join ""Account"" subC on subC.""AccountId"" = lscd.""SubSampleCollectedBy""
                                   left join ""Account"" subB ON subB.""AccountId"" = lscd.""SubBarcodeGeneratedBy""
                                   left join ""Location"" subL on subL.""LocationId"" = lscd.""LocationId""
                                   left join ""Account"" sc on sc.""AccountId"" = lsc.""SampleCollectedBy""
                                   left join ""Account"" bc on bc.""AccountId"" = lsc.""BarcodeGeneratedBy""
                                   {where}
	                               order by lsc.""CollectionDate"" desc ";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }

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

        /// <summary>
        /// Fetches the new lab booking detail.
        /// </summary>
        /// <param name="NewLabBookingDetailId">The new lab booking detail identifier.</param>
        /// <returns></returns>
        public async Task<NewLabBookingDetail> FetchNewLabBookingDetail(int NewLabBookingDetailId)
        {
            var NewLabBookingDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(l => l.NewLabBookingDetailId == NewLabBookingDetailId);
            return NewLabBookingDetail;
        }

        /// <inheritdoc/>
        public async Task<int> AddTechnicianVerificationAsync(LabTechnicianVerificationModel model)
        {
            var findBooking = await this.unitOfWork.NewLabBookingDetails.FindAsync(x => x.NewLabBookingDetailId == model.NewLabBookingDetailId);
            if (findBooking == null)
            {
                return 0;
            }

            var getStatus = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "TechnicianVerified");
            if (getStatus == null)
            {
                return 0;
            }

            findBooking.LabBookingStatusId = getStatus.LabBookingStatusId;
            findBooking.TechnicianComment = model.TechnicianComment;
            findBooking.TechnicianId = model.TechnicianId;
            findBooking.TechnicianVerificationDate = DateTime.Now;

            var response = await this.unitOfWork.NewLabBookingDetails.UpdateAsync(findBooking);

            if (response > 0)
            {
                var findLabName = await this.unitOfWork.LabMainDetails.FindAsync(x => x.LabMainDetailId == findBooking.LabMainDetailId);
                var timeLine = new LabBookingTimeLine
                {
                    Comment = $@"Lab technician verified {findLabName.TestName} lab",
                    CommentedBy = (int)model.TechnicianId,
                    CreatedDate = DateTime.Now,
                    LabBookingStatusId = getStatus.LabBookingStatusId,
                    NewLabBookingHeaderId = findBooking.NewLabBookingHeaderId,
                    NewLabBookingDetailId = findBooking.NewLabBookingDetailId
                };
                await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeLine);
            }
            return response;
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabTransferModel>> FetchLabsForTechnicianAndDoctorAsync(LabSampleHandlerModel model)
        {
            var where = "where 1=1";

            if (model.NewLabBookingHeaderId > 0)
            {
                where += $@" and nlbh.""NewLabBookingHeaderId"" = {model.NewLabBookingHeaderId} and lbs.""Status"" != 'Cancelled'";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and nlbh.""CreatedDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and nlbh.""CreatedDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" ilike '%{model.RequisitionNumber}%'";
            }

            if (model.PatientId > 0)
            {
                where += $@" and  nlbh.""PatientId"" = {model.PatientId}";
            }
            if (model.DoctorId > 0)
            {
                where += $@" and  nlbh.""DoctorId"" = {model.DoctorId}";
            }
           
            if (model.LabMainDetailId > 0)
            {
                where += $@" and  nlbd.""LabMainDetailId"" = {model.LabMainDetailId}";
            }

            if (!string.IsNullOrEmpty(model.UMRNo ))
            {
                where +=$@" and  P.""UMRNo"" ilike '%{model.UMRNo}%'";
            }
            if (!string.IsNullOrEmpty(model.BookingType))
            {
                if (model.BookingType == "ip")
                {
                    where += $@" and nlbh.""AdmissionId"" is not null ";
                }
                else
                {
                    where += $@" and nlbh.""AdmissionId"" is null ";
                }
            }
            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }

            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }

            if (model.LabBookingStatusId != null)
            {
                where += $@" and  nlbd.""LabBookingStatusId"" = {model.LabBookingStatusId}";
            }

            if (!string.IsNullOrEmpty(model.Status) && model.Status == "Verified")
            {
                where += $@" and  lbs.""Status"" = 'Verified'";
            }

            if (model.IsShowSampleCollected != null)
            {
                where += (bool)model.IsShowSampleCollected ? $@" and lbs.""Status"" = 'SampleCollected'" : string.Empty;
            }

            if (model.IsInternalLab)
            {
                where += $@" and lmd.""IsInternalLab"" is true";
            }

            if (model.LocationId != null && model.LocationId > 0)
            {
                where += $@" and lth.""TransferedLocationId"" = {model.LocationId}";
            }

            var query = $@"with allData as (select distinct ltd.""NewLabBookingDetailId"", max(ltd.""LabTransferHeaderId"") over (partition by (ltd.""NewLabBookingDetailId"")) as ""LabTransferHeaderId"" ,max(ltd.""LabTransferDetailId"") over (partition by (ltd.""NewLabBookingDetailId"")) as ""LabTransferDetailId""
			                ,max(lth.""TransferedDate"" ) over (partition by (ltd.""NewLabBookingDetailId"")) as ""TransferedDate"" , tr.""FullName"" as ""TransferByName"",
				                max(lth.""ReceivedDate"" ) over (partition by (ltd.""NewLabBookingDetailId"")) as ""ReceivedDate"",
				                l.""LocationId"" as ""TransferedLocationId"" ,l.""Name"" as ""TransferedLocation"" ,lbs.""Active"", nlbh.""DoctorId"",
			                rb.""FullName"" as ""RecievedByName"",nlbd.""NewLabBookingDetailId"", nlbd.""NewLabBookingHeaderId"", nlbd.""LabMainDetailId"", nlbd.""ChargeCategoryId"", nlbd.""LabBookingStatusId"",
		                    nlbd.""Comment"",  nlbd.""HoldBy"",  nlbd.""UnHoldBy"",  nlbd.""HoldComments"",  nlbd.""UnHoldComments"",  nlbd.""Emergency"",  nlbd.""TechnicianId"",
		                    nlbd.""TechnicianComment"",  nlbd.""TechnicianVerificationDate"", nlbh.""RequisitionNumber"" , nlbh.""CreatedDate"" as ""BookedDate"" , nlbh.""LocationId"" ,a.""EncounterType"",nlbh.""AppointmentId"" ,
		                    bl.""Name"" as ""BilledLocation"", lsc.""CollectionDate"" ,sl.""Name"" as ""SampleCollectionLocation"", sa.""FullName"" as ""SampleCollectedByName"",
		                    lbs.""Status"" ,lmd.""TestName"" ,lmd.""TestCode"",COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",
		                    COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
		                    p.""UMRNo"" , CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType"",p.""PatientId"",
		                    e.""FullName"" as ""EmployeeName"", ld.""DepartmentName"",p.""DateOfBirth"", tech.""FullName"" as ""TechnicianName""
			                from ""LabTransferDetail"" ltd
					        join ""LabTransferHeader"" lth on lth.""LabTransferHeaderId"" = ltd.""LabTransferHeaderId""
					        join ""Account"" tr on tr.""AccountId"" = lth.""TransferedBy""
					        join ""Location"" l on l.""LocationId"" = lth.""TransferedLocationId""
					        left join ""Account"" rb on rb.""AccountId"" = lth.""ReceivedBy""
					        join ""NewLabBookingDetail"" nlbd on nlbd.""NewLabBookingDetailId"" = ltd.""NewLabBookingDetailId""
			                join ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlbd.""NewLabBookingHeaderId""
			                join ""LabBookingStatus"" lbs on lbs.""LabBookingStatusId"" = nlbd.""LabBookingStatusId""
			                join ""Location"" bl on bl.""LocationId"" = nlbh.""LocationId""
			                join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
			                join ""Location"" sl on sl.""LocationId"" = lsc.""LocationId""
			                join ""Account"" sa on sa.""AccountId"" = lsc.""SampleCollectedBy""
			                join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                    join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
                            left join ""Appointment"" a on a.""AppointmentId"" = nlbh.""AppointmentId""
		                    left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                        left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                        left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
                            left join ""Account"" tech ON tech.""AccountId"" = nlbd.""TechnicianId""
	                         {where}
	                        order by nlbh.""CreatedDate"" desc) select count(*) over() as ""TotalItems"" ,* from allData ";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }

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

        /// <inheritdoc/>
        public async Task<IEnumerable<CheckTransferLocationModel>> FetchPreviousTransferDetailsAsync(CheckTransferLocationModel model)
        {
            var where = " where 1=1 ";

            if (!string.IsNullOrEmpty(model.BookingIds))
            {
                where += $@" and ltd.""NewLabBookingDetailId"" in ({model.BookingIds})";
            }

            var query = $@"select distinct ltd.""NewLabBookingDetailId"" ,lth.""TransferedLocationId"" , l.""Name"" as ""TransferLocationName"" from
	                            ""LabTransferHeader"" lth
	                            join ""LabTransferDetail"" ltd on ltd.""LabTransferHeaderId"" = lth.""LabTransferHeaderId""
	                            join ""Location"" l on l.""LocationId"" = lth.""TransferedLocationId""
	                            {where} ";

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

        /// <summary>
        /// Gets the latest transfer number asynchronous.
        /// </summary>
        /// <returns></returns>
        private async Task<string> GetLatestTransferNumberAsync()
        {
            var fixedText = "T";
            var previous = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>($@"select ""TransferNumber"" from ""LabTransferHeader"" order by ""LabTransferHeaderId"" desc limit 1");
            if (previous == null)
            {
                return $@"{fixedText}{DateTime.Now:yyyy}1";
            }
            else
            {
                var numWithoutFixedText = previous.Replace(fixedText, "");
                var getYear = numWithoutFixedText[..4];
                if (getYear != DateTime.Now.ToString("yyyy"))
                {
                    return $@"{fixedText}{DateTime.Now:yyyy}1";
                }
                var getNumber = numWithoutFixedText.Replace(DateTime.Now.ToString("yyyy"), "");
                var getCurrentCount = long.Parse(getNumber) + 1;
                return $@"{fixedText}{DateTime.Now:yyyy}{getCurrentCount}";
            }
        }

        /// <summary>
        /// Gets the latest external transfer number asynchronous.
        /// </summary>
        /// <returns></returns>
        private async Task<string> GetLatestExternalTransferNumberAsync()
        {
            var fixedText = "ET";
            var previous = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>($@"select ""TransferNumber"" from ""ExternalLabTransfer"" order by ""ExternalLabTransferId"" desc limit 1");
            if (previous == null)
            {
                return $@"{fixedText}{DateTime.Now:yyyy}1";
            }
            else
            {
                var numWithoutFixedText = previous.Replace(fixedText, "");
                var getYear = numWithoutFixedText[..4];
                if (getYear != DateTime.Now.ToString("yyyy"))
                {
                    return $@"{fixedText}{DateTime.Now:yyyy}1";
                }
                var getNumber = numWithoutFixedText.Replace(DateTime.Now.ToString("yyyy"), "");
                var getCurrentCount = long.Parse(getNumber) + 1;
                return $@"{fixedText}{DateTime.Now:yyyy}{getCurrentCount}";
            }
        }

        /// <summary>Gets the latest requisition number.</summary>
        /// <returns></returns>
        private async Task<string> GetLatestRequisitionNumber()
        {
            var previous = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>($@"select ""RequisitionNumber"" from ""NewLabBookingHeader"" order by ""NewLabBookingHeaderId"" 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}";
            }
        }


        /// <summary>
        /// Calculates the age.
        /// </summary>
        /// <param name="Bday">The bday.</param>
        /// <param name="Cday">The cday.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentException">Birthday date must be earlier than current date</exception>
        private Age CalculateAge(DateTime Bday, DateTime Cday)
        {
            int Years;
            int Months;
            int Days;

            if ((Cday.Year - Bday.Year) > 0 ||
                (((Cday.Year - Bday.Year) == 0) && ((Bday.Month < Cday.Month) ||
                  ((Bday.Month == Cday.Month) && (Bday.Day <= Cday.Day)))))
            {
                int DaysInBdayMonth = DateTime.DaysInMonth(Bday.Year, Bday.Month);
                int DaysRemain = Cday.Day + (DaysInBdayMonth - Bday.Day);

                if (Cday.Month > Bday.Month)
                {
                    Years = Cday.Year - Bday.Year;
                    Months = Cday.Month - (Bday.Month + 1) + Math.Abs(DaysRemain / DaysInBdayMonth);
                    Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth;
                }
                else if (Cday.Month == Bday.Month)
                {
                    if (Cday.Day >= Bday.Day)
                    {
                        Years = Cday.Year - Bday.Year;
                        Months = 0;
                        Days = Cday.Day - Bday.Day;
                    }
                    else
                    {
                        Years = (Cday.Year - 1) - Bday.Year;
                        Months = 11;
                        Days = DateTime.DaysInMonth(Bday.Year, Bday.Month) - (Bday.Day - Cday.Day);
                    }
                }
                else
                {
                    Years = (Cday.Year - 1) - Bday.Year;
                    Months = Cday.Month + (11 - Bday.Month) + Math.Abs(DaysRemain / DaysInBdayMonth);
                    Days = (DaysRemain % DaysInBdayMonth + DaysInBdayMonth) % DaysInBdayMonth;
                }
            }
            else
            {
                throw new ArgumentException("Birthday date must be earlier than current date");
            }

            var x = new Age();
            x.Years = Years;
            x.Months = Months;
            x.Days = Days;
            return x;
        }

        /// <summary>
        /// Uploads the lab consent form asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <param name="locationId">The location identifier.</param>
        /// <returns></returns>
        public async Task<int> UploadLabConsentFormAsync(LabSampleHandlerModel model, int locationId)
        {
            var ConsentFormUploadedStatus = await this.unitOfWork.LabBookingStatus.FindAsync(x => x.Status == "ConsentFormUploaded" && x.Active);
            if (ConsentFormUploadedStatus == null)
            {
                return 0;
            }
            
            var LabSampleCollection = await this.unitOfWork.LabSampleCollections.FindAsync(d => d.LabSampleCollectionId == model.LabSampleCollectionId);
            if (LabSampleCollection == null)
            {
                return -1;
            }
            var transaction = this.unitOfWork.BeginTransaction();
            LabSampleCollection.ConsentFormUrl = model.ConsentFormUrl;
            LabSampleCollection.UploadedBy = model.UploadedBy;
            LabSampleCollection.UploadedDate = DateTime.Now;
            var response = await this.unitOfWork.LabSampleCollections.UpdateAsync(LabSampleCollection,transaction);
            if (response == 0)
            {
                transaction.Rollback();
                return -2;
            }
            var timeLine = new LabBookingTimeLine
            {
                Comment = $@"ConsentForm  uploaded for lab {model.TestName}",
                CommentedBy = (int)model.UploadedBy,
                CreatedDate = DateTime.Now,
                LabBookingStatusId = ConsentFormUploadedStatus.LabBookingStatusId,
                NewLabBookingHeaderId = model.NewLabBookingHeaderId,
                NewLabBookingDetailId = model.NewLabBookingDetailId
            };
            var timelineReposnse = await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeLine, transaction);
            if (timelineReposnse == 0)
            {
                transaction.Rollback();
                return -3;
            }

            var labLog = new LabLog
            {
                AccountId = model.UploadedBy,
                LabLogTypeId = (int)LabLogTypes.Lab_Sample_ConsentForm,
                LogFrom = (short)model.RoleId,
                LogDate = DateTime.UtcNow,
                LocationId = locationId,
                LogDescription = $@"{model.CreatedByName} has Uploaded <b>Consent Form</b> for <strong>{model.RequisitionNumber} - {model.TestName}</strong> successfully."
            };
            var labLogReposnse = await this.unitOfWork.LabLogs.InsertAsync(labLog, transaction);
            if (labLogReposnse == 0)
            {
                transaction.Rollback();
                return -3;
            }
            transaction.Commit();
            return response;
        }

        /// <summary>
        /// Fetches the labs without cancelled asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        public async Task<IEnumerable<LabSampleHandlerModel>> FetchLabsWithoutCancelledAsync(LabSampleHandlerModel model)
        {
            var where = "where 1=1";

            if (model.LocationId != null && model.LocationId > 0)
            {
                where += $@"  and nlbh.""LocationId""='{model.LocationId}'";
            }

            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and nlbh.""CreatedDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and nlbh.""CreatedDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.BookingType))
            {
                if (model.BookingType == "ip")
                {
                    where += $@" and nlbh.""AdmissionId"" is not null ";
                }
                else
                {
                    where += $@" and nlbh.""AdmissionId"" is null ";
                }

            }

            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" ilike '%{model.RequisitionNumber}%'";
            }

            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }

            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }

            if (model.PatientId != null && model.PatientId > 0)
            {
                where += $@" and  nlbd.""PatientId"" = {model.PatientId}";
            }

            if (model.IsInternalLab)
            {
                where += $@" and lmd.""IsInternalLab"" is true";
            }

            var query = $@"SELECT count(nlbh.*) over () as ""TotalItems"",nlbh.""NewLabBookingHeaderId"", nlbh.""RequisitionNumber"", nlbh.""Type"", nlbh.""PatientId"", nlbh.""DoctorId"", nlbh.""EmployeeId"",
                                       nlbh.""LocationId"", nlbh.""OverallTotalAmount"", nlbh.""OverallDiscount"", nlbh.""OverallNetAmount"", nlbh.""OverallDiscountPercentage"", nlbh.""PayTypeId"",
                                    nlbh.""PaymentNumber"", nlbh.""CreatedBy"", nlbh.""CreatedDate"", nlbh.""ModifiedBy"", nlbh.""ModifiedDate"", nlbh.""Active""  ,
                                    c.""FullName"" as ""CreatedByName"",m.""FullName"" as ""ModifiedByName"",COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",
                                    COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
                                    (CASE WHEN p.""ThumbnailUrl"" IS NOT NULL THEN CONCAT('Local/', p.""Guid"", '/', p.""ThumbnailUrl"") ELSE '' END) AS ""PatientThumbnailUrl"",
                                    e.""FullName"" as ""EmployeeName"",l.""Name"" as ""LocationName"",p.""UMRNo"",p.""Gender"",p.""Age"",CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType"",
                                    nlbd.""NewLabBookingDetailId"", nlbd.""LabMainDetailId"", nlbd.""ChargeCategoryId"", nlbd.""LabBookingStatusId"", nlbd.""DiscountPercentage"",
		                            nlbd.""DiscountAmount"", nlbd.""TotalAmount"", nlbd.""NetAmount"", lbs.""Status"",lbs.""RowColor"",
		                            lmd.""TestName"",lmd.""TestCode"", lmd.""IsExternalLab"", lmd.""IsInternalLab"" , ld.""DepartmentName"" ,cc.""ChargeCategoryName"" ,lst.""TypeName"",
		                            lmd.""SampleUsage"",lmd.""ConsentFormRequired"",nlbd.""Emergency"",
		                            lv.""LabVacutainerName"", CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType""
                                    FROM ""NewLabBookingHeader"" nlbh
                                   join ""NewLabBookingDetail"" nlbd on nlbd.""NewLabBookingHeaderId"" = nlbh.""NewLabBookingHeaderId""
                                   join ""Account"" c on c.""AccountId"" = nlbh.""CreatedBy""
                                   join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
                                   join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                           join ""LabMainDetail"" lmd ON lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                           join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
		                           join ""ChargeCategory"" cc on cc.""ChargeCategoryId"" = nlbd.""ChargeCategoryId""
		                           left join ""LabSampleType"" lst on lst.""LabSampleTypeId"" = lmd.""LabSampleTypeId""
                                   left join ""LabVacutainer"" lv on lv.""LabVacutainerId"" = lmd.""LabVacutainerId""
	                               left join ""Account"" m on m.""AccountId"" = nlbh.""ModifiedBy""
	                               left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                               left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                               left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
                                   { where} and lbs.""Status"" <> 'Cancelled'

                                   order by nlbh.""CreatedDate"" desc";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query += $@" limit {model.PageSize} offset {model.PageIndex * model.PageSize}";
            }

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

        public async Task<int> OnReceiveSampleNewAsync(SampleReceiveNewUserModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var Labtransferdetails = new List<LabTransferDetail>();
            foreach (var lab in model.Labs)
            {
                var sample = new LabTransferDetail();
                sample.LabTransferDetailId = lab.LabTransferDetailId;
                sample.LabTransferHeaderId = lab.LabTransferHeaderId;
                sample.NewLabBookingDetailId = lab.NewLabBookingDetailId;
                sample.LabSampleCollectionDetailId = lab.LabSampleCollectionDetailId;
                sample.ReceivedBy = model.ReceivedBy;
                sample.ReceivedDate = DateTime.Now;
                Labtransferdetails.Add(sample);
            }
            var updateResponse = await this.unitOfWork.LabTransferDetails.BulkUpdateAsync(Labtransferdetails, transaction);
            if (!updateResponse)
            {
                transaction.Rollback();
                return -1;
            }
            var FindRemaainingTransferDetails = (await this.unitOfWork.LabTransferDetails.FindAllAsync(d => d.LabTransferHeaderId == model.Labs[0].LabTransferHeaderId && d.ReceivedBy == null)).ToList();
            if (FindRemaainingTransferDetails.Count == 0)
            {
                var findHeader = await this.unitOfWork.LabTransferHeaders.FindAsync(x => x.LabTransferHeaderId == model.Labs[0].LabTransferHeaderId);
                if (findHeader == null)
                {
                    transaction.Rollback();
                    return -1;
                }
                else
                {
                    findHeader.ReceivedBy = model.ReceivedBy;
                    findHeader.ReceivedDate = DateTime.Now;
                    var InsertResponse = await this.unitOfWork.LabTransferHeaders.UpdateAsync(findHeader, transaction);
                    if (InsertResponse == 0)
                    {
                        transaction.Rollback();
                        return -3;
                    }
                }
            }

            var findReceivedStatus = await this.unitOfWork.LabBookingStatus.FindAsync(b => b.Status == "SampleRecieved");
            if (findReceivedStatus == null)
            {
                transaction.Rollback();
                return -2;
            }

            var sampleId = new List<int>();

            foreach (var item in model.Labs)
            {
                var findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(d => d.LabSampleCollectionDetailId == item.LabSampleCollectionDetailId);
                if (findSub == null)
                {
                    transaction.Rollback();
                    return -1;
                }

                findSub.LabBookingStatusId = findReceivedStatus.LabBookingStatusId;
                var updateSub = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub, transaction);
                if (updateSub == 0)
                {
                    transaction.Rollback();
                    return -3;
                }

                var checkIf = sampleId.Find(i => i == findSub.LabSampleCollectionId);
                if (checkIf == 0)
                {
                    sampleId.Add(findSub.LabSampleCollectionId);
                }

                var getLabBookingDetail = await this.unitOfWork.NewLabBookingDetails.FindAsync(d => d.NewLabBookingDetailId == item.NewLabBookingDetailId);
                var getLabDetail = await this.unitOfWork.LabMainDetails.FindAsync(l => l.LabMainDetailId == getLabBookingDetail.LabMainDetailId);

                var timeline = new LabBookingTimeLine
                {
                    CommentedBy = (int)model.ReceivedBy,
                    Comment = $@"Received samples for lab {getLabDetail.TestName}-{findSub.SampleName}",
                    CreatedDate = DateTime.Now,
                    LabBookingStatusId = findReceivedStatus.LabBookingStatusId,
                    NewLabBookingHeaderId = getLabBookingDetail.NewLabBookingHeaderId,
                    NewLabBookingDetailId = getLabBookingDetail.NewLabBookingDetailId
                };
                await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline, transaction);

            }

            foreach (var sampleCollectionId in sampleId)
            {
                var query = $@"select count(*) from ""LabSampleCollectionDetail""  where   ""LabSampleCollectionId"" = {sampleCollectionId} and ""LabBookingStatusId"" != {findReceivedStatus.LabBookingStatusId}";
                var count = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<int>(query, transaction);
                if (count == 0)
                {
                    var updateQuery = $@"update ""NewLabBookingDetail"" set  ""LabBookingStatusId"" = {findReceivedStatus.LabBookingStatusId} where  ""NewLabBookingDetailId"" = (select ""NewLabBookingDetailId"" from ""LabSampleCollection"" where ""LabSampleCollectionId"" = {sampleCollectionId} )";
                    await this.unitOfWork.Current.ExecuteAsync(updateQuery, transaction);
                }
            }
            transaction.Commit();
            return model.Labs[0].LabTransferHeaderId;
        }

        public async Task<int> onDepartmentAcceptAsync(LabTransferModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var labTransferDetail = await this.unitOfWork.LabTransferDetails.FindAsync(b => b.LabSampleCollectionDetailId == model.LabSampleCollectionDetailId);
            if (labTransferDetail == null)
            {
                transaction.Rollback();
                return -2;
            }
            labTransferDetail.DepartmentReceivedBy = model.ReceivedBy;
            labTransferDetail.DepartmentReceivedDate = DateTime.Now;
            var updateSub1 = await this.unitOfWork.LabTransferDetails.UpdateAsync(labTransferDetail, transaction);
            if (updateSub1 == 0)
            {
                transaction.Rollback();
                return -3;
            }
            var DepartmentReceivedStatus = await this.unitOfWork.LabBookingStatus.FindAsync(b => b.Status == "DepartmentReceived");
            if (DepartmentReceivedStatus == null)
            {
                transaction.Rollback();
                return -2;
            }
            var findSub = await this.unitOfWork.LabSampleCollectionDetails.FindAsync(d => d.LabSampleCollectionDetailId == model.LabSampleCollectionDetailId);
            if (findSub == null)
            {
                transaction.Rollback();
                return -1;
            }

            findSub.LabBookingStatusId = DepartmentReceivedStatus.LabBookingStatusId;
            var updateSub = await this.unitOfWork.LabSampleCollectionDetails.UpdateAsync(findSub, transaction);
            if (updateSub == 0)
            {
                transaction.Rollback();
                return -3;
            }
            var timeline = new LabBookingTimeLine
            {
                CommentedBy = (int)model.ReceivedBy,
                Comment = $@"Department Received sample for lab {model.TestName}-{findSub.SampleName}",
                CreatedDate = DateTime.Now,
                LabBookingStatusId = DepartmentReceivedStatus.LabBookingStatusId,
                NewLabBookingHeaderId = (int)model.NewLabBookingHeaderId,
                NewLabBookingDetailId = model.NewLabBookingDetailId
            };
            await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline, transaction);
            transaction.Commit();
            return 1;
        }

        /// <summary>
        /// Transfers the collected external sample asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        public async Task<int> TransferCollectedExternalSampleAsync(ExternalLabTransferUserModel model)
        {
            var getStatus = await this.unitOfWork.LabBookingStatus.FindAsync(s => s.Status == "SampleTransfered");
            if (getStatus == null)
            {
                return -1;
            }
            var Agency = await this.unitOfWork.ExternalLabAgency.FindAsync(l => l.ExternalLabAgencyId == model.ExternalLabAgencyId);
            if (Agency == null)
            {
                return -2;
            }
            
            var ExternalTransferNumber = await this.GetLatestExternalTransferNumberAsync();
            var transaction = this.unitOfWork.BeginTransaction();
            var labs = model.Labs;
           string newLabBookingDetailIds =  string.Join(",", model.Labs.Select(x => x.NewLabBookingDetailId));
           string labSampleCollectionDetailIds =  string.Join(",", model.Labs.Select(x => x.LabSampleCollectionDetailId));
            foreach (var lab in model.Labs)
            {
                var ExternalLabTransfer = new ExternalLabTransfer
                {
                    TransferredBy = model.TransferedBy,
                    TransferredDate = DateTime.Now,
                    Comments = model.Comments,
                    ExternalLabAgencyId = model.ExternalLabAgencyId,
                    NewLabBookingDetailId = lab.NewLabBookingDetailId,
                    LabSampleCollectionDetailId = (int)lab.LabSampleCollectionDetailId,
                    TransferNumber = ExternalTransferNumber,
                    FromLocationId = model.LocationId,
                    Active =true
                };
                ExternalLabTransfer.ExternalLabTransferId = await this.unitOfWork.ExternalLabTransfer.InsertAsync(ExternalLabTransfer, transaction);
                if (ExternalLabTransfer.ExternalLabTransferId == 0)
                {
                    transaction.Rollback();
                    return -3;
                }
                if (lab.NewLabBookingHeaderId != null && !string.IsNullOrEmpty(lab.TestName))
                {
                    var timeline = new LabBookingTimeLine
                    {
                        CommentedBy = model.TransferedBy,
                        Comment = $@"{lab.TestName} sample has been Transferred",
                        CreatedDate = DateTime.Now,
                        LabBookingStatusId = getStatus.LabBookingStatusId,
                        NewLabBookingHeaderId = (int)lab.NewLabBookingHeaderId,
                        NewLabBookingDetailId = lab.NewLabBookingDetailId
                    };
                    await this.unitOfWork.LabBookingTimeLines.InsertAsync(timeline, transaction);
                }

            }
            var SampleCollectionupdateQuery = $@"update ""LabSampleCollectionDetail"" set  ""LabBookingStatusId"" = {getStatus.LabBookingStatusId} where  ""LabSampleCollectionDetailId"" in ({labSampleCollectionDetailIds} )";
            var SampleCollectionresponse = await this.unitOfWork.Current.ExecuteAsync(SampleCollectionupdateQuery, transaction);
            if (model.Labs.Count != SampleCollectionresponse)
            {
                transaction.Rollback();
                return -4;
            }
            var updateQuery = $@"update ""NewLabBookingDetail"" set  ""LabBookingStatusId"" = {getStatus.LabBookingStatusId} where  ""NewLabBookingDetailId"" in ({newLabBookingDetailIds} )";
            var response = await this.unitOfWork.Current.ExecuteAsync(updateQuery, transaction);
            if (model.Labs.Count != response)
            {
                transaction.Rollback();
                return -5;
            }
            transaction.Commit();
            
            return response;
        }


        /// <summary>
        /// Fetches the external transfered labs asynchronous.
        /// </summary>
        /// <param name="model">The model.</param>
        /// <returns></returns>
        public async Task<IEnumerable<FetchExternalLabTransferUserModel>> FetchExternalTransferedLabsAsync(FetchExternalLabTransferUserModel model)
        {
            var where = "where 1=1";

            if (model.ExternalLabTransferId != null)
            {
                where += $@" and nlbd .""LabBookingStatusId"" = {model.LabBookingStatusId}";
            }
            if (!string.IsNullOrEmpty(model.RequisitionNumber))
            {
                where += $@" and nlbh.""RequisitionNumber"" ilike '%{model.RequisitionNumber}%'";
            }

            if (!string.IsNullOrEmpty(model.TransferNumber))
            {
                where += $@" and lower(elt.""TransferNumber"") ilike '%{model.TransferNumber.Trim().ToLower()}%'";
            }

            if (!string.IsNullOrEmpty(model.DepartmentName))
            {
                where += $@" and (lower(ld.""DepartmentName"") ilike '%{model.DepartmentName.ToLower()}%')";
            }

            if (!string.IsNullOrEmpty(model.TestName))
            {
                where += $@" and (lower(lmd.""TestName"") ilike '%{model.TestName.ToLower()}%' or lower(lmd.""TestCode"") ilike '%{model.TestName.ToLower()}%')";
            }
            if (!string.IsNullOrEmpty(model.FromDate))
            {
                where += $@" and elt.""TransferredDate""::date >= '{Convert.ToDateTime(model.FromDate):yyyy-MM-dd}'::date";
            }

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" and elt.""TransferredDate""::date <= '{Convert.ToDateTime(model.ToDate):yyyy-MM-dd}'::date";
            }

            if (model.FromLocationId > 0)
            {
                where += $@" and elt.""FromLocationId"" = {model.FromLocationId} ";
            }

            if (model.NewLabBookingDetailId != null)
            {
                where += $@" and nlbd.""NewLabBookingDetailId"" = {model.NewLabBookingDetailId}";
            }

            if (model.Status != null)
            {
                if (model.Status == "SampleTransfered")
                {
                    where += $@" and 2=2 ";
                }
                else if (model.Status == "SampleReceivePage")
                {
                    where += $@" and (lbsd.""Status"" = 'SampleRecieved' or lbsd.""Status"" = 'SampleRejected' or lbsd.""Status"" = 'DepartmentReceived') and lts.""ReceivedBy"" is not null ";
                }
                else if (model.Status == "DataEntryPage")
                {
                    where += $@" and (lbsd.""Status"" = 'ParameterAdded' or lbsd.""Status"" = 'SampleVerified')
                                 and lbs.""Status"" <> 'TechnicianVerified' and lbs.""Status"" <> 'Verified' and lbs.""Status"" <> 'RemovedDoctor' and lbs.""Status"" <> 'DoctorAssigned' 
                                 and lbs.""Status"" <> 'UnHold' and lbs.""Status"" <> 'Hold' and  lbs.""Status"" <> 'DoctorVerified' ";
                }
                else
                {
                    where += $@" and (lbsd.""Status"" = 'SampleRecieved' or lbsd.""Status"" = 'SampleVerified' or lbsd.""Status"" = 'SampleRejected') and lth.""ReceivedBy"" is not null ";
                }

            }

            if (model.LabBookingStatusId != null)
            {
                where += $@" and nlbd .""LabBookingStatusId"" = {model.LabBookingStatusId}";
            }

            if (model.PatientId > 0)
            {
                where += $@" and nlbh.""PatientId"" = {model.PatientId}";
            }

            if (!string.IsNullOrEmpty(model.BookingType))
            {
                if (model.BookingType == "ip")
                {
                    where += $@" and nlbh.""AdmissionId"" is not null ";
                }
                else
                {
                    where += $@" and nlbh.""AdmissionId"" is null ";
                }
            }

            var query2 = $@"SELECT count(elt.*) over() as ""TotalItems"",elt.""TransferNumber"",elt.""TransferredBy"",elt.""TransferredDate"",elt.""FromLocationId"",
			                            tb.""FullName"" as ""TransferByName"", lmd.""TestName"" ,lmd.""TestCode"", lmd.""SampleUsage"", lbs.""Status"" ,
			                            COALESCE (CONCAT(p.""Salutation"",' ',p.""FullName"") ,CONCAT(p.""Salutation"",' ',nlbh.""PatientName"") ) as ""PatientName"",nlbh.""RequisitionNumber"" ,
			                            COALESCE (p.""Mobile"" ,nlbh.""Mobile"" ) as ""Mobile"", COALESCE (nlbh.""DoctorName"" , prv.""FullName"" ) as ""DoctorName"",
			                            e.""FullName"" as ""EmployeeName"",l.""Name"" as ""FromLocation"",p.""UMRNo"",p.""Gender"",p.""Age"",
			                            lsc.""SampleCollectedBy"" ,lsc.""CollectionDate"" ,lsc.""IsBarcodeGenerated"" ,lbs.""RowColor"",nlbh.""PaymentType"",
			                            lsc.""BarcodeGeneratedBy"" , lsc.""BarcodeDate"" , sc.""FullName""  as ""SampleCollectedByName"", ld.""DepartmentName"",
			                            bc.""FullName"" as ""BarcodeGeneratedByName"",nlbh.""CreatedDate"" as ""BookedDate"",nlbh.""PatientId"",
                                        nlbd.""NewLabBookingDetailId"",nlbh.""NewLabBookingHeaderId"",p.""DateOfBirth"",COALESCE (nlbd.""Comment"",lscd.""Comment"") as ""Comment"",lscl.""Name"" as ""SampleCollectionLocation"",nlbd.""Emergency"",
                                        nlbd.""TechnicianComment"" ,nlbd.""TechnicianVerificationDate"" , tec.""FullName"" as ""TechnicianName"", CASE WHEN nlbh.""AdmissionId"" is not null THEN 'IP' else 'OP' END ""BookingType"",nlbd.""Emergency""
                                        ,lscd.""LabSampleCollectionDetailId"", lscd.""SubSampleCollectedBy"", lscd.""SubCollectionDate"",
                                    lscd.""SubIsBarcodeGenerated"", lscd.""SubBarcodeGeneratedBy"", lscd.""SubBarcodeDate"", lscd.""LocationId"", lscd.""SampleName"",
                                    subC.""FullName"" as ""SubSampleCollectedByName"", subB.""FullName"" as ""SubBarcodeGeneratedByName"", subL.""Name"" as ""SubSampleCollectionLocation"",
                                    LMD.""NoOfSamplesCollect"" ,LMD.""NoOfSamplesCollectText"" , lbsd.""Status"" as ""SubStatus""
                                         FROM ""ExternalLabTransfer"" elt
		                              join ""Location"" lt on lt.""LocationId"" = elt.""FromLocationId""
		                              join ""Account"" tb on tb.""AccountId"" = elt.""TransferredBy""
		                              join ""NewLabBookingDetail"" nlbd ON nlbd.""NewLabBookingDetailId"" = elt.""NewLabBookingDetailId""
		                              join ""LabMainDetail"" lmd on lmd.""LabMainDetailId"" = nlbd.""LabMainDetailId""
		                              join ""LabDepartment"" ld on ld.""LabDepartmentId"" = lmd.""LabDepartmentId""
		                              join ""NewLabBookingHeader"" nlbh on nlbh.""NewLabBookingHeaderId"" = nlbd.""NewLabBookingHeaderId""
		                              join ""Location"" l ON l.""LocationId"" = nlbh.""LocationId""
		                              join ""LabBookingStatus"" lbs ON lbs.""LabBookingStatusId"" = nlbd .""LabBookingStatusId""
		                              left join ""Patient"" p ON p.""PatientId"" =nlbh.""PatientId""
	                                  left join ""Provider"" prv on prv.""ProviderId"" = nlbh.""DoctorId""
	                                  left join ""Account"" e on e.""AccountId"" = nlbh.""EmployeeId""
	                                  left join ""LabSampleCollection"" lsc on lsc.""NewLabBookingDetailId"" = nlbd.""NewLabBookingDetailId""
	                                  left join ""Location"" lscl on lscl.""LocationId"" = lsc.""LocationId""
	                                  left join ""Account"" sc on sc.""AccountId"" = lsc.""SampleCollectedBy""
	                                  left join ""Account"" bc on bc.""AccountId"" = lsc.""BarcodeGeneratedBy""
	                                  left join ""Account"" tec on tec.""AccountId"" = nlbd.""TechnicianId""
	                                  left join ""LabSampleCollectionDetail"" lscd on  lscd.""LabSampleCollectionDetailId"" = elt.""LabSampleCollectionDetailId""
	                                   LEFT join ""LabBookingStatus"" lbsd ON lbsd.""LabBookingStatusId"" = lscd.""LabBookingStatusId""
	                                   left join ""Account"" subC on subC.""AccountId"" = lscd.""SubSampleCollectedBy""
	                                   left join ""Account"" subB ON subB.""AccountId"" = lscd.""SubBarcodeGeneratedBy""
	                                   left join ""Location"" subL on subL.""LocationId"" = lscd.""LocationId""
                                        {where}
			                            order by elt.""TransferredDate"" desc ";

            if (model.PageIndex != null && model.PageSize != null)
            {
                model.PageIndex = model.PageIndex > 0 ? model.PageIndex - 1 : model.PageIndex;
                query2 += $@" limit {model.PageSize} offset {model.PageSize * model.PageIndex}";
            }

            return await this.unitOfWork.Current.QueryAsync<FetchExternalLabTransferUserModel>(query2);
        }
    }

    

    /// <summary>
    /// The age
    /// </summary>
    public class Age
    {
        /// <summary>
        /// Gets or sets the years.
        /// </summary>
        /// <value>
        /// The years.
        /// </value>
        public int Years { get; set; }

        /// <summary>
        /// Gets or sets the months.
        /// </summary>
        /// <value>
        /// The months.
        /// </value>
        public int Months { get; set; }

        /// <summary>
        /// Gets or sets the days.
        /// </summary>
        /// <value>
        /// The days.
        /// </value>
        public int Days { get; set; }
    }
}