// Local SVG-based image generator as fallback for Nano-banana API issues
// Generate creative theme elements based on joke content
function generateThemeElements(jokeText: string, topic: string): any {
const elements: any = {
backgroundStyle: 'linear-gradient',
colors: ['#667eea', '#764ba2'],
icons: ['π', 'π€£', 'π', 'πͺ'],
decorations: [],
burstElements: []
};
// Programming jokes
if (topic === 'programming' || jokeText.includes('code') || jokeText.includes('programming') || jokeText.includes('developer') || jokeText.includes('front-end') || jokeText.includes('backend')) {
elements.colors = ['#00BCD4', '#0097A7'];
elements.icons = ['π»', 'β‘', 'π§', 'π'];
elements.decorations = ['{"x": 150, "y": 200, "size": 20, "color": "#00BCD4", "icon": "π»"}', '{"x": 874, "y": 350, "size": 25, "color": "#0097A7", "icon": "β‘"}'];
elements.backgroundStyle = 'programming';
}
// Cat/Animal jokes
else if (topic === 'cats' || topic === 'animals' || jokeText.includes('cat') || jokeText.includes('pet') || jokeText.includes('animal')) {
elements.colors = ['#FFB74D', '#FF9800'];
elements.icons = ['π±', 'πΎ', 'πΈ', 'π²'];
elements.decorations = ['{"x": 150, "y": 250, "size": 30, "color": "#FFB74D", "icon": "π±"}', '{"x": 874, "y": 400, "size": 35, "color": "#FF9800", "icon": "πΎ"}'];
elements.backgroundStyle = 'animals';
}
// Food jokes
else if (topic === 'food' || jokeText.includes('food') || jokeText.includes('eat') || jokeText.includes('pizza') || jokeText.includes('cheese')) {
elements.colors = ['#4CAF50', '#388E3C'];
elements.icons = ['π', 'π', 'π', 'β€οΈ'];
elements.decorations = ['{"x": 150, "y": 300, "size": 40, "color": "#4CAF50", "icon": "π"}', '{"x": 874, "y": 450, "size": 45, "color": "#388E3C", "icon": "π"}'];
elements.backgroundStyle = 'food';
}
// Default/General jokes
else {
elements.decorations = ['{"x": 150, "y": 175, "size": 25, "color": "#FFD700", "icon": "β"}', '{"x": 874, "y": 175, "size": 30, "color": "#FF6B35", "icon": "π"}'];
}
// Add burst elements for creativity
elements.burstElements = [
'{"x": 100, "y": 300, "size": 15, "color": "#FF69B4"}',
'{"x": 924, "y": 300, "size": 20, "color": "#87CEEB"}',
'{"x": 200, "y": 700, "size": 25, "color": "#98FB98"}',
'{"x": 824, "y": 700, "size": 18, "color": "#DDA0DD"}'
];
return elements;
}
export function generateLocalDadJokeImage(joke: string, topic: string = 'general', rating: string = 'PG-13'): string {
// Escape HTML special characters for SVG
const escapeHtml = (text: string) => {
return text
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
};
const safeJoke = escapeHtml(joke);
const safeTopic = escapeHtml(topic);
const safeRating = escapeHtml(rating);
// Generate creative theme elements based on joke content
const jokeText = joke.toLowerCase();
const themeElements = generateThemeElements(jokeText, topic);
// Rating badge colors and icons
const ratingInfo = {
PG: { color: '#4CAF50', icon: 'π', text: 'PG - Family Friendly' },
'PG-13': { color: '#FF9800', icon: 'π', text: 'PG-13 - Mild Adult Humor' },
'R': { color: '#F44336', icon: 'π', text: 'R - Mature Audiences' }
};
const currentRating = ratingInfo[rating as keyof typeof ratingInfo] || ratingInfo['PG-13'];
// Create SVG with Dad Joke visualization
const svgContent = `
<svg width="1024" height="1024" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="bgGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:${themeElements.colors[0]};stop-opacity:1" />
<stop offset="100%" style="stop-color:${themeElements.colors[1]};stop-opacity:1" />
</linearGradient>
<linearGradient id="cardGradient" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#ffffff;stop-opacity:1" />
<stop offset="100%" style="stop-color:#f8f9fa;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Background -->
<rect width="1024" height="1024" fill="url(#bgGradient)"/>
<!-- Main Card -->
<rect x="50" y="50" width="924" height="924" rx="30" ry="30" fill="url(#cardGradient)" stroke="#ddd" stroke-width="2"/>
<!-- Title with Theme Icons -->
<text x="512" y="120" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="48" font-weight="bold" fill="#333">
${themeElements.icons[0]} Dad Joke Visualizer ${themeElements.icons[1]}
</text>
<!-- Topic Badge with Theme Colors -->
<rect x="312" y="150" width="200" height="50" rx="25" ry="25" fill="${themeElements.colors[0]}" stroke="${themeElements.colors[1]}" stroke-width="2"/>
<text x="412" y="185" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="24" font-weight="bold" fill="white">
${safeTopic.toUpperCase()}
</text>
<!-- Rating Badge -->
<rect x="532" y="150" width="200" height="50" rx="25" ry="25" fill="${currentRating.color}" stroke="#333" stroke-width="2"/>
<text x="632" y="185" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="20" font-weight="bold" fill="white">
${currentRating.icon} ${safeRating}
</text>
<!-- Joke Container with Theme Border -->
<rect x="100" y="250" width="824" height="400" rx="20" ry="20" fill="#fff" stroke="${themeElements.colors[0]}" stroke-width="4"/>
<!-- Joke Text -->
<text x="512" y="350" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="28" fill="#333" text-align="center">
<tspan x="512" dy="0">"${safeJoke}"</tspan>
</text>
<!-- Theme-specific Decorations -->
${themeElements.decorations.map((decor: string) => {
const d = JSON.parse(decor);
return `<circle cx="${d.x}" cy="${d.y}" r="${d.size}" fill="${d.color}" opacity="0.8"/><text x="${d.x}" y="${d.y + 5}" text-anchor="middle" font-size="${d.size}" font-family="emoji">${d.icon}</text>`;
}).join('')}
<!-- Enhanced Reaction with Theme Colors -->
<rect x="350" y="550" width="324" height="100" rx="50" ry="50" fill="${themeElements.colors[0]}" stroke="${themeElements.colors[1]}" stroke-width="3"/>
<text x="512" y="585" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="28" font-weight="bold" fill="white">
${themeElements.icons[2]} LOL!! ${themeElements.icons[3]}
</text>
<text x="512" y="615" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="18" fill="white">
Dad Joke Approved!
</text>
<!-- Footer -->
<text x="512" y="750" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="24" fill="#666">
Generated by Dad Joke Visualizer
</text>
<text x="512" y="780" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="16" fill="#999">
πͺ Made for Dad Joke enthusiasts everywhere! πͺ
</text>
<text x="512" y="810" text-anchor="middle" font-family="Comic Sans MS, cursive, sans-serif" font-size="14" fill="orange">
Note: Enhanced SVG mode (Nano-banana experiencing SSL issues)
</text>
<!-- Enhanced Border Accents -->
<rect x="70" y="70" width="884" height="4" fill="${themeElements.colors[0]}" opacity="0.8"/>
<rect x="70" y="950" width="884" height="4" fill="${themeElements.colors[0]}" opacity="0.8"/>
<rect x="70" y="70" width="4" height="884" fill="${themeElements.colors[0]}" opacity="0.8"/>
<rect x="950" y="70" width="4" height="884" fill="${themeElements.colors[0]}" opacity="0.8"/>
</svg>
`;
// Convert SVG to data URL
const base64 = Buffer.from(svgContent.trim()).toString('base64');
return `data:image/svg+xml;base64,${base64}`;
}
export function generateDadJokeImageWithLocalFallback(joke: string, topic: string = 'general', rating: string = 'PG-13'): string {
console.log(`π¨ Generating local SVG Dad Joke visualization... (${rating} rated)`);
console.log('β
No external API dependencies - pure local generation!');
return generateLocalDadJokeImage(joke, topic, rating);
}