import "server-only"; import type { AgentPsdFont } from "@/lib/agents/psd-font-config"; function normalizeFontToken(value: string) { return String(value || "") .trim() .toLowerCase() .replace(/[^a-z0-9]+/g, ""); } function isIgnoredFontName(value: string) { const normalized = normalizeFontToken(value); return ( !normalized || normalized === "adobeinvisfont" || normalized.startsWith("adobeheiti") || normalized.startsWith("adobesong") || normalized.startsWith("adobeming") ); } export function normalizeDetectedFontNames(value: unknown) { if (!Array.isArray(value)) return [] as string[]; return Array.from( new Set( value .map((item) => String(item || "").trim()) .filter((item) => item && !isIgnoredFontName(item)) ) ); } function getPsdFontIdentityTokens(font: Pick) { return Array.from( new Set( [font.name, font.family] .map((item) => normalizeFontToken(String(item || ""))) .filter(Boolean) ) ); } export function doesPsdFontMatchDetectedNames(params: { detectedFontNames: string[]; font: Pick; }) { const detectedFontNames = normalizeDetectedFontNames(params.detectedFontNames); if (detectedFontNames.length === 0) { return true; } const fontTokens = new Set(getPsdFontIdentityTokens(params.font)); return detectedFontNames.some((detectedFontName) => fontTokens.has(normalizeFontToken(detectedFontName)) ); } export function findBestMatchingPsdFont(params: { detectedFontNames: string[]; fonts: AgentPsdFont[]; }) { const detectedFontNames = normalizeDetectedFontNames(params.detectedFontNames); if (detectedFontNames.length === 0 || params.fonts.length === 0) { return null; } const exactMap = new Map(); const normalizedMap = new Map(); for (const font of params.fonts) { for (const candidate of [font.name, font.family]) { const raw = String(candidate || "").trim(); if (!raw) continue; exactMap.set(raw.toLowerCase(), font); normalizedMap.set(normalizeFontToken(raw), font); } } for (const detectedFontName of detectedFontNames) { const exactMatch = exactMap.get(detectedFontName.toLowerCase()); if (exactMatch) { return { font: exactMatch, detectedFontName, confidence: "high" as const, }; } } for (const detectedFontName of detectedFontNames) { const normalizedDetected = normalizeFontToken(detectedFontName); const normalizedMatch = normalizedMap.get(normalizedDetected); if (normalizedMatch) { return { font: normalizedMatch, detectedFontName, confidence: "high" as const, }; } } for (const detectedFontName of detectedFontNames) { const normalizedDetected = normalizeFontToken(detectedFontName); if (!normalizedDetected) continue; const containsMatch = params.fonts.find((font) => { const fontName = normalizeFontToken(font.name); const fontFamily = normalizeFontToken(font.family); return ( fontName.includes(normalizedDetected) || fontFamily.includes(normalizedDetected) || normalizedDetected.includes(fontName) || normalizedDetected.includes(fontFamily) ); }); if (containsMatch) { return { font: containsMatch, detectedFontName, confidence: "medium" as const, }; } } return null; }