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";

const logger = {
	info: (...args: unknown[]) => console.log("[search-assignment-webhook]", ...args),
	error: (...args: unknown[]) => console.error("[search-assignment-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();
};

// Helper function to find all parent IDs
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
					}
				}
				
			}
		}
		// Build the category mapping
		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 processBcSearchProductAssignmentWebhookJob(job: {
	websiteId: number;
	scope: string;
	entityId: number;
	payload: string;
}) {
	try {
		const payloadParsed = job.payload ? JSON.parse(job.payload) : {};
		const product_id = payloadParsed?.data?.product_id ?? job.entityId;
		let id = parseInt(String(product_id), 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 || {};
		}
		
		// Fetch filter configuration
		let bigCommerceContent: any = null;
		try {
			let filterResponse = 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 filterContent = await filterResponse.json();
			if (filterContent.status === "success") {
				bigCommerceContent = filterContent.data || {};
			}
		} catch (e) {
			console.log('Error fetching filter config:', e);
		}
		
		logger.info(`Webhook received: ${type} For ${websiteDetail?.websiteURL}`);
      logger.info(`Payload: ${JSON.stringify(req.body, null, 2)}`);
		if( typeSenseConfig && Object.keys(typeSenseConfig).length > 0 && storeHash && accessToken ){
			let client	= await createTypeSenseClient(typeSenseConfig),
				productCollectionName	= typeSenseConfig.tablePrefix+websiteId+"_products";
			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`);
			if (productData !== null) {
				let product = productData.data,
					resultProducts: any = {},
					shouldCallEnrichment = false;
				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['html_description']	= product.description
				resultProducts["searchKeywords"]		= product.search_keywords ?? ""
				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']					= productVariants.price ? parseFloat(parseFloat(productVariants.price).toFixed(2)) : 0
							variantsProducts['retail_price']			= productVariants.retail_price ? parseFloat(parseFloat(productVariants.retail_price).toFixed(2)) : 0
							variantsProducts['sale_price']			= productVariants.sale_price ? parseFloat(parseFloat(productVariants.sale_price).toFixed(2)) : 0
							variantsProducts['stock_qty']				= productVariants.inventory_level ? productVariants.inventory_level : 0
							variantsProducts['option_values']		= productVariants.option_values ? productVariants.option_values : ""
							variantsProducts['calculated_price']	= productVariants.calculated_price ? parseFloat(productVariants.calculated_price) : 0
							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 ( colorMap && 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 //await bigCommerce.get('/catalog/products/' + product.id + '/images')
				if (productImages) {
					//let data = productImages.data
					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 //await bigCommerce.get('/catalog/products/'+product.id+'/custom-fields?limit=0&page=1')
					if( productCustomFields ){
						//let data	= productCustomFields.data
						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("|")
									// Replace all `#` with `cbSearch` in each string
									customFieldValues = customFieldValues.map((value:string) => value.replace(/#/g, "cbSharp"));
									resultProducts['custom_fields'][cleanedName] = resultProducts['custom_fields'][cleanedName].concat(customFieldValues)
								}
							}
						}
					}
				}
				resultProducts['channel_ids'] = product.channels
				// 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"]
				// 	}
				// }
				// 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);
						}
					}
				}
				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;
	}
}