import FacetFields from "@database/models/FacetFields";
import CategoryFacetFields from "@database/models/CategoryFacetFields";
import CategoryItemFacetFields from "@database/models/CategoryItemFacetFields";
import CategorySearches from "@database/models/CategorySearches";
import BrandSearches from "@database/models/BrandSearches";
import BrandFacetFields from "@database/models/BrandFacetFields";
import BrandItemFacetFields from "@database/models/BrandItemFacetFields";
type FacetSeedOptions = {
	instantFacetType?: string;
	instantSearchable?: boolean;
	categoryFacetType?: string;
	categorySearchable?: boolean;
};

async function ensureFacetRow(
	Model: any,
	where: Record<string, unknown>,
	createPayload: Record<string, unknown>,
	orderWhere?: Record<string, unknown>
) {
	const existing = await Model.findOne({ where });
	if (existing) return;
	const scopeRows = await Model.findAll({ where: orderWhere ?? where });
	const order = scopeRows?.length ?? 0;
	await Model.create({ ...createPayload, order });
}

/**
 * Seeds options.{name} and available_options.{name} facet rows (inactive by default).
 */
export async function registerProductOptionFacets(
	websiteId: number,
	optionNames: string[],
	titleForOption?: (optionName: string) => string,
	opts: FacetSeedOptions = {}
) {
	if (!optionNames?.length) return;

	const {
		instantFacetType = "disjunctive",
		instantSearchable = true,
		categoryFacetType = "disjunctive",
		categorySearchable = false,
	} = opts;

	const getTitle = titleForOption ?? ((name: string) => name);
	const collectionSearch = await CategorySearches.findOne({ where: { websiteId } });
	const brandSearch = await BrandSearches.findOne({ where: { websiteId } });

	for (let i = 0; i < optionNames.length; i++) {
		const optionName = optionNames[i];
		const title = getTitle(optionName);
		const pairs: { attribute: string; title: string; searchable: boolean; facetType: string }[] = [
			{
				attribute: `options.${optionName}`,
				title,
				searchable: instantSearchable,
				facetType: instantFacetType,
			},
			{
				attribute: `available_options.${optionName}`,
				title,
				searchable: instantSearchable,
				facetType: instantFacetType,
			},
		];

		for (const pair of pairs) {
			await ensureFacetRow(
				FacetFields,
				{ websiteId, attribute: pair.attribute },
				{
					websiteId,
					title: pair.title,
					attribute: pair.attribute,
					facetType: pair.facetType,
					searchable: pair.searchable,
					status: false,
				}
			);

			if (collectionSearch) {
				await ensureFacetRow(
					CategoryFacetFields,
					{ websiteId, attribute: pair.attribute },
					{
						websiteId,
						title: pair.title,
						attribute: pair.attribute,
						facetType: categoryFacetType,
						searchable: categorySearchable,
						status: false,
					}
				);

				const categoryFacetItems = await CategoryItemFacetFields.findAll({
					where: { websiteId },
					attributes: ["categoryId"],
					group: ["categoryId"],
				});
				if (categoryFacetItems?.length) {
					for (let m = 0; m < categoryFacetItems.length; m++) {
						const categoryId = categoryFacetItems[m].dataValues.categoryId;
						await ensureFacetRow(
							CategoryItemFacetFields,
							{ websiteId, categoryId, attribute: pair.attribute },
							{
								websiteId,
								categoryId,
								title: pair.title,
								attribute: pair.attribute,
								facetType: categoryFacetType,
								searchable: categorySearchable,
								status: false,
							},
							{ websiteId, categoryId }
						);
					}
				}
			}

			if (brandSearch) {
				await ensureFacetRow(
					BrandFacetFields,
					{ websiteId, attribute: pair.attribute },
					{
						websiteId,
						title: pair.title,
						attribute: pair.attribute,
						facetType: categoryFacetType,
						searchable: categorySearchable,
						status: false,
					}
				);

				const brandFacetItems = await BrandItemFacetFields.findAll({
					where: { websiteId },
					attributes: ["brandId"],
					group: ["brandId"],
				});
				if (brandFacetItems?.length) {
					for (let m = 0; m < brandFacetItems.length; m++) {
						const brandId = brandFacetItems[m].dataValues.brandId;
						await ensureFacetRow(
							BrandItemFacetFields,
							{ websiteId, brandId, attribute: pair.attribute },
							{
								websiteId,
								brandId,
								title: pair.title,
								attribute: pair.attribute,
								facetType: categoryFacetType,
								searchable: categorySearchable,
								status: false,
							},
							{ websiteId, brandId }
						);
					}
				}
			}
		}
	}
}
