import { prisma } from "@/lib/db"; import { attachBrandToTopic, buildMergedProductContext, migrateLegacyProductCatalog, syncTopicProductSnapshot, } from "@/lib/services/product-catalog"; import { hasProductContext, parseProductContext } from "@/lib/types/product-context"; /** 將主題內嵌的 productContext 補寫進 ProductProfile 表(舊資料相容)。 */ export async function migrateOrphanProductContexts(accountIds: string[]) { if (accountIds.length === 0) return; await migrateLegacyProductCatalog(accountIds); const orphans = await prisma.topic.findMany({ where: { accountId: { in: accountIds }, topicGoal: "placement", productProfileId: null, productContext: { not: null }, }, }); for (const topic of orphans) { const context = topic.productContext?.trim(); if (!context || !hasProductContext(context)) continue; const fields = parseProductContext(context); const label = [fields.brand, fields.product].filter(Boolean).join(" · ") || topic.label; const existing = topic.accountId ? await prisma.productProfile.findFirst({ where: { accountId: topic.accountId, context, }, }) : null; const profile = existing ?? (await prisma.productProfile.create({ data: { accountId: topic.accountId ?? undefined, label, context, }, })); await prisma.topic.update({ where: { id: topic.id }, data: { productProfileId: profile.id }, }); } } export async function syncProfileContextToTopics(profileId: string, context: string) { await prisma.topic.updateMany({ where: { productProfileId: profileId }, data: { productContext: context.trim() || null }, }); } export async function attachProfileToTopic(topicId: string, profileId: string | null) { if (!profileId) { const topic = await prisma.topic.update({ where: { id: topicId }, data: { productProfileId: null }, }); await syncTopicProductSnapshot(topicId); return topic; } const profile = await prisma.productProfile.findUnique({ where: { id: profileId }, include: { brand: true }, }); if (!profile) throw new Error("找不到產品"); if (profile.brandId) { return attachBrandToTopic(topicId, profile.brandId, profileId); } const context = buildMergedProductContext( profile.brand?.name ?? parseProductContext(profile.context).brand, profile.context, profile.label ); return prisma.topic.update({ where: { id: topicId }, data: { productProfileId: profileId, productContext: context, }, }); } export async function attachBrandSelectionToTopic( topicId: string, brandId: string | null, productId: string | null ) { return attachBrandToTopic(topicId, brandId, productId); } export function validateProfileContext(context: string | null | undefined): boolean { return hasProductContext(context); }