using System;
using System.Collections.Generic;
using System.Linq;
using Dapper;
using Hims.Domain.Entities;
using Hims.Domain.Entities.Enums;

namespace Hims.Infrastructure.Services
{
    using System.Threading.Tasks;
    using Hims.Domain.Repositories.UnitOfWork;
    using Hims.Domain.Services;
    using Shared.UserModels.Package;
    using Product = Shared.UserModels.Package.Product;
    using Surgery = Shared.UserModels.Package.Surgery;
    using MetaData = Shared.UserModels.Package.MetaData;
    using General = Shared.UserModels.ChargeManagement;
    using Hims.Shared.UserModels.Laboratory;

    /// <summary> The chat service.</summary>
    public class PackageService : IPackageService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <inheritdoc cref="IChatService" />
        public PackageService(IUnitOfWork unitOfWork) => this.unitOfWork = unitOfWork;

        public async Task<MetaData.ViewModel> FetchMetaDataAsync(int packageId, int locationId)
        {
            try
            {


                var data = new MetaData.ViewModel();

                var query = $@"SELECT
	                        d.""DepartmentId"",
	                        d.""DepartmentName"",
	                        G.""ChargeGroupId"",
	                        G.""ChargeGroupName"",
	                        C.""ChargeId"",
	                        C.""ChargeName"",
	                        C.""Active"",
	                        C.""RepeatTypeId"",
	                        T.""RepeatTypeName"",
	                        C.""AutomaticTypeId"",
	                        A.""Name"" AS ""AutomaticTypeName"",
	                        C.""Cost"",
	                        C.""ChargeTypeId"",
	                        pc.""Unit""
                        FROM
	                        ""Package""
	                        P JOIN ""PackageCharge"" pc ON pc.""PackageId"" = P.""PackageId""
	                        JOIN ""Charge"" C ON C.""ChargeId"" = pc.""ChargeId""
	                        JOIN ""ChargeGroup"" G ON G.""ChargeGroupId"" = C.""ChargeGroupId""
	                        JOIN ""Department"" d ON d.""DepartmentId"" = G.""DepartmentId""
	                        LEFT JOIN ""RepeatType"" T ON T.""RepeatTypeId"" = C.""RepeatTypeId""
	                        LEFT JOIN ""AutomaticType"" A ON A.""AutomaticTypeId"" = C.""AutomaticTypeId""
                        WHERE
	                        P.""PackageId"" = {packageId}
                        ORDER BY
	                        d.""DepartmentName"",
	                        G.""ChargeGroupName"",
	                        C.""ChargeName""";
                data.Generals = await this.unitOfWork.Current.QueryAsync<General.ViewModel>(query);

                query = $@"SELECT P
	                        .""PharmacyProductId"" AS ""ProductId"",
	                        P.""ProductName"",
	                        P.""GenericName"",
	                        C.""Name"" AS ""CategoryName"",
	                        P.""Active"",
	                        M.""Name"" AS ""CompanyName"",
                            pc.""Unit"",
	                        costs.*
                        FROM
	                        ""Package"" k
	                        JOIN ""PackageCharge"" pc ON pc.""PackageId"" = k.""PackageId""
	                        JOIN ""PharmacyProduct"" p on p.""PharmacyProductId"" = pc.""ProductId""
	                        LEFT JOIN ""LookupValue"" C ON C.""LookupValueId"" = P.""CategoryId""
	                        LEFT JOIN ""Company"" M ON M.""CompanyId"" = P.""CompanyId""
	                        LEFT JOIN LATERAL (
	                        SELECT
		                        d.""Mrp"",
		                        MIN ( d.""Mrp"" ) OVER ( ) AS ""Min"",
		                        MAX ( d.""Mrp"" ) OVER ( ) AS ""Max""
	                        FROM
		                        ""PharmacyRetailStock"" d
	                        WHERE
		                        P.""PharmacyProductId"" = d.""PharmacyProductId"" AND (d.""QuantityIn"" - d.""QuantityOut"" > 0)
	                        LIMIT 1
	                        ) costs ON TRUE
	                        WHERE k.""PackageId"" = {packageId}";
                data.Products = await this.unitOfWork.Current.QueryAsync<Product.ViewModel>(query);

                query = $@"SELECT
	                        h.""SurgeryKitHeaderId"" AS ""SurgeryKitId"",
	                        h.""KitName"",
	                        P.""PharmacyProductId"" AS ""ProductId"",
	                        P.""ProductName"",
	                        P.""GenericName"",
	                        C.""Name"" AS ""CategoryName"",
	                        P.""Active"",
	                        M.""Name"" AS ""CompanyName"",
	                        d.""Quantity"" AS ""Unit"",
	                        costs.*
                        FROM
                            ""Package""
	                        k JOIN ""PackageCharge"" pc ON pc.""PackageId"" = k.""PackageId""
	                        JOIN ""SurgeryKitHeader"" h on h.""SurgeryKitHeaderId"" = pc.""SurgeryKitId""
	                        LEFT JOIN ""SurgeryKitDetail"" d ON d.""SurgeryKitHeaderId"" = h.""SurgeryKitHeaderId""
	                        LEFT JOIN ""PharmacyProduct"" P ON P.""PharmacyProductId"" = d.""PharmacyProductId""
	                        LEFT JOIN ""LookupValue"" C ON C.""LookupValueId"" = P.""CategoryId""
	                        LEFT JOIN ""Company"" M ON M.""CompanyId"" = P.""CompanyId""
	                        LEFT JOIN LATERAL (
	                        SELECT
		                        d.""Mrp"",
		                        MIN ( d.""Mrp"" ) OVER ( ) AS ""Min"",
		                        MAX ( d.""Mrp"" ) OVER ( ) AS ""Max""
	                        FROM
		                        ""PharmacyRetailStock"" d
	                        WHERE
		                        P.""PharmacyProductId"" = d.""PharmacyProductId"" AND (d.""QuantityIn"" - d.""QuantityOut"" > 0)
	                        LIMIT 1
	                        ) costs ON TRUE
	                        WHERE k.""PackageId"" = {packageId}";
                data.Surgeries = await this.unitOfWork.Current.QueryAsync<Surgery.ViewModel>(query);

                query = $@"SELECT lh.""LabHeaderId"",
	                        lh.""LabName"",
	                        lh.""LabCode"",
	                        lh.""Active"",
                            pc.""Unit"",
	                        LHM.""Charge"" ""Cost""
                        FROM
	                        ""Package"" k
	                        JOIN ""PackageCharge"" pc ON pc.""PackageId"" = k.""PackageId""
	                        JOIN ""LabHeader"" lh on lh.""LabHeaderId"" = pc.""LabHeaderId""
                            JOIN ""LocationLabHeaderMap"" LHM on LHM.""LabHeaderId"" = LH.""LabHeaderId""

                            WHERE k.""PackageId"" = {packageId} AND  LHM.""LocationId""={locationId} ";
                data.Labs = await this.unitOfWork.Current.QueryAsync<LabHeaderModel>(query);
                return data;
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public async Task<IEnumerable<ViewModel>> FetchAsync(FilterModel model)
        {
            var where = $@"WHERE 1 = 1 ";

            if (!string.IsNullOrEmpty(model.PackageName))
            {
                where += $@" AND p.""Name"" ilike '{model.PackageName}' ";
            }

            var locWhere = $@"AND 1 = 1 ";

            if (model.LocationId > 0)
            {
                locWhere += $@" AND LP.""LocationId"" ={model.LocationId} ";
            }

            var query = $@"SELECT
                            COUNT(p.""PackageId"") OVER() AS ""TotalItems"",
	                        p.""PackageId"",
	                        p.""Name"",
	                        p.""Amount"",
                            p.""Active"",
	                        general.""TotalGeneral"",
	                        medicines.""TotalMedicines"",
	                        labs.""TotalLabs"",
	                        kits.""TotalKits"",
                            string_agg(L.""Name"", ', ') as ""LocationNames"",string_agg(L.""LocationId""::text, ', ') as ""LocationIds""
                        FROM
	                        ""Package"" p

                       join ""LocationPackageMap"" LP ON LP.""PackageId"" = p.""PackageId""  {locWhere}
                    left join ""Location"" L ON L.""LocationId"" = LP.""LocationId""

                        LEFT JOIN LATERAL (
	                        SELECT COUNT(c.""PackageChargeId"") OVER() AS ""TotalGeneral"" FROM ""PackageCharge"" c
	                        WHERE p.""PackageId"" = c.""PackageId"" AND c.""ChargeId"" IS NOT NULL
	                        LIMIT 1
                        ) general ON true
                        LEFT JOIN LATERAL (
	                        SELECT COUNT(c.""PackageChargeId"") OVER() AS ""TotalMedicines"" FROM ""PackageCharge"" c
	                        WHERE p.""PackageId"" = c.""PackageId"" AND c.""ProductId"" IS NOT NULL
	                        LIMIT 1
                        ) medicines ON true
                        LEFT JOIN LATERAL (
	                        SELECT COUNT(c.""PackageChargeId"") OVER() AS ""TotalLabs"" FROM ""PackageCharge"" c
	                        WHERE p.""PackageId"" = c.""PackageId"" AND c.""LabHeaderId"" IS NOT NULL
	                        LIMIT 1
                        ) labs ON true
                        LEFT JOIN LATERAL (
	                        SELECT COUNT(c.""PackageChargeId"") OVER() AS ""TotalKits"" FROM ""PackageCharge"" c
	                        WHERE p.""PackageId"" = c.""PackageId"" AND c.""SurgeryKitId"" IS NOT NULL
	                        LIMIT 1
                        ) kits ON true {where}
                        group by p.""PackageId"", general.""TotalGeneral"", medicines.""TotalMedicines"",labs.""TotalLabs"", kits.""TotalKits"" ";

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);

            var records = await this.unitOfWork.Current.QueryAsync<ViewModel>(query);
            return records;
        }

        public async Task<int> InsertAsync(InsertModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            var query = $@"SELECT ""PackageId"" from ""Package"" WHERE UPPER(TRIM(""Name"")) = UPPER(TRIM('{model.Name}'))";
            var isExists = await this.unitOfWork.Current.QueryFirstOrDefaultAsync<int>(query, transaction);
            if (isExists > 0)
            {
                transaction.Rollback();
                return -2;
            }

            var package = new Package
            {
                CreatedBy = model.CreatedBy,
                Active = true,
                Amount = model.Amount,
                CreatedDate = DateTime.Now,
                Name = model.Name
            };
            var packageId = await this.unitOfWork.Package.InsertAsync(package, transaction);
            if (packageId <= 0)
            {
                transaction.Rollback();
                return -1;
            }

            var packageCharges = model.Records.Select(x => new PackageCharge
            {
                CreatedBy = model.CreatedBy,
                CreatedDate = DateTime.Now,
                PackageId = packageId,
                Active = true,
                ChargeId = x.ChargeId,
                ProductId = x.ProductId,
                Unit = x.Unit,
                ReducedAmount = x.ReducedAmount,
                SurgeryKitId = x.SurgeryKitId,
                LabHeaderId = x.LabHeaderId
            });

            var insertResponse = await this.unitOfWork.PackageCharge.BulkInsertAsync(packageCharges, transaction);
            if (insertResponse <= 0)
            {
                transaction.Rollback();
                return -1;
            }


            if (model.LocationIds != null)
            {
                var ids = model.LocationIds.Split(',');
                foreach (var locationId in ids)
                {

                    var location = new LocationPackageMap
                    {
                        PackageId = packageId,
                        LocationId = Convert.ToInt32(locationId)
                    };
                    var locationInsertId = await this.unitOfWork.LocationPackageMap.InsertAsync(location, transaction);
                    if (locationInsertId == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }
            }

            transaction.Commit();
            return insertResponse;
        }

        public async Task<int> DeletePackageChargeAsync(DeleteModel model)
        {
            var isExists = await this.unitOfWork.AdmissionPackage.CountAsync(x => x.PackageId == model.PackageId && x.Active);
            if (isExists > 0)
            {
                return -2;
            }

            var deleteResponse = model.DeleteTypeId switch
            {
                PackageDeleteType.General => await this.unitOfWork.PackageCharge.DeleteAsync(x =>
                    x.PackageId == model.PackageId && x.ChargeId == model.Id),
                PackageDeleteType.Product => await this.unitOfWork.PackageCharge.DeleteAsync(x =>
                    x.PackageId == model.PackageId && x.ProductId == model.Id),
                _ => await this.unitOfWork.PackageCharge.DeleteAsync(x =>
                    x.PackageId == model.PackageId && x.SurgeryKitId == model.Id)
            };

            return deleteResponse ? 1 : -1;
        }

        public async Task<int> DeleteAsync(MetaData.FilterModel model)
        {
            var isExists = await this.unitOfWork.AdmissionPackage.CountAsync(x => x.PackageId == model.Id && x.Active);
            if (isExists > 0)
            {
                return -2;
            }

            var deleteResponse = await this.unitOfWork.Package.DeleteAsync(x =>
                x.PackageId == model.Id);

            return deleteResponse ? 1 : -1;
        }

        public async Task<int> UpdateAsync(UpdateModel model)
        {
            var transaction = this.unitOfWork.BeginTransaction();
            foreach (var record in model.Records)
            {
                if (record.ChargeId > 0)
                {
                    var isChargeExists = await this.unitOfWork.PackageCharge.FindAsync(x => x.PackageId == model.PackageId && x.ChargeId == record.ChargeId, transaction);
                    if (isChargeExists != null)
                    {
                        if (isChargeExists.Unit != record.Unit)
                        {
                            isChargeExists.Unit = record.Unit;
                            isChargeExists.ModifiedBy = model.CreatedBy;
                            isChargeExists.ModifiedDate = DateTime.Now;

                            var updateResponse = await this.unitOfWork.PackageCharge.UpdateAsync(isChargeExists, transaction);
                            if (updateResponse <= 0)
                            {
                                transaction.Rollback();
                                return -1;
                            }
                        }
                    }
                    else
                    {
                        var packageCharge = new PackageCharge
                        {
                            CreatedBy = model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            PackageId = model.PackageId,
                            Active = true,
                            ChargeId = record.ChargeId,
                            ProductId = null,
                            Unit = record.Unit,
                            ReducedAmount = record.ReducedAmount,
                            SurgeryKitId = null,
                            LabHeaderId = null
                        };
                        var insertResponse = await this.unitOfWork.PackageCharge.InsertAsync(packageCharge, transaction);
                        if (insertResponse <= 0)
                        {
                            transaction.Rollback();
                            return -1;
                        }
                    }
                }

                if (record.ProductId > 0)
                {
                    var isProductExists = await this.unitOfWork.PackageCharge.FindAsync(x => x.PackageId == model.PackageId && x.ProductId == record.ProductId, transaction);
                    if (isProductExists != null)
                    {
                        if (isProductExists.Unit != record.Unit)
                        {
                            isProductExists.Unit = record.Unit;
                            isProductExists.ModifiedBy = model.CreatedBy;
                            isProductExists.ModifiedDate = DateTime.Now;
                            var updateResponse = await this.unitOfWork.PackageCharge.UpdateAsync(isProductExists, transaction);
                            if (updateResponse <= 0)
                            {
                                transaction.Rollback();
                                return -1;
                            }
                        }
                    }
                    else
                    {
                        var packageCharge = new PackageCharge
                        {
                            CreatedBy = model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            PackageId = model.PackageId,
                            Active = true,
                            ChargeId = null,
                            ProductId = record.ProductId,
                            Unit = record.Unit,
                            ReducedAmount = record.ReducedAmount,
                            SurgeryKitId = null,
                            LabHeaderId = null
                        };
                        var insertResponse = await this.unitOfWork.PackageCharge.InsertAsync(packageCharge, transaction);
                        if (insertResponse <= 0)
                        {
                            transaction.Rollback();
                            return -1;
                        }
                    }
                }

                if (record.LabHeaderId > 0)
                {
                    var isLabExists = await this.unitOfWork.PackageCharge.FindAsync(x => x.PackageId == model.PackageId && x.LabHeaderId == record.LabHeaderId, transaction);
                    if (isLabExists != null)
                    {
                        if (isLabExists.Unit != record.Unit)
                        {
                            isLabExists.Unit = record.Unit;
                            isLabExists.ModifiedBy = model.CreatedBy;
                            isLabExists.ModifiedDate = DateTime.Now;
                            var updateResponse = await this.unitOfWork.PackageCharge.UpdateAsync(isLabExists, transaction);
                            if (updateResponse <= 0)
                            {
                                transaction.Rollback();
                                return -1;
                            }
                        }
                    }
                    else
                    {
                        var packageCharge = new PackageCharge
                        {
                            CreatedBy = model.CreatedBy,
                            CreatedDate = DateTime.Now,
                            PackageId = model.PackageId,
                            Active = true,
                            ChargeId = null,
                            ProductId = null,
                            Unit = record.Unit,
                            ReducedAmount = record.ReducedAmount,
                            SurgeryKitId = null,
                            LabHeaderId = record.LabHeaderId
                        };
                        var insertResponse = await this.unitOfWork.PackageCharge.InsertAsync(packageCharge, transaction);
                        if (insertResponse <= 0)
                        {
                            transaction.Rollback();
                            return -1;
                        }
                    }
                }

                if (record.SurgeryKitId > 0)
                {
                    var isProductExists = await this.unitOfWork.PackageCharge.FindAsync(x => x.PackageId == model.PackageId && x.SurgeryKitId == record.SurgeryKitId, transaction);
                    if (isProductExists != null) continue;
                    var packageCharge = new PackageCharge
                    {
                        CreatedBy = model.CreatedBy,
                        CreatedDate = DateTime.Now,
                        PackageId = model.PackageId,
                        Active = true,
                        ChargeId = null,
                        ProductId = null,
                        Unit = 0,
                        ReducedAmount = record.ReducedAmount,
                        SurgeryKitId = record.SurgeryKitId
                    };
                    var insertResponse = await this.unitOfWork.PackageCharge.InsertAsync(packageCharge, transaction);
                    if (insertResponse > 0) continue;
                    transaction.Rollback();
                    return -1;
                }
            }

            var package = await this.unitOfWork.Package.FindAsync(x => x.PackageId == model.PackageId, transaction);
            if (Math.Abs(package.Amount - model.Amount) > 0.0 || package.Name != model.Name)
            {
                package.Amount = model.Amount;
                package.Name = model.Name;
                package.ModifiedBy = model.CreatedBy;
                package.ModifiedDate = DateTime.Now;
                var updateResponse = await this.unitOfWork.Package.UpdateAsync(package, transaction);
                if (updateResponse <= 0)
                {
                    transaction.Rollback();
                    return -1;
                }
            }

            var query = $@"DELETE from ""LocationPackageMap"" where ""PackageId""= {package.PackageId} ";
            var res = await this.unitOfWork.Current.QuerySingleOrDefaultAsync(query, transaction);
            if (res == 0)
            {
                transaction.Rollback();
                return 0;
            }
            if (model.LocationIds != null)
            {
                var ids = model.LocationIds.Split(',');
                foreach (var locationId in ids)
                {

                    var location = new LocationPackageMap
                    {
                        PackageId = package.PackageId,
                        LocationId = Convert.ToInt32(locationId)
                    };
                    var locationInsertId = await this.unitOfWork.LocationPackageMap.InsertAsync(location, transaction);
                    if (locationInsertId == 0)
                    {
                        transaction.Rollback();
                        return 0;
                    }
                }
            }
            transaction.Commit();
            return 1;
        }

        public async Task<IEnumerable<Product.BasicViewModel>> FetchProductMastersAsync()
        {
            var query = $@"SELECT P
	                            .""PharmacyProductId"" AS ""ProductId"",
	                            P.""ProductName"",
	                            C.""LookupValueId"" AS ""CategoryId"",
	                            C.""Name"" AS ""CategoryName""
                            FROM
	                            ""PharmacyProduct""
	                            P LEFT JOIN ""LookupValue"" C ON C.""LookupValueId"" = P.""CategoryId""";
            var records = await this.unitOfWork.Current.QueryAsync<Product.BasicViewModel>(query);
            return records;
        }

        public async Task<IEnumerable<Product.ViewModel>> FetchProductsAsync(Product.FilterModel model)
        {
            var where = $@"WHERE 1 = 1 ";

            if (!string.IsNullOrEmpty(model.Product))
            {
                where += $@" AND p.""ProductName"" ilike '{model.Product}' ";
            }

            if (!string.IsNullOrEmpty(model.Category))
            {
                where += $@" AND c.""Name"" ilike '{model.Category}' ";
            }

            var query = $@"SELECT
                                COUNT(p.""PharmacyProductId"") OVER() AS ""TotalItems"",
                                p.""PharmacyProductId"" AS ""ProductId"",
                                p.""ProductName"",
                                p.""GenericName"",
                                c.""Name"" AS ""CategoryName"",
                                p.""Active"",
                                m.""Name"" AS ""CompanyName"",
                                costs.*
                            FROM
	                            ""PharmacyProduct"" p
	                            LEFT JOIN ""LookupValue"" c on c.""LookupValueId"" = p.""CategoryId""
	                            LEFT JOIN ""Company"" m on m.""CompanyId"" = p.""CompanyId""
	                            LEFT JOIN LATERAL (
		                            select d.""Mrp"", MIN(d.""Mrp"") OVER() AS ""Min"", MAX(d.""Mrp"") OVER() AS ""Max""  from ""PharmacyRetailStock"" d
		                            WHERE p.""PharmacyProductId"" = d.""PharmacyProductId"" AND (d.""QuantityIn"" - d.""QuantityOut"" > 0)
		                            LIMIT 1
	                            ) costs on true {where}";

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);

            var records = await this.unitOfWork.Current.QueryAsync<Product.ViewModel>(query);
            return records;
        }

        public async Task<IEnumerable<Surgery.BasicViewModel>> FetchSurgeryMastersAsync()
        {
            var query = $@"SELECT h.""KitName"" FROM ""SurgeryKitHeader"" h";
            var records = await this.unitOfWork.Current.QueryAsync<Surgery.BasicViewModel>(query);
            return records;
        }

        public async Task<IEnumerable<Surgery.ViewModel>> FetchSurgeryKitsAsync(Surgery.FilterModel model)
        {
            var where = $@"WHERE 1 = 1 ";

            if (!string.IsNullOrEmpty(model.Kit))
            {
                where += $@" AND h.""KitName"" = '{model.Kit}' ";
            }

            var query = $@"SELECT
	                        h.""SurgeryKitHeaderId"" AS ""SurgeryKitId"",
	                        h.""KitName"",
	                        p.""PharmacyProductId"" AS ""ProductId"",
	                        p.""ProductName"",
	                        p.""GenericName"",
	                        c.""Name"" AS ""CategoryName"",
	                        p.""Active"",
	                        m.""Name"" AS ""CompanyName"",
                            d.""Quantity"" AS ""Unit"",
	                        costs.*
                        FROM
	                        ""SurgeryKitHeader"" h
	                        LEFT JOIN ""SurgeryKitDetail"" d on d.""SurgeryKitHeaderId"" = h.""SurgeryKitHeaderId""
	                        LEFT JOIN ""PharmacyProduct"" p on p.""PharmacyProductId"" = d.""PharmacyProductId""
	                        LEFT JOIN ""LookupValue"" c on c.""LookupValueId"" = p.""CategoryId""
	                        LEFT JOIN ""Company"" m on m.""CompanyId"" = p.""CompanyId""
	                        LEFT JOIN LATERAL (
		                        select d.""Mrp"", MIN(d.""Mrp"") OVER() AS ""Min"", MAX(d.""Mrp"") OVER() AS ""Max""  from ""PharmacyRetailStock"" d
		                        WHERE p.""PharmacyProductId"" = d.""PharmacyProductId"" AND (d.""QuantityIn"" - d.""QuantityOut"" > 0)
		                        LIMIT 1
	                        ) costs on true {where}";
            var records = await this.unitOfWork.Current.QueryAsync<Surgery.ViewModel>(query);
            return records;
        }

        public async Task<string> FindNameByPackageId(int packageId)
        {
            var query = $@"SELECT ""Name"" FROM ""Package"" WHERE ""PackageId"" = {packageId}";
            var response = await this.unitOfWork.Current.QuerySingleOrDefaultAsync<string>(query);
            return response;

        }

    }
}
