import { getLogoSettings } from "./integration-settings"; export type LogoCandidate = { name: string; domain: string; logoUrl: string | null }; const DOMAIN_RE = /^[a-z0-9.-]+\.[a-z]{2,}$/i; export function normalizeDomain(domain: string | null | undefined): string | null { if (!domain) return null; const d = domain.trim().toLowerCase(); if (!DOMAIN_RE.test(d)) return null; return d; } /** Baut die öffentliche Logo-URL für eine gespeicherte Domain. Key bleibt serverseitig. */ export async function logoImageUrl(domain: string | null | undefined): Promise { const d = normalizeDomain(domain); const { publishableKey } = await getLogoSettings(); if (!d || !publishableKey) return null; return `https://img.logo.dev/${d}?token=${publishableKey}&size=128&format=png`; } /** Kürzel aus dem Anbieternamen als Fallback, z. B. "Therme Erding" → "TE". */ export function monogram(name: string): string { const parts = name.trim().split(/\s+/).filter(Boolean); if (parts.length === 0) return "?"; if (parts.length === 1) return parts[0].slice(0, 2).toUpperCase(); return (parts[0][0] + parts[1][0]).toUpperCase(); } /** Reichert ein Voucher-Objekt um die öffentliche logoUrl an (serverseitig). */ export async function withLogoUrl( v: T ): Promise { return { ...v, logoUrl: await logoImageUrl(v.providerDomain) }; } /** Sucht Anbieter über Logo.dev (serverseitig, Secret-Key). Gibt max. 8 Treffer zurück. */ export async function searchLogos(query: string): Promise { const { secretKey } = await getLogoSettings(); if (!secretKey) throw new Error("LOGO_DEV_SECRET_KEY fehlt"); const q = query.trim(); if (!q) return []; const res = await fetch(`https://api.logo.dev/search?q=${encodeURIComponent(q)}`, { headers: { Authorization: `Bearer ${secretKey}` }, }); if (!res.ok) throw new Error(`Logosuche ${res.status}`); const data: unknown = await res.json(); if (!Array.isArray(data)) return []; const out: LogoCandidate[] = []; for (const item of data) { if (typeof item !== "object" || item === null) continue; const rec = item as Record; const domain = normalizeDomain(typeof rec.domain === "string" ? rec.domain : null); if (!domain) continue; const name = typeof rec.name === "string" && rec.name.trim() ? rec.name.trim() : domain; out.push({ name, domain, logoUrl: await logoImageUrl(domain) }); if (out.length >= 8) break; } return out; }