import { createTypeSenseClient } from "./typesense.ts";
import { ensureProductCollectionSchema } from "./ensureProductCollectionSchema.ts";
import { registerProductOptionFacets } from "./registerProductOptionFacets.ts";
import { buildAvailableOptionsFromVariants } from "./variantInStockForFacets.ts";
import { CollectionDetails, CustomFields } from "../../../Database/Connection.js";
import { bigcommerceClient } from "../../../Utils/BigCommerce.js";

import * as cheerio from "cheerio";
import { buildColorMap, buildOptionType } from "./buildOptionType.ts";
import { applyProductNormalizedFields } from "./productSearchNormalize.ts";
import { parseBcMoney } from "../../Utils/bigcommerceAiProductPricing.js";

const logger = {
	info: (...args: unknown[]) => console.log("[search-product-webhook]", ...args),
	error: (...args: unknown[]) => console.error("[search-product-webhook]", ...args),
};

const stripHtmlTags = (input: string) => {
	if (input == null || typeof input !== "string") return "";
	const $ = cheerio.load(input);
	$("style, script, noscript").remove();
	return $.text().replace(/\s+/g, " ").trim();
};

const getParentIds = (category:any, categories:any) => {
	const parentIds = [];
	let currentCategory = category;
	while (currentCategory && currentCategory.parent_id !== 0) {
		parentIds.push(currentCategory.parent_id);
		currentCategory = categories.find((cat:any) => cat.category_id === currentCategory.parent_id);
	}
	return parentIds;
}

const getFullPath = (cat: any, categoryMap: any) => {
	let path = [cat.name];
	while (cat && cat.parent_id !== 0) {
		cat = categoryMap[cat.parent_id];
		if (!cat) break;
		path.unshift(cat.name);
	}
	return path.join(' > ');
}

const getCategoryParentId	= async (bigCommerce:any) =>{
	try{
		let page						= 1,
			categoryIds				= {},
			categoryDataArray		= [],
			categoryDataObject	= await bigCommerce.get(`/catalog/trees/categories?limit=250&page=${page}&include_fields=category_id,parent_id,name`);
		if( typeof categoryDataObject.data !== "undefined" ){
			let categoryData	= categoryDataObject.data,
				totalPages	= categoryDataObject.meta.pagination.total_pages;
			while( page <= totalPages ){
				categoryDataArray	= [...categoryDataArray, ...categoryData]
				page++;
				if( page <= totalPages ){
					categoryDataObject	= await bigCommerce.get(`/catalog/trees/categories?limit=250&page=${page}&include_fields=category_id,parent_id,name`)
					if( typeof categoryDataObject.data !== "undefined" ){
						categoryData	= categoryDataObject.data
					}
				}
				
			}
		}
		categoryDataArray.forEach(category => {
			categoryIds[category.category_id] = {
				name: category.name,
				parent_id: category.parent_id || 0,
				parentIds: getParentIds(category, categoryDataArray)
			};
		});
		return categoryIds
	}catch(e){
		console.log(e)
		return {}
	}
}

function normalizeFieldName(name:string) {
	return name.replace(/[^a-zA-Z0-9 _.]/g, ""); // remove all except letters, numbers, and spaces
}

export async function processBcSearchProductWebhookJob(job: {
	websiteId: number;
	scope: string;
	entityId: number;
	payload: string;
}) {
	try {
		const payloadParsed = job.payload ? JSON.parse(job.payload) : {};
		if (!payloadParsed?.data) return;

		let id = parseInt(String(job.entityId), 10);
		let websiteId = parseInt(String(job.websiteId), 10);
		let type = String(job.scope || "");
		let storeHash: any = null;
		let accessToken: any = null;
		let websiteDetail: any = null;
		let attributeToFilterValues: any = {};
		let colorFamilies: any = [];
		let colorFilters: any = [];
		let customFilters: any = {};
		let customFilterWithName: any = {};
		let typeSenseConfig: any = null;

		const rawResponse = await fetch(
			`${process.env.CBEND_URL}/api/v1/website/getBigCommerceSearchShopDetails`,
			{
				method: "POST",
				headers: {
					Accept: "application/json",
					"Content-Type": "application/json",
				},
				body: JSON.stringify({ websiteId }),
			}
		);
		const content = await rawResponse.json();
		if (content.status === "success") {
			websiteDetail = content.data.websiteDetail ? content.data.websiteDetail : {};
			typeSenseConfig = content.data.typeSenseConfig ? content.data.typeSenseConfig : {};
			accessToken = content.data.accessToken ? content.data.accessToken : null;
			storeHash = content.data.storeHash ? content.data.storeHash : null;
			attributeToFilterValues = content.data.attributeToFilterValues
				? content.data.attributeToFilterValues
				: {};
			colorFamilies = content.data?.colorFamilies || [];
			colorFilters = content.data?.colorFilters || [];
			customFilters = content.data?.customFilters || {};
			customFilterWithName = content.data?.customFilterWithName || {};
		}
		
		logger.info(`Webhook received: ${type} For ${websiteDetail?.websiteURL}`);
      logger.info(`Payload: ${JSON.stringify(req.body, null, 2)}`);
		logger.info(`Type: ${type}`);
		logger.info(accessToken, storeHash);
		if (typeSenseConfig && Object.keys(typeSenseConfig).length > 0 && storeHash && accessToken) {
			let client = await createTypeSenseClient(typeSenseConfig),
				productCollectionName = typeSenseConfig.tablePrefix + websiteId + "_products";
			if (type == "product/deleted") {
				client.collections(productCollectionName).documents("" + id).delete()
					.then(async (response) => {
						client.collections(productCollectionName).retrieve()
							.then(async (collectionInfo) => {
								let collectionCount = collectionInfo.num_documents;
								await CollectionDetails.update({ collectionCount }, { where: { websiteId, collectionType: "product" } })
							})
					}).catch(error => {
						console.error('Error delete product documents:', error);
					})
			} else {
				logger.info(`Product Updated`);
				let shouldCallEnrichment = false;
				const bigCommerce = await bigcommerceClient(accessToken, storeHash)
				let categoryTreeIds	= await getCategoryParentId(bigCommerce)
				const productData = await bigCommerce.get(`/catalog/products/${id}?include=channels,custom_fields,variants,images,options,modifiers`);
				logger.info(`Product Data: ${JSON.stringify(productData, null, 2)}`);
				if (productData !== null) {
					let product = productData.data,
						resultProducts: any = {}
					if (websiteId === 791) {
						try {
							const existingDoc = await client.collections(productCollectionName).documents("" + id).retrieve() as { title?: string; name?: string; description?: string } | null;
							const newTitle = product.name ?? "";
							const newDesc = product.description ? stripHtmlTags(product.description) : "";
							const oldTitle = (existingDoc?.title ?? existingDoc?.name) ?? "";
							const oldDesc = existingDoc?.description ?? "";
							shouldCallEnrichment = (String(oldTitle) !== String(newTitle) || String(oldDesc) !== String(newDesc));
						} catch {
							shouldCallEnrichment = true;
						}
					}
					resultProducts['id'] = "" + product.id
					resultProducts['product_id']	= product.id
					resultProducts['title'] = product.name
					resultProducts['name'] = product.name
					resultProducts['type'] = product.type ? product.type : ""
					resultProducts['created_at'] = product.date_created ? Math.floor(new Date(product.date_created).getTime() / 1000) : 0
					resultProducts['sku'] = product.sku ? product.sku : ""
					resultProducts['price'] = product.price ? parseFloat(parseFloat(product.price).toFixed(2)) : 0
					resultProducts['cost_price'] = product.cost_price ? parseFloat(parseFloat(product.cost_price).toFixed(2)) : 0
					resultProducts['retail_price'] = product.retail_price ? parseFloat(parseFloat(product.retail_price).toFixed(2)) : 0
					resultProducts['sale_price'] = product.sale_price ? parseFloat(parseFloat(product.sale_price).toFixed(2)) : 0
					resultProducts['calculated_price'] = product.calculated_price ? parseFloat(parseFloat(product.calculated_price).toFixed(2)) : 0
					resultProducts['effective_price']	= resultProducts['sale_price'] > 0 ? resultProducts['sale_price'] : resultProducts['price']
					resultProducts['is_visible'] = product.is_visible ? 1 : 0
					resultProducts['is_featured'] = product.is_featured ? 1 : 0
					resultProducts['availability'] = product.availability ?? "available"
					resultProducts['isPriceHidden'] = product.is_price_hidden ? 1 : 0
					resultProducts['priceHiddenLabel'] = product.price_hidden_label ?? ""
					resultProducts['description'] = product.description ? stripHtmlTags(product.description) : ""
					resultProducts["searchKeywords"]		= product.search_keywords ?? ""
					resultProducts['html_description']	= product.description
					resultProducts['url'] = product.custom_url ? product.custom_url.url : ""
					resultProducts['stock_qty'] = 0
					resultProducts["inventory_tracking"]	= product.inventory_tracking
					resultProducts["modifiers"]	= product.modifiers
					if( product.inventory_tracking === "none" ){
						resultProducts["in_stock"]	= 1
					}else if( product.inventory_tracking === "product" ){
						resultProducts['stock_qty']	= parseInt(product.inventory_level)
						if( product.inventory_level === 0 ){
							resultProducts["in_stock"]	= 0
						}else{
							resultProducts["in_stock"]	= 1
						}
					}else if( product.inventory_tracking === "variant" ){
						resultProducts["stock_qty"]	= 0
						resultProducts["in_stock"]		= 0
					}
					resultProducts['weight'] = product.weight ? product.weight : 0
					resultProducts['width'] = product.width ? product.width : 0
					resultProducts['depth'] = product.depth ? product.depth : 0
					resultProducts['height'] = product.height ? product.height : 0
					if (product.brand_id > 0) {
						let brandNameObj = await bigCommerce.get('/catalog/brands/' + product.brand_id);
						if (brandNameObj && brandNameObj.data) {
							let brandData = brandNameObj.data
							resultProducts['brand'] = brandData.name
						}
						resultProducts['brandId'] = product.brand_id
					} else {
						resultProducts['brand'] = ""
						resultProducts['brandId'] = 0
					}
					resultProducts['timeStamp'] = new Date()
					resultProducts['variants'] = []
					resultProducts['variant_ids'] = []
					resultProducts['product_images'] = []
					resultProducts['categories'] = []
					resultProducts['category_ids'] = []
					resultProducts['options'] = {}
					resultProducts['available_options'] = {}
					resultProducts['option_names'] = []
					resultProducts['option_type'] = []
					resultProducts['discount_category_ids']		= []
					resultProducts['categories_full_path'] = []
					resultProducts['image'] = ""
					resultProducts['upc'] = product.upc ? product.upc : ""
					resultProducts["bin_picking_number"]	= product.bin_picking_number ?? ""
					for (let vals of product.categories) {
						if (!categoryTreeIds[vals]) continue
						resultProducts.categories.push(categoryTreeIds[vals].name)
						resultProducts.category_ids.push(vals)
						resultProducts.discount_category_ids.push(vals)
						resultProducts.categories_full_path.push(
							getFullPath(
								{ name: categoryTreeIds[vals].name, parent_id: categoryTreeIds[vals].parent_id },
								categoryTreeIds
							)
						)
						resultProducts.category_ids	= [...resultProducts.category_ids, ...categoryTreeIds[vals].parentIds]
					}
					if( resultProducts.category_ids.length > 0 ){
						resultProducts.category_ids	= [...new Set(resultProducts.category_ids)]
					}
					const colorMap = buildColorMap(product);
					resultProducts['option_type'] = buildOptionType(product);
					let variants = product.variants
					if( variants ){
						if( variants.length > 0 ){
							resultProducts['total_variants']	= variants.length
							for( let i = 0; i < variants.length; i++ ){
								let productVariants	= variants[i],
									variantsProducts	= {}
								resultProducts['variant_ids'].push(productVariants.id)
								variantsProducts['id']						= productVariants.id
								variantsProducts['sku']						= productVariants.sku ? productVariants.sku : ""
								variantsProducts['upc']						= productVariants.upc ? productVariants.upc : ""
								variantsProducts['price']					= parseBcMoney(productVariants.price)
								variantsProducts['retail_price']			= parseBcMoney(productVariants.retail_price)
								variantsProducts['sale_price']			= parseBcMoney(productVariants.sale_price)
								variantsProducts['stock_qty']				= productVariants.inventory_level ? productVariants.inventory_level : 0
								variantsProducts['option_values']		= productVariants.option_values ? productVariants.option_values : ""
								variantsProducts['calculated_price']	= parseBcMoney(productVariants.calculated_price)
								variantsProducts['image_url']				= productVariants.image_url ? productVariants.image_url : ""
								variantsProducts['options']				= {}
								let optionValues	= productVariants.option_values;
								if( optionValues && optionValues.length > 0 ){
									for( let j = 0; j < optionValues.length; j++ ){
										let currentOptionValue	= optionValues[j],
											optionValue	= currentOptionValue.label,
											optionName	= currentOptionValue.option_display_name
										if( typeof resultProducts['options'][optionName] === "undefined" ){
											resultProducts['options'][optionName]	= []
										}
										if( resultProducts['options'][optionName].indexOf(optionValue) === -1 ){
											resultProducts['options'][optionName].push(optionValue)
										}
										if( resultProducts['option_names'].indexOf(optionName) === -1 ){
											resultProducts['option_names'].push(optionName)
										}
										variantsProducts['options'][optionName]	= optionValue
									}
								}
								if ( Object.keys(colorMap).length > 0 ){
									variantsProducts['option_values'] = variantsProducts['option_values'].map(option => {
										if ( colorMap[option.id]) {
											return { ...option, color_code: colorMap[option.id] };
										}
										return option;
									})
								}
								if( product.inventory_tracking === "variant" ){
									if( resultProducts["in_stock"] === 0 && parseInt(productVariants.inventory_level) > 0 ){
										resultProducts["in_stock"]	= 1
									}
									if( parseInt(productVariants.inventory_level) > 0 ){
										variantsProducts["in_stock"]	= 1
									}else{
										variantsProducts["in_stock"]	= 0
									}
									if( parseInt(productVariants.inventory_level) > 0 ){
										resultProducts["stock_qty"]	+= parseInt(productVariants.inventory_level)
									}
								}else{
									variantsProducts["in_stock"]	= 1
								}
								resultProducts['variants'].push(variantsProducts)
							}
							resultProducts["available_options"] = buildAvailableOptionsFromVariants(
								product.inventory_tracking,
								resultProducts["in_stock"],
								resultProducts["variants"]
							);
						}
					}
					let productImages = product.images
					if (productImages) {
						for (let i = 0; i < productImages.length; i++) {
							let productImg = productImages[i]
							resultProducts['product_images'].push(productImg.url_standard??productImg.url_thumbnail)
							if (productImg.is_thumbnail) {
								resultProducts['image'] = productImg.url_standard??productImg.url_thumbnail
							}
						}
					}
					let customFieldObj	= await CustomFields.findAll({where: {websiteId}, attributes: ["name"], order: [["customFieldId", "asc"]]}),
						customFields		= []
					if( customFields ){
						for( let i = 0; i < customFieldObj.length; i++ ){
							customFields.push(customFieldObj[i].dataValues.name)
						}
					}
					if( customFields.length > 0 ){
						resultProducts['custom_fields']	= {}
						let productCustomFields	= product.custom_fields
						if( productCustomFields ){
							for( let i = 0; i < productCustomFields.length; i++ ){
								let currentCustomField	= productCustomFields[i]
								let cleanedName = normalizeFieldName(currentCustomField.name);
								if( customFields.indexOf(currentCustomField.name) !== -1 ){
									if( typeof resultProducts['custom_fields'][cleanedName] === "undefined" ){
										resultProducts['custom_fields'][cleanedName]	= []
									}
									if( currentCustomField.value.indexOf("|") === -1 ){
										resultProducts['custom_fields'][cleanedName].push(currentCustomField.value.toString().replace(/#/g, "cbSharp"))
									}else{
										let customFieldValues	= currentCustomField.value.split("|")
										customFieldValues = customFieldValues.map((value:string) => value.replace(/#/g, "cbSharp"));
										resultProducts['custom_fields'][cleanedName] = resultProducts['custom_fields'][cleanedName].concat(customFieldValues)
									}
								}
							}
						}
					}
					// if( websiteId === 519 ){
					// 	if( resultProducts["retail_price"] > resultProducts["price"] && resultProducts["sale_price"] > 0 && resultProducts["price"] === resultProducts["sale_price"] ){
					// 		resultProducts["sale_price"]	= resultProducts["price"]
					// 		resultProducts["price"]	= resultProducts["retail_price"]
					// 		resultProducts["effective_price"]	= resultProducts["sale_price"]
					// 	}
					// }
					resultProducts['channel_ids'] = product.channels
					logger.info(`Before Process: ${JSON.stringify(resultProducts, null, 2)}`);
					// Helper function to get nested value from object using dot notation
					const getNestedValue = (obj:any, path:any) => {
						const parts = path.split('.');
						let current = obj;
						for (const part of parts) {
							if (current === null || current === undefined) return undefined;
							current = current[part];
						}
						return current;
					};

					// Helper function to set nested value in object using dot notation
					const setNestedValue = (obj:any, path:any, value:any) => {
						const parts = path.split('.');
						let current = obj;

						// Navigate to the parent of the target field
						for (let i = 0; i < parts.length - 1; i++) {
							if (!current[parts[i]]) {
								current[parts[i]] = {};
							}
							current = current[parts[i]];
						}

						// Set the final value
						current[parts[parts.length - 1]] = value;
					};

					// Helper function to map color values to color families
					const getMappedColor = (value:string) => {
						if (!value || typeof value !== 'string') return "Unmapped";

						const normalizedValue = value.toLowerCase().trim();

						if (!colorFamilies || !Array.isArray(colorFamilies)) return "Unmapped";

						const mappedFamily = colorFamilies.find(fam => {
							// Split colorsIncluded into array of colors
							let colors = [];
							if (fam.colorsIncluded) {
								colors = fam.colorsIncluded.split(",").map(c => c.trim().toLowerCase());
							}

							// Check if value matches any color in the family or matches the family code
							return colors.includes(normalizedValue) || (fam.familyCode && fam.familyCode.toLowerCase() === normalizedValue);
						});

						if (mappedFamily) {
							return mappedFamily.familyName || "Unmapped";
						}

						return "Unmapped";
					};

					// Get color filter attributes from colorFilters array
					const colorFilterAttributes = colorFilters.map((filter:any) => filter.attribute).filter(Boolean);

					// Replace attribute values with displayNames from attributeToFilterValues (optimized with Map lookups)
					if (attributeToFilterValues && Object.keys(attributeToFilterValues).length > 0) {
						// Pre-build lookup Maps for O(1) access instead of O(n) find operations
						const attributeLookupMaps = new Map();

						for (const attributePath in attributeToFilterValues) {
							const filterValues = attributeToFilterValues[attributePath];
							if (Array.isArray(filterValues) && filterValues.length > 0) {
								const valueMap = new Map();
								for (const filter of filterValues) {
									if (filter.value !== null && filter.value !== undefined && filter.displayName) {
										// Store both exact match and string match for flexibility
										valueMap.set(filter.value, filter.displayName);
										valueMap.set(String(filter.value), filter.displayName);
									}
								}
								if (valueMap.size > 0) {
									attributeLookupMaps.set(attributePath, valueMap);
								}
							}
						}

						// Helper function to get displayName using O(1) Map lookup
						const getDisplayName = (attributePath:string, value:string) => {
							const valueMap = attributeLookupMaps.get(attributePath);
							if (!valueMap) {
								return value; // Return original value if attribute not found
							}
							// Try exact match first, then string match
							return valueMap.get(value) || valueMap.get(String(value)) || value;
						};

						// Replace custom_fields values
						if (resultProducts.custom_fields) {
							for (let key in resultProducts.custom_fields) {
								const attributePath = `custom_fields.${key}`;
								let value = resultProducts.custom_fields[key];

								if (Array.isArray(value)) {
									// Replace each value in array
									resultProducts.custom_fields[key] = value.map(v => getDisplayName(attributePath, v));
								} else if (value !== null && value !== undefined) {
									// Replace single value
									resultProducts.custom_fields[key] = getDisplayName(attributePath, value);
								}
							}
						}

						// Replace categories
						if (resultProducts.categories && Array.isArray(resultProducts.categories)) {
							const attributePath = 'categories';
							resultProducts.categories = resultProducts.categories.map((category:any) => getDisplayName(attributePath, category));
						}

						// Replace product_type
						if (resultProducts.product_type) {
							const attributePath = 'product_type';
							resultProducts.product_type = getDisplayName(attributePath, resultProducts.product_type);
						}

						// Replace tags
						if (resultProducts.tags && Array.isArray(resultProducts.tags)) {
							const attributePath = 'tags';
							resultProducts.tags = resultProducts.tags.map((tag:any) => getDisplayName(attributePath, tag));
						}

						// Replace brand
						if (resultProducts.brand) {
							const attributePath = 'brand';
							resultProducts.brand = getDisplayName(attributePath, resultProducts.brand);
						}

						// Replace options values
						if (resultProducts.options && typeof resultProducts.options === 'object') {
							for (let optionKey in resultProducts.options) {
								const attributePath = `options.${optionKey}`;
								let optionValue = resultProducts.options[optionKey];

								if (Array.isArray(optionValue)) {
									// Replace each value in array
									resultProducts.options[optionKey] = optionValue.map(v => getDisplayName(attributePath, v));
								} else if (optionValue !== null && optionValue !== undefined) {
									// Replace single value
									resultProducts.options[optionKey] = getDisplayName(attributePath, optionValue);
								}
							}
						}

						if (resultProducts.available_options && typeof resultProducts.available_options === "object") {
							for (let optionKey in resultProducts.available_options) {
								const attributePath = `options.${optionKey}`;
								let optionValue = resultProducts.available_options[optionKey];
								if (Array.isArray(optionValue)) {
									resultProducts.available_options[optionKey] = optionValue.map((v) =>
										getDisplayName(attributePath, v)
									);
								} else if (optionValue !== null && optionValue !== undefined) {
									resultProducts.available_options[optionKey] = getDisplayName(attributePath, optionValue);
								}
							}
						}
					}

					// Populate custom filter attributes by combining parent filter values
					if (customFilters && Object.keys(customFilters).length > 0) {
						// Process each custom filter
						for (const customAttribute in customFilters) {
							const parentAttributes = customFilters[customAttribute];

							if (!Array.isArray(parentAttributes) || parentAttributes.length === 0) {
								continue;
							}

							// Collect all unique values from parent attributes
							const valuesSet = new Set();

							for (const parentAttr of parentAttributes) {
								const attrValue = getNestedValue(resultProducts, parentAttr);

								if (attrValue !== undefined && attrValue !== null) {
									if (Array.isArray(attrValue)) {
										// Add all values from array
										attrValue.forEach(v => {
											if (typeof v === "string" && v.trim().length > 0) {
												valuesSet.add(v.trim());
											} else if (v !== null && v !== undefined) {
												valuesSet.add(String(v).trim());
											}
										});
									} else if (typeof attrValue === "string" && attrValue.trim().length > 0) {
										// Add single string value
										valuesSet.add(attrValue.trim());
									} else if (attrValue !== null && attrValue !== undefined) {
										// Convert other types to string
										valuesSet.add(String(attrValue).trim());
									}
								}
							}

							// Only set the custom attribute if we have values
							if (valuesSet.size > 0) {
								const combinedValues = Array.from(valuesSet);

								// Set the custom attribute value
								if (customAttribute.includes('.')) {
									// Handle nested attributes (e.g., options.color_156)
									setNestedValue(resultProducts, customAttribute, combinedValues);
								} else {
									// Handle top-level attributes
									resultProducts[customAttribute] = combinedValues;
								}

								console.log(`Set ${customAttribute} for product ${resultProducts.id}:`, combinedValues);
							}
						}
					}

					// Map color values to color families for color filter attributes
					if (colorFilterAttributes.length > 0 && colorFamilies.length > 0) {
						console.log('Processing color family mappings for color filters');

						for (const colorAttribute of colorFilterAttributes) {
							const colorValue = getNestedValue(resultProducts, colorAttribute);

							if (colorValue !== undefined && colorValue !== null) {
								let mappedColors = [];

								if (Array.isArray(colorValue)) {
									// Map each color value in the array to its color family
									mappedColors = colorValue.map(v => {
										if (typeof v === "string" && v.trim().length > 0) {
											return getMappedColor(v);
										}
										return "Unmapped";
									}).filter(color => color !== "Unmapped");

									// Remove duplicates
									mappedColors = [...new Set(mappedColors)];
								} else if (typeof colorValue === "string" && colorValue.trim().length > 0) {
									// Map single color value
									const mapped = getMappedColor(colorValue);
									if (mapped !== "Unmapped") {
										mappedColors = [mapped];
									}
								}

								// Update the product with mapped color families
								if (mappedColors.length > 0) {
									if (colorAttribute.includes('.')) {
										// Handle nested attributes
										setNestedValue(resultProducts, colorAttribute, mappedColors);
									} else {
										// Handle top-level attributes
										resultProducts[colorAttribute] = mappedColors;
									}

									console.log(`Mapped colors for ${colorAttribute} in product ${resultProducts.id}:`, mappedColors);
								}
							}
						}
					}

					// Add custom filter attributes to options array for facet field creation
					if (customFilters && Object.keys(customFilters).length > 0) {
						let customFilterAttribute = Object.keys(customFilters);
						for (let i = 0; i < customFilterAttribute.length; i++) {
							const optionName = customFilterAttribute[i].replace("options.", "");
							if (resultProducts["option_names"].indexOf(optionName) === -1) {
								resultProducts["option_names"].push(optionName);
							}
						}
					}
					logger.info(`Before Process: ${JSON.stringify(resultProducts, null, 2)}`);
					applyProductNormalizedFields(resultProducts);
					await ensureProductCollectionSchema(client, productCollectionName);
					client.collections(productCollectionName).documents().upsert(resultProducts)
						.then(async (response) => {
							if (websiteId === 791 && shouldCallEnrichment) {
								fetch(`${process.env.CBEND_URL}/api/v1/job/enrichProductWebhook`, {
									method: "POST",
									headers: { "Accept": "application/json", "Content-Type": "application/json" },
									body: JSON.stringify({ websiteId: 791, productId: id }),
								}).catch(() => {});
							}
							client.collections(productCollectionName).retrieve()
								.then(async (collectionInfo) => {
									let collectionCount = collectionInfo.num_documents;
									await CollectionDetails.update({ collectionCount }, { where: { websiteId, collectionType: "product" } })
								})
						}).catch(error => {
							console.error('Error creating collection:', error);
						})
					await registerProductOptionFacets(
						websiteId,
						resultProducts["option_names"] ?? [],
						(name) => customFilterWithName[name] ?? name
					);
				}
			}
		}
	} catch (e) {
		console.log(e);
		logger.error(e);
		throw e;
	}
}