import { eq, inArray } from "drizzle-orm";
import { db as prodDb } from "../../db/index.ts";
import { categories, globalItems, items, settings } from "../../db/schema.ts";

type Db = typeof prodDb;

interface OnboardingResult {
	itemsCreated: number;
	categoriesCreated: string[];
}

/**
 * Complete onboarding by batch-creating user items from selected global catalog items.
 * Auto-creates categories based on the global items' category field.
 * Sets onboardingComplete setting to "true".
 */
export async function completeOnboarding(
	db: Db = prodDb,
	userId: number,
	globalItemIds: number[],
): Promise<OnboardingResult> {
	if (globalItemIds.length === 0) {
		// No items selected — just mark complete
		await db
			.insert(settings)
			.values({ userId, key: "onboardingComplete", value: "true" })
			.onConflictDoUpdate({
				target: [settings.userId, settings.key],
				set: { value: "true" },
			});
		return { itemsCreated: 0, categoriesCreated: [] };
	}

	// Fetch all selected global items
	const selectedItems = await db
		.select()
		.from(globalItems)
		.where(inArray(globalItems.id, globalItemIds));

	if (selectedItems.length === 0) {
		await db
			.insert(settings)
			.values({ userId, key: "onboardingComplete", value: "true" })
			.onConflictDoUpdate({
				target: [settings.userId, settings.key],
				set: { value: "true" },
			});
		return { itemsCreated: 0, categoriesCreated: [] };
	}

	// Collect unique category names from global items
	const categoryNames = [
		...new Set(
			selectedItems
				.map((gi) => gi.category)
				.filter((c): c is string => c !== null && c.trim() !== ""),
		),
	];

	// Get existing user categories
	const existingCats = await db
		.select()
		.from(categories)
		.where(eq(categories.userId, userId));

	const existingCatMap = new Map(
		existingCats.map((c) => [c.name.toLowerCase(), c.id]),
	);

	// Create missing categories
	const newCategoryNames: string[] = [];
	for (const catName of categoryNames) {
		if (!existingCatMap.has(catName.toLowerCase())) {
			const [created] = await db
				.insert(categories)
				.values({ name: catName, userId })
				.returning();
			existingCatMap.set(catName.toLowerCase(), created.id);
			newCategoryNames.push(catName);
		}
	}

	// Get the "Uncategorized" category for items without a category
	let uncategorizedId = existingCatMap.get("uncategorized");
	if (!uncategorizedId) {
		const [unc] = await db
			.insert(categories)
			.values({ name: "Uncategorized", userId })
			.returning();
		uncategorizedId = unc.id;
	}

	// Create user items linked to global items
	let itemsCreated = 0;
	for (const gi of selectedItems) {
		const catId = gi.category
			? (existingCatMap.get(gi.category.toLowerCase()) ?? uncategorizedId)
			: uncategorizedId;

		await db.insert(items).values({
			name: gi.brand ? `${gi.brand} ${gi.model}` : gi.model,
			categoryId: catId,
			userId,
			weightGrams: gi.weightGrams,
			priceCents: gi.priceCents,
			// globalItem images are external URLs, not S3 filenames — skip copying
			// The item inherits its image via globalItemId linkage
			globalItemId: gi.id,
		});
		itemsCreated++;
	}

	// Mark onboarding complete
	await db
		.insert(settings)
		.values({ userId, key: "onboardingComplete", value: "true" })
		.onConflictDoUpdate({
			target: [settings.userId, settings.key],
			set: { value: "true" },
		});

	return { itemsCreated, categoriesCreated: newCategoryNames };
}
