exports.generatePicturePrompt = (project = {}) => { const { title = "", lyrics: lyricsRaw, musicConfig = {}, coverStyle: coverStyleRaw = "", artistName: artistNameRaw = "", } = project || {}; // --- 1. Nettoyage et Normalisation --- const sanitizeInline = (value = "") => { if (typeof value !== "string") return ""; return value .replace(/[\r\n]+/g, " ") .replace(/[<>]/g, "") .trim(); }; const titleForPrompt = sanitizeInline(title) || "Sans titre"; const artistName = sanitizeInline(artistNameRaw) || sanitizeInline(project?.userName || ""); const hasArtistName = artistName.length > 0; const { genres = [], tempo = "", mood = "", instruments = [], } = musicConfig || {}; const userStyle = sanitizeInline(coverStyleRaw); // --- 2. Intelligence Visuelle (Mapping) --- // Détermination de l'énergie visuelle const isEnergetic = tempo && /\b(rapid|fast|vite|agité|upbeat|energ|dance|rock|metal)\b/i.test( String(tempo), ); const isDark = mood && /\b(sombre|triste|dark|sad|mélancoli|nuit|night|eerie)\b/i.test( String(mood), ); // Construction de la Palette & Lumière let visualAtmosphere = ""; if (isDark) { visualAtmosphere = "Atmosphere: Cinematic dark lighting, moody shadows, deep contrast. Palette: Midnight blue, obsidian, deep purple, metallic accents."; } else if (isEnergetic) { visualAtmosphere = "Atmosphere: Dynamic lighting, high energy, vibrant saturation. Palette: Neon colors, electric blue, magenta, bright yellow, high contrast."; } else { visualAtmosphere = "Atmosphere: Soft natural lighting, harmonious and ethereal. Palette: Pastel tones, warm gold, soft coral, balanced and elegant colors."; } // Définition du Style de Rendu (Si l'utilisateur est vague, on renforce) let renderingStyle = userStyle ? `Art Style: ${userStyle}` : "Art Style: Digital Art, Mixed Media"; if ( userStyle.toLowerCase().includes("realist") || userStyle.toLowerCase().includes("photo") ) { renderingStyle += ", 8k resolution, highly detailed texture, photorealistic, cinematic depth of field, raytracing."; } else if ( userStyle.toLowerCase().includes("illu") || userStyle.toLowerCase().includes("dessin") ) { renderingStyle += ", vector art, clean lines, professional illustration, flat design or detailed painting."; } else { // Style par défaut "Album Cover" qui marche bien renderingStyle += ", abstract surrealism, conceptual album art, high fidelity, masterpiece."; } // --- 3. Extraction de l'Inspiration (Lyrics) --- // On cherche le REFRAIN en priorité pour l'image, car c'est le cœur visuel const sections = Array.isArray(lyricsRaw) ? lyricsRaw : []; const chorus = sections.find( (s) => s.type === "refrain" || s.type === "chorus", ); const verse = sections.find( (s) => s.type === "couplet" || s.type === "verse", ); // On prend 2 lignes max du refrain, ou du premier couplet const visualHook = (chorus?.lyrics || verse?.lyrics || "") .split("\n") .filter((l) => l.length > 10) // On évite les lignes trop courtes .slice(0, 2) .join(". "); const imageryPrompt = visualHook ? `Visual Inspiration: An artistic interpretation of these lyrics: "${visualHook}".` : "Visual Inspiration: Abstract visual representation of the song's mood."; // --- 4. Construction du Prompt Final (Structure Optimisée Imagen 3) --- const promptParts = [ // Rôle "Design a professional, high-quality music album cover.", // 1. Le Texte (Crucial pour Imagen 3 - Doit être au début ou très clair) `**Typography & Text:**`, `The song title "${titleForPrompt}" must be the CENTERPIECE. Write it in a distinct, artistic font that matches the mood.`, hasArtistName ? `The artist name "${artistName}" must appear smaller, elegant, and legible near the bottom or top.` : "", "Ensure perfect spelling. The text should be integrated into the artwork (e.g., metallic texture, neon glow, or bold cut-out), not just pasted on top.", // 2. Le Visuel `**Visuals:**`, renderingStyle, imageryPrompt, `Subject: A central visual element that represents the song. ${isEnergetic ? "Dynamic composition." : "Balanced, centered composition."}`, // 3. L'Atmosphère (Context from music config) `**Mood & Color:**`, visualAtmosphere, genres.length > 0 ? `Musical Vibe Reference: ${genres.join(", ")}.` : "", // 4. Contraintes Négatives (Phrasées positivement pour l'IA) "**Constraints:**", "Use a square 1:1 aspect ratio.", "Do NOT depict literal musical instruments (like guitars or microphones) unless they are part of a surreal abstract composition.", "No blurry text. No messy borders. No watermarks.", ]; return promptParts.filter(Boolean).join("\n\n"); };