namespace Hims.Infrastructure.Services
{
    using System;
    using System.Collections.Generic;
    using System.Threading.Tasks;
    using System.Linq;
    using Dapper;
    using Domain.Entities;
    using Domain.Repositories.UnitOfWork;
    using Domain.Services;
    using Domain.Configurations;
    using Hims.Shared.DataFilters;
    using Shared.EntityModels;
    using Shared.UserModels.Laboratory;

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

        /// <inheritdoc cref="ILaboratoryPackageService" />
        public LaboratoryPackageServices(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        /// <inheritdoc/>
        public async Task<int> ModifyLabPackage(AddBooking model)
        {
            using (var transaction = this.unitOfWork.BeginTransaction())
            {
                var labPackage = new LabPackage
                {
                    Active = true,
                    Amount = model.Amount,
                    CreatedBy = model.CreatedBy,
                    Name = model.Name.Trim(),
                    CreatedDate = DateTime.Now
                };

                var existingLabPackage = await this.unitOfWork.LabPackages.FindAsync(l => l.LabPackageId == model.LabPackageId);

                var duplicateNameQuery = $@"Select * from  ""LabPackage"" where lower(""Name"") = '{labPackage.Name.ToLower()}' limit 1";
                var duplicateNameResponse = (await this.unitOfWork.Current.QueryAsync<LabPackage>(duplicateNameQuery)).ToList();

                if (existingLabPackage != null)
                {
                    if (duplicateNameResponse.Count > 0 && (duplicateNameResponse[0].LabPackageId != existingLabPackage.LabPackageId))
                    {
                        transaction.Rollback();
                        return -10;
                    }
                    existingLabPackage.Name = labPackage.Name;
                    existingLabPackage.Amount = labPackage.Amount;
                    existingLabPackage.ModifiedBy = labPackage.CreatedBy;
                    //  existingLabPackage.ModifiedBy = model.AccountId;
                    // existingLabPackage.ModifiedDate = DateTime.Now;
                    existingLabPackage.ModifiedDate = labPackage.CreatedDate;
                    labPackage.LabPackageId = existingLabPackage.LabPackageId;
                    var labPackageUpdateResponse = await this.unitOfWork.LabPackages.UpdateAsync(existingLabPackage, transaction);
                    if (labPackageUpdateResponse <= 0)
                    {
                        transaction.Rollback();
                        return -1;
                    }
                    //fetch exisitng location for this package 
                    var exisitingLocation = await this.unitOfWork.LocationLabPackageMap.FindAsync(
                        m => (m.LabPackageId == existingLabPackage.LabPackageId && m.LocationId == model.LocationId));
                    exisitingLocation.ModifiedBy = model.CreatedBy;
                    exisitingLocation.ModifiedDate = DateTime.Now;
                    exisitingLocation.Amount = (decimal)labPackage.Amount;

                    var labPackageMapUpdateResponse = await this.unitOfWork.LocationLabPackageMap.UpdateAsync(exisitingLocation, transaction);
                    if (labPackageMapUpdateResponse <= 0)
                    {
                        transaction.Rollback();
                        return -1;
                    }
                }
                else
                {
                    if (duplicateNameResponse.Count > 0)
                    {
                        transaction.Rollback();
                        return -10;
                    }
                    labPackage.LabPackageId = await this.unitOfWork.LabPackages.InsertAsync(labPackage, transaction);
                    if (labPackage.LabPackageId == 0)
                    {
                        transaction.Rollback();
                        return -2;
                    }
                    //Insert into Location Map
                    var locationMap = new LocationLabPackageMap
                    {
                        LocationId = model.LocationId,
                        LabPackageId = labPackage.LabPackageId,
                        IsActive = true,
                        Amount = (decimal)labPackage.Amount,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now
                    };
                    locationMap.LocationLabPackageMapId = await this.unitOfWork.LocationLabPackageMap.InsertAsync(locationMap, transaction);
                    if (locationMap.LocationLabPackageMapId <= 0)
                    {
                        transaction.Rollback();
                        return -2;
                    }

                }
                /////////////////////////////////////////////////////
                var labPackages = new List<LabPackageDetail>();
                model.Labs.ForEach((item) =>
                {
                    var detail = new LabPackageDetail
                    {
                        LabPackageId = labPackage.LabPackageId,
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        //LabHeaderId = item.LabHeaderId,
                        //LabPackageDetailId = item.LabPackageDetailId
                    };
                    labPackages.Add(detail);
                });

                if (existingLabPackage == null)
                {
                    var packageDetailResponse = await this.unitOfWork.LabPackageDetails.BulkInsertAsync(labPackages, transaction);
                    if (packageDetailResponse <= 0)
                    {
                        transaction.Rollback();
                        return -3;
                    }
                    transaction.Commit();
                    return labPackage.LabPackageId;
                }

                var existingLabDetails = (await this.unitOfWork.LabPackageDetails.FindAllAsync(m => m.LabPackageId == labPackage.LabPackageId)).ToList();

                if (existingLabDetails.Count > 0)
                {
                    var missingRecords = (existingLabDetails.Where(item => labPackages.All(inputList => inputList.LabPackageDetailId != item.LabPackageDetailId))).ToList();
                    if (missingRecords.Count > 0)
                    {
                        var ids = string.Join(",", missingRecords.Select(m => m.LabPackageDetailId));
                        var deleteQuery = $@"Delete from ""LabPackageDetail"" where ""LabPackageDetailId"" in ({ids})";
                        var deleteResponse = await this.unitOfWork.Current.ExecuteAsync(deleteQuery, transaction);
                        if (deleteResponse <= 0)
                        {
                            transaction.Rollback();
                            return -4;
                        }
                    }
                }

                var newRecord = labPackages.Where(p => p.LabPackageDetailId == 0).ToList();
                if (newRecord.Count > 0)
                {
                    var newRecordResponse = await this.unitOfWork.LabPackageDetails.BulkInsertAsync(newRecord, transaction);
                    if (newRecordResponse <= 0)
                    {
                        transaction.Rollback();
                        return -5;
                    }
                }

                transaction.Commit();
                return labPackage.LabPackageId;
            }
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabPackageModel>> FetchAllLabPackages(LabPackageModel model)
        {
            var where = "where 1=1";
            if (!string.IsNullOrEmpty(model.Name))
            {
                where += $@" and LP.""Name"" ilike '%{model.Name}%'";
            }

            if (model.AccountId != null)
            {
                where += $@" AND C.""AccountId"" = '{model.AccountId}'";
            }
            if (model.LocationId > 0)
            {
                where += $@" AND LPM.""LocationId"" = '{model.LocationId}'";
            }

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

            if (!string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND LP.""CreatedDate"" ::DATE <= '{model.ToDate}'::DATE";
            }
            var query = $@"SELECT count(LP.*) over() as ""TotalItems"",LP.""LabPackageId"", LP.""Name"", LPM.""Amount"", LP.""CreatedBy"", LP.""CreatedDate"", LP.""ModifiedBy"", LP.""ModifiedDate"",LP.""Active"",
		                    (Select count(*) from ""LabPackageDetail"" where ""LabPackageId""= LP.""LabPackageId"") as ""NoOfLabs"",C.""FullName"" as ""CreatedByName"",
		                    CR.""RoleName"" as ""CreatedByRole"",M.""FullName"" as ""ModifiedByName"",MR.""RoleName"" as ""ModifiedByRole""
	                    FROM ""LabPackage"" LP	
	                    join ""Account"" C on C.""AccountId"" = LP.""CreatedBy""
	                    join ""Role"" CR on CR.""RoleId"" = C.""RoleId""
	                    left join ""Account"" M on M.""AccountId"" = LP.""ModifiedBy""
	                    left join ""Role"" MR on MR.""RoleId"" = M.""RoleId"" 
                        join ""LocationLabPackageMap"" LPM on LPM.""LabPackageId"" = LP.""LabPackageId"" 
                        {where}
                        order by LP.""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<LabPackageModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabPackageDetailModel>> FetchLabPackageDetails(int labPackageId)
        {
            var query = $@"SELECT LPD.""LabPackageDetailId"", LPD.""LabPackageId"", LPD.""LabHeaderId"", LPD.""CreatedBy"", LPD.""CreatedDate"",
		                            LH.""LabName"", LH.""LabCode"", C.""FullName"" as ""CreatedByName"",
                                    LH.""InPatientCharge"", LH.""Signature"", LHM.""Charge"",LH.""Active"", LH.""CreatedBy"", LH.""CreatedDate"", LH.""ModifiedBy"", LH.""ModifiedDate""
                                FROM ""LabPackageDetail"" LPD
	                            join ""LabHeader"" LH on LH.""LabHeaderId"" = LPD.""LabHeaderId""
                                join ""LocationLabHeaderMap"" LHM on LHM.""LabHeaderId"" = LH.""LabHeaderId"" 

                                join ""Account"" C on C.""AccountId"" =  LPD.""CreatedBy""
	                            where LPD.""LabPackageId"" = {labPackageId} order by LPD.""CreatedDate"" desc";
            return await this.unitOfWork.Current.QueryAsync<LabPackageDetailModel>(query);
        }

        /// <inheritdoc/>
        public async Task<int> DeleteLabPackageAsync(int labPackageId, int? locationId)
        {
            using (var transaction = this.unitOfWork.BeginTransaction())
            {

                var existingLabDetails = (await this.unitOfWork.LocationLabPackageMap.FindAllAsync(m => m.LabPackageId == labPackageId)).ToList();
                //If lab Package is mapped to multiple locations delete only the mapping data
                if (existingLabDetails.Count > 1)
                {
                    var deleteLocPackage = $@"Delete from ""LocationLabPackageMap"" where ""LabPackageId"" = {labPackageId} AND ""LocationId"" ={locationId}";
                    var deleteLocPackageResponse = await this.unitOfWork.Current.ExecuteAsync(deleteLocPackage, transaction);
                    if (deleteLocPackageResponse <= 0)
                    {
                        transaction.Rollback();
                        return -1;
                    }
                    else
                    {
                        transaction.Commit();
                        return deleteLocPackageResponse;
                    }
                }

                var deleteLocPackageM = $@"Delete from ""LocationLabPackageMap"" where ""LabPackageId"" = {labPackageId} AND ""LocationId"" ={locationId}";
                var deleteLocPackageResponseM = await this.unitOfWork.Current.ExecuteAsync(deleteLocPackageM, transaction);
                if (deleteLocPackageResponseM <= 0)
                {
                    transaction.Rollback();
                    return -3;
                }

                var deletePackageDetailQuery = $@"Delete from ""LabPackageDetail"" where ""LabPackageId"" = {labPackageId}";
                var deletePackageDetailResponse = await this.unitOfWork.Current.ExecuteAsync(deletePackageDetailQuery, transaction);
                if (deletePackageDetailResponse <= 0)
                {
                    transaction.Rollback();
                    return -1;
                }
                var deletePackageQuery = $@"Delete from ""LabPackage"" where ""LabPackageId"" = {labPackageId}";
                var deletePackageResponse = await this.unitOfWork.Current.ExecuteAsync(deletePackageQuery, transaction);
                if (deletePackageResponse <= 0)
                {
                    transaction.Rollback();
                    return -2;
                }
                transaction.Commit();
                return deletePackageResponse;
            }
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<LabBookingDetailModel>> FetchLabBookingPackageAsync(int labBookingHeaderId, int? labBookingDetailId)
        {
            var where = $@"where LBH.""LabBookingHeaderId"" = {labBookingHeaderId}";
            if (labBookingDetailId != null)
            {
                where += $@" and LBH.""LabBookingDetailId"" = {labBookingDetailId}";
            }
            var query = $@"SELECT LBH.""LabBookingDetailId"", LBH.""LabBookingHeaderId"",
                                    LP.""Name"" as ""PackageName"",LBH.""LabHeaderId"",LBH.""LabPackageId"", LBH.""Status"",LBH.""DiscountPercentage""
                                    ,LBH.""DiscountAmount"",LBH.""Amount"",LBH.""NetAmount"",LBH.""IsReportGenerated"",LBH.""ReportDate"",
                                    LBH.""IsSampleCollected"",LBH.""SampleDate"",
									Typed.""FullName"" as ""TypedByName"", Verified.""FullName"" as ""VerifiedByName"",Doctor.""FullName"" as ""VerifiedByDoctorName"",
                                    LBH.""Barcode"",LBH.""BarcodeGeneratedBy"",BR.""FullName"" as ""BarcodeGeneratedName"",LBH.""BarcodeGeneratedDate""
	                                FROM ""LabBookingDetail"" LBH
									join ""LabPackage"" LP on LP.""LabPackageId"" = LBH.""LabPackageId""
									left join ""Account"" Typed on Typed.""AccountId"" = LBH.""TypedBy""
									left join ""Account"" Verified on Verified.""AccountId"" = LBH.""VerifiedBy""
									left join ""Provider"" Doctor on Doctor.""ProviderId"" = LBH.""VerifiedByDoctorId"" 
                                    left Join ""Account"" Br on Br.""AccountId"" = LBH.""BarcodeGeneratedBy""

                                    {where}  order by LBH.""LabBookingDetailId"" desc";
            return await this.unitOfWork.Current.QueryAsync<LabBookingDetailModel>(query);
        }

        /// <inheritdoc/>
        public async Task<IEnumerable<BookingPackageLaboratoryModel>> FetchLabsInsidePackageBookingAsync(int labBookingDetailId, int? labBookingPackageDetailId)
        {
            var where = $@" where LBPD.""LabBookingDetailId"" = {labBookingDetailId}";
            if (labBookingPackageDetailId != null)
            {
                where += $@" and LBPD.""LabBookingPackageDetailId"" = {labBookingPackageDetailId}";
            }
            var query = $@"SELECT LH.""LabName"",LH.""LabCode"",LBPD.""LabBookingPackageDetailId"", LBPD.""LabBookingDetailId"", 
                                    LBPD.""LabHeaderId"", LBPD.""Status"", LBPD.""IsReportGenerated"", LBPD.""ReportDate"", 
                                    LBPD.""IsSampleCollected"", LBPD.""SampleDate"", LBPD.""TypedBy"", LBPD.""TypedDate"",
                                    Typed.""FullName"" as ""TypedByName"",LBPD.""VerifiedBy"", Verified.""FullName"" as ""VerifiedByName""
                                    ,LBPD.""Barcode"",LD.""DepartmentName"",AC.""FullName"" as ""SampleCollectedBy""
                                        ,AR.""FullName"" as ""CollectedSampleReceivedBy"",LBPD.""SampleReceivedDate"",
                                        Doctor.""FullName"" as ""VerifiedByDoctorName"",LBPD.""IsBarcode"",LBPD.""BarcodeGeneratedBy"",BR.""FullName"" as ""BarcodeGeneratedName"",LBPD.""BarcodeGeneratedDate""
                                        FROM ""LabBookingPackageDetail"" LBPD

	                                    inner join ""LabHeader"" LH on LH.""LabHeaderId"" = LBPD.""LabHeaderId""

	                                    left join ""Account"" Typed on Typed.""AccountId"" = LBPD.""TypedBy""
	                                    left join ""Account"" Verified on Verified.""AccountId"" = LBPD.""VerifiedBy""
                                        join ""LabDepartment"" LD on LH.""LabDepartmentId""=LD.""LabDepartmentId""
                                        left join ""Account"" AC on AC.""AccountId""=LBPD.""SampleCollectedBy""
                                        left join ""Account"" AR on AR.""AccountId""=LBPD.""CollectedSampleReceivedBy""
                                        left Join ""Account"" Br on Br.""AccountId"" = LBPD.""BarcodeGeneratedBy""
										left join ""Provider"" Doctor on Doctor.""ProviderId"" = LBPD.""VerifiedByDoctorId""
                                        {where}  order by LBPD.""LabBookingPackageDetailId"" desc";
            return await this.unitOfWork.Current.QueryAsync<BookingPackageLaboratoryModel>(query);
        }

        ///// <inheritdoc/>
        //public async Task<int> UpdateLabBookingStatusForSample(RequestLaboratory model)
        //{
        //    var where = "where 1=1";

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

        //    var query = $@"Update ""LabBookingDetail"" set ""Status"" = '{model.Status}',""IsSampleCollected"" = true,  ""SampleCollectedBy""={model.AccountId},
        //                        ""SampleDate"" = '{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}' {where}";

        //    await this.UpdateLabBookingPackageStatusForSample(model);

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



        /// <inheritdoc/>
        public async Task<IEnumerable<LabReportParamModel>> FetchLabResultReportParameterPackageAsync(int labBookingDetailId, int labBookingPackageDetailId)
        {
            var query = $@"SELECT distinct LD.""LabDetailId"", LD.""LabHeaderId"", LD.""TestParameter"", LD.""ReferenceRange"", LD.""RefrenceRangeUnit"",
                                LV.""Name"" as ""RefrenceRangeUnitName"",
                                LPP.""LabPatientParameterId"", LPP.""LabDetailId"", LPP.""TestParamResult"",LPP.""LabBookingPackageDetailId"",
                                LBPD.""TypedBy"", LBPD.""TypedDate"", A.""FullName"" as ""TypedByName"", LBPD.""VerifiedBy"",
								V.""FullName"" as ""VerifiedByName""
	                                FROM ""LabDetail"" LD
	                                left join ""LookupValue"" LV on LV.""LookupValueId"" = LD.""RefrenceRangeUnit""
	                                join ""LabPatientParameter"" LPP on LPP.""LabDetailId"" = LD.""LabDetailId""
	                                join ""LabBookingPackageDetail"" LBPD on LBPD.""LabBookingPackageDetailId"" = LPP.""LabBookingPackageDetailId""
									join ""Account"" A on A.""AccountId"" = LBPD.""TypedBy""
									left join ""Account"" V on V.""AccountId"" = LBPD.""VerifiedBy""
	                                where LPP.""LabBookingDetailId"" = {labBookingDetailId} and LPP.""LabBookingPackageDetailId"" = {labBookingPackageDetailId}";
            return await this.unitOfWork.Current.QueryAsync<LabReportParamModel>(query);
        }

        /// <inheritdoc/>
        public async Task<int> VerifyLabBookingPackageAsync(int verifiedBy, int? labBookingDetailId, int? labBookingPackageDetailId)
        {
            var where = " where 1=1";
            var flagPackage = false;
            if (labBookingDetailId != null && labBookingPackageDetailId == null)
            {
                where += $@" and ""LabBookingDetailId"" = {labBookingDetailId}";
                await this.UpdatePackageBookingDetail(verifiedBy, (int)labBookingDetailId);
            }
            else
            {
                where += $@" and ""LabBookingPackageDetailId"" = {labBookingPackageDetailId}";
                flagPackage = true;
            }

            var query = $@"UPDATE ""LabBookingPackageDetail"" SET ""Status""='Report Generated', ""IsReportGenerated""= true, 
                                ""ReportDate""='{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}', ""VerifiedBy""={verifiedBy} {where}";
            var response = await this.unitOfWork.Current.ExecuteAsync(query);
            if (flagPackage)
            {
                var (flag, labId) = await this.CheckStatusForReportUpdateAsync((int)labBookingPackageDetailId);
                if (flag)
                {
                    await this.UpdatePackageBookingDetail(verifiedBy, labId);
                }
            }
            return response;
        }

        /// <summary>
        /// The update package booking detail.
        /// </summary>
        /// <param name="verifiedBy">
        /// The verified by.
        /// </param>
        /// <param name="labBookingDetailId">
        /// The lab booking detail id.
        /// </param>
        /// <returns></returns>
        private async Task<bool> UpdatePackageBookingDetail(int verifiedBy, int labBookingDetailId)
        {
            var bookingDetail = await this.unitOfWork.LabBookingDetails.FindAsync(m => m.LabBookingDetailId == labBookingDetailId);
            if (bookingDetail == null)
            {
                return false;
            }
            bookingDetail.VerifiedBy = verifiedBy;
            //bookingDetail.Status = "Report Verified By Technician";(on vikas requirement);
            bookingDetail.Status = "Report Generated";
            bookingDetail.ReportDate = DateTime.UtcNow.AddMinutes(330);
            bookingDetail.IsReportGenerated = true;
            return await this.unitOfWork.LabBookingDetails.UpdateAsync(bookingDetail) > 0;
        }

        /// <summary>
        /// The check status for report update async.
        /// </summary>
        /// <param name="labBookingPackageDetailId">
        /// The lab booking package detail id.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        private async Task<Tuple<bool, int>> CheckStatusForReportUpdateAsync(int labBookingPackageDetailId)
        {
            var response = await this.unitOfWork.LabBookingPackageDetails.FindAsync(m => m.LabBookingPackageDetailId == labBookingPackageDetailId);
            if (response == null)
            {
                return Tuple.Create(false, 0);
            }
            var labBookingId = response.LabBookingDetailId;
            var fetchAllPackageLabs = (await this.unitOfWork.LabBookingPackageDetails.FindAllAsync(m => m.LabBookingDetailId == labBookingId)).ToList();
            if (fetchAllPackageLabs.Count > 0)
            {
                var isAnyRecordMissing = (fetchAllPackageLabs.Where(m => m.IsReportGenerated == null || m.IsReportGenerated == false)).ToList();
                if (isAnyRecordMissing.Count > 0)
                {
                    return Tuple.Create(false, 0);
                }
                else
                {
                    return Tuple.Create(true, labBookingId);
                }
            }
            return Tuple.Create(false, 0);
        }

        /// <summary>
        /// The check all status for update async.
        /// </summary>
        /// <param name="labBookingPackageDetailId">
        /// The model.
        /// </param>
        /// <returns>
        /// The <see cref="Task"/>
        /// </returns>
        //private async Task<bool,int> CheckAllStatusForPackedLabsAsync(int labBookingPackageDetailId)
        //{
        //    var response = await this.unitOfWork.LabBookingPackageDetails.FindAsync(m => m.LabBookingPackageDetailId == labBookingPackageDetailId);
        //    if (response == null)
        //    {
        //        return Tuple.Create(false, 0);
        //    }
        //    var labBookingId = response.LabBookingDetailId;
        //    var fetchAllPackageLabs = (await this.unitOfWork.LabBookingPackageDetails.FindAllAsync(m => m.LabBookingDetailId == labBookingId)).ToList();
        //    if (fetchAllPackageLabs.Count > 0)
        //    {
        //        var isAnyRecordMissing = (fetchAllPackageLabs.Where(m => m.IsSampleCollected == null || m.IsSampleCollected == false)).ToList();
        //        if (isAnyRecordMissing.Count > 0)
        //        {
        //            return Tuple.Create(false, 0);
        //        }
        //        else
        //        {
        //            return Tuple.Create(true, labBookingId);
        //        }
        //    }
        //    return Tuple.Create(false, 0);

        //}
        ///// <inheritdoc/>
        //private async Task<bool> UpdatePackedLabsBookingDetail(string status ,int accountId, int labBookingDetailId)

        //{
        //    //RequestLaboratory model)//int verifiedBy, int labBookingDetailId

        //        var bookingDetail = await this.unitOfWork.LabBookingDetails.FindAsync(m => m.LabBookingDetailId == labBookingDetailId);
        //        if (bookingDetail == null)
        //        {
        //            return false;
        //        }

        //    //var query = $@"Update """" set ""Status"" = '{model.Status}',""IsSampleCollected"" = true, ""SampleCollectedBy""={model.AccountId},
        //    //                    ""SampleDate"" = '{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}' {where}";
        //    //var response = await this.unitOfWork.Current.ExecuteAsync(query);

        //    bookingDetail.SampleCollectedBy = accountId;
        //        bookingDetail.Status = status;
        //        bookingDetail.SampleDate = DateTime.UtcNow.AddMinutes(330);
        //        bookingDetail.IsSampleCollected = true;
        //        return await this.unitOfWork.LabBookingDetails.UpdateAsync(bookingDetail) > 0;          
        //}

        /// <inheritdoc/>
        public async Task<int> UpdateSelectedLab(LabSample model)
        {
            var response = 0;
            var flagcheck = false;
            if (model.LabBookingDetailIds.Any())
            {
                var ids = string.Join(",", model.LabBookingDetailIds);
                var query = $@"UPDATE ""LabBookingDetail""  SET ""Status""='{model.Status}',""IsSampleCollected""= true,""SampleCollectedBy""={model.AccountId}, ""SampleDate"" = '{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}' WHERE ""LabBookingDetailId"" in  ({ids})";
                response = await this.unitOfWork.Current.ExecuteAsync(query);
            }
            if (model.labBookingPackageDetailIds.Any())
            {
                flagcheck = true;
                var ids = string.Join(",", model.labBookingPackageDetailIds);
                var query = $@"UPDATE ""LabBookingPackageDetail""  SET ""Status""='{model.Status}',""IsSampleCollected""= true,""SampleCollectedBy""={model.AccountId}, ""SampleDate"" = '{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}' WHERE ""LabBookingPackageDetailId"" in  ({ids})";
                response = await this.unitOfWork.Current.ExecuteAsync(query);
            }


            try
            {
                for (int i = 0; i <= model.labBookingPackageDetailIds.Count; i++)
                {
                    if (response > 0 && flagcheck)
                    {
                        var getAnPackageBooking = await this.unitOfWork.LabBookingPackageDetails.FindAsync(x => x.LabBookingPackageDetailId == model.labBookingPackageDetailIds[i]);
                        if (getAnPackageBooking != null)
                        {

                            var getAllTheLabsInPackage = (await this.unitOfWork.LabBookingPackageDetails.FindAllAsync(x => x.LabBookingDetailId == getAnPackageBooking.LabBookingDetailId)).ToList();
                            if (getAllTheLabsInPackage.Count > 0)
                            {
                                var checktoupdate = (getAllTheLabsInPackage.Where(c => c.SampleCollectedBy == (int?)null)).ToList();
                                if (checktoupdate.Count == 0)
                                {
                                    var query = $@"UPDATE ""LabBookingDetail""  SET ""Status""='{model.Status}', ""SampleCollectedBy""={model.AccountId}, ""SampleDate"" = '{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}' WHERE ""LabBookingDetailId"" = {getAnPackageBooking.LabBookingDetailId}";
                                    response = await this.unitOfWork.Current.ExecuteAsync(query);
                                }
                            }
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                // ignore
            }
            return response;
        }

        public async Task<IEnumerable<LabPackageModel>> FetchImportLabPackages(LabPackageModel model)
        {
            var where = "where 1=1";
            if (!string.IsNullOrEmpty(model.Name))
            {
                where += $@" and LP.""Name"" ilike '%{model.Name}%'";
            }

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

            var query = $@"SELECT count(LP.*) over() as ""TotalItems"",LP.""LabPackageId"", l.""Name"" as ""LocationName"",LP.""Name"", LPM.""Amount"", LP.""CreatedBy"", LP.""CreatedDate"", LP.""ModifiedBy"", LP.""ModifiedDate"",LP.""Active"",
		                    (Select count(*) from ""LabPackageDetail"" where ""LabPackageId""= LP.""LabPackageId"") as ""NoOfLabs""
		                    
	                    FROM ""LabPackage"" LP	
                        join ""LocationLabPackageMap"" LPM on LPM.""LabPackageId"" = LP.""LabPackageId"" 
						left join ""Location"" l on l.""LocationId"" = LPM.""LocationId""


                        { where} and LPM.""LabPackageId"" not in (select ""LabPackageId"" from ""LocationLabPackageMap"" where ""LocationId"" = {model.LocationId})
                        order by LP.""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<LabPackageModel>(query);

        }

        public async Task<int> ModifyImportPackage(PackageImportModel model)
        {
            try
            {
                using (var transaction = this.unitOfWork.BeginTransaction())
                {
                    foreach (var item in model.Packages)
                    {
                        var locationMap = new LocationLabPackageMap
                        {
                            LocationId = model.LocationId,
                            LabPackageId = (int)item.LabPackageId,
                            IsActive = true,
                            Amount = (decimal)item.Amount,
                            CreatedBy = model.CreatedBy,
                            CreatedDate = DateTime.Now
                        };

                        var response = await this.unitOfWork.LocationLabPackageMap.InsertAsync(locationMap, transaction);
                    }
                    transaction.Commit();
                    return 1;
                }
            }
            catch (Exception ex)
            {
                throw;

            }

            /// <inheritdoc/>
            //public async Task<int> UpdatePackageLabForBarcodeAsync(RequestLaboratory model)
            //{

            //    var query = $@"Update ""LabBookingPackageDetail"" set ""Barcode""='{model.Barcode}'
            //                        where ""LabBookingPackageDetailId"" = {model.LabBookingPackageDetailId}";
            //    var response = await this.unitOfWork.Current.ExecuteAsync(query);

            //    return response;
            //}

            /// <inheritdoc/>
            //public async Task<int> UpdateSampleReceivedStatus(int loginId ,int labBookingPackageDetailId)
            //{
            //    var query = $@"UPDATE ""LabBookingPackageDetail"" SET ""CollectedSampleReceivedBy""={loginId}, ""SampleReceivedDate"" = '{DateTime.UtcNow.AddMinutes(330).ToString("yyyy-MM-dd hh:mm tt")}' WHERE ""LabBookingPackageDetailId"" = {labBookingPackageDetailId}";
            //    return await this.unitOfWork.Current.ExecuteAsync(query);

            //}

        }
    }
}