import { NextRequest, NextResponse } from 'next/server'; interface ResolvedMotorcycleImage { imageUrl: string; caption: string; source: 'google' | 'curated' | 'wikimedia' | 'wikipedia'; attribution: string; } // Curated high-resolution stock photography for flagship motorcycles const CURATED_IMAGES: Record = { 'yamaha_yzf-r6_2001': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/e/e0/2001_Yamaha_YZFR600.jpg/960px-2001_Yamaha_YZFR600.jpg', caption: '2001 Yamaha YZF-R6 (5EB)', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, 'yamaha_yzf-r6': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/d/dd/Yamaha_YZF-R6_Cropped.jpg/960px-Yamaha_YZF-R6_Cropped.jpg', caption: 'Yamaha YZF-R6 Supersport', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, 'ducati_panigale-v4-s': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/a/a7/Ducati_Panigale_V4_S_Corse.jpg/960px-Ducati_Panigale_V4_S_Corse.jpg', caption: 'Ducati Panigale V4 S Corse', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, 'ducati_panigale-v4': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/a/a8/Ducati_Panigale_V4_-_Tuning_World_Bodensee_2018%2C_Friedrichshafen_%28OW1A0484%29.jpg/3840px-Ducati_Panigale_V4_-_Tuning_World_Bodensee_2018%2C_Friedrichshafen_%28OW1A0484%29.jpg', caption: 'Ducati Panigale V4', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, 'bmw_s1000rr': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/a/a0/2022-05_BMW_M_Motorrad_S1000RR.jpg/960px-2022-05_BMW_M_Motorrad_S1000RR.jpg', caption: 'BMW S1000RR Superbike', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, 'honda_cbr600rr': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/6/64/2006HondaCBR600RR-001.jpg/960px-2006HondaCBR600RR-001.jpg', caption: 'Honda CBR600RR', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, 'kawasaki_ninja-zx-6r': { imageUrl: 'https://thumb.wikimedia.org/wikipedia/commons/thumb/9/93/2009_Kawasaki_Ninja_ZX-6R_in_white.jpg/960px-2009_Kawasaki_Ninja_ZX-6R_in_white.jpg', caption: 'Kawasaki Ninja ZX-6R', source: 'curated', attribution: 'Wikimedia Commons / CC BY', }, }; function normalizeKey(make: string, model: string, year?: number): string { const normMake = make.toLowerCase().replace(/[^a-z0-9]/g, ''); const normModel = model.toLowerCase().replace(/standard/g, '').replace(/[^a-z0-9]/g, ''); return year ? `${normMake}_${normModel}_${year}` : `${normMake}_${normModel}`; } export async function GET(request: NextRequest) { const { searchParams } = new URL(request.url); const make = (searchParams.get('make') || '').trim(); const rawModel = (searchParams.get('model') || '').trim(); const yearParam = searchParams.get('year'); const year = yearParam ? parseInt(yearParam, 10) : undefined; if (!make && !rawModel) { return NextResponse.json({ error: 'Make and model are required' }, { status: 400 }); } // Clean model name (remove "Standard", "Base", etc.) const cleanModel = rawModel .replace(/\bstandard\b/gi, '') .replace(/\bbase\b/gi, '') .trim(); // Tier 1: Check curated exact and model cache if (year) { const exactCurated = CURATED_IMAGES[normalizeKey(make, cleanModel, year)]; if (exactCurated) { return NextResponse.json(exactCurated, { headers: { 'Cache-Control': 'public, s-maxage=604800, stale-while-revalidate=86400' }, }); } } const modelCurated = CURATED_IMAGES[normalizeKey(make, cleanModel)] || CURATED_IMAGES[cleanModel.toLowerCase().replace(/[^a-z0-9]/g, '')]; if (modelCurated) { return NextResponse.json(modelCurated, { headers: { 'Cache-Control': 'public, s-maxage=604800, stale-while-revalidate=86400' }, }); } // Tier 2: Google Custom Search API (if configured in environment) const googleKey = process.env.GOOGLE_SEARCH_API_KEY; const googleCx = process.env.GOOGLE_SEARCH_ENGINE_ID; if (googleKey && googleCx) { try { const q = [year, make, cleanModel, 'motorcycle stock photo'].filter(Boolean).join(' '); const googleUrl = `https://www.googleapis.com/customsearch/v1?key=${encodeURIComponent( googleKey )}&cx=${encodeURIComponent(googleCx)}&q=${encodeURIComponent(q)}&searchType=image&num=3&safe=active`; const gRes = await fetch(googleUrl, { next: { revalidate: 604800 } }); if (gRes.ok) { const gData = await gRes.json(); const firstItem = gData.items?.[0]; if (firstItem?.link) { const result: ResolvedMotorcycleImage = { imageUrl: firstItem.link, caption: firstItem.title || `${year ? year + ' ' : ''}${make} ${cleanModel}`, source: 'google', attribution: firstItem.displayLink || 'Google Image Search', }; return NextResponse.json(result, { headers: { 'Cache-Control': 'public, s-maxage=604800, stale-while-revalidate=86400' }, }); } } } catch (err) { console.warn('Google Custom Search API error, falling back:', err); } } // Tier 3: Wikimedia Commons API Search const searchQueries: string[] = []; if (year && year > 1900) { searchQueries.push(`${year} ${make} ${cleanModel}`); } searchQueries.push(`${make} ${cleanModel}`); searchQueries.push(`${cleanModel}`); for (const query of searchQueries) { try { const commonsUrl = `https://commons.wikimedia.org/w/api.php?action=query&format=json&generator=search&gsrnamespace=6&gsrsearch=${encodeURIComponent( query )}&gsrlimit=6&prop=imageinfo&iiprop=url|extmetadata&iiurlwidth=960`; const cRes = await fetch(commonsUrl, { headers: { 'User-Agent': 'MotorSignal/1.0 (https://motorsignal.app; contact@motorsignal.app)', }, next: { revalidate: 604800 }, }); if (cRes.ok) { const cData = await cRes.json(); const pages = cData.query?.pages; if (pages) { for (const rawPage of Object.values(pages) as any[]) { const title = (rawPage.title || '').toLowerCase(); if ( title.includes('logo') || title.includes('icon') || title.includes('diagram') || title.includes('flag') || title.includes('badge') ) { continue; } const info = rawPage.imageinfo?.[0]; const imgUrl = info?.thumburl || info?.url; if (imgUrl && /\.(jpe?g|png|webp)/i.test(imgUrl)) { const result: ResolvedMotorcycleImage = { imageUrl: imgUrl, caption: `${year ? year + ' ' : ''}${make} ${cleanModel}`, source: 'wikimedia', attribution: 'Wikimedia Commons / CC', }; return NextResponse.json(result, { headers: { 'Cache-Control': 'public, s-maxage=604800, stale-while-revalidate=86400', }, }); } } } } } catch (err) { console.warn('Wikimedia query error:', err); } } // Tier 4: Wikipedia Lead Summary Image const wikiTitles = [ `${make} ${cleanModel}`, cleanModel, `${make}_${cleanModel}`.replace(/\s+/g, '_'), ]; for (const title of wikiTitles) { try { const wikiUrl = `https://en.wikipedia.org/api/rest_v1/page/summary/${encodeURIComponent(title)}`; const wRes = await fetch(wikiUrl, { headers: { 'User-Agent': 'MotorSignal/1.0 (https://motorsignal.app; contact@motorsignal.app)', }, next: { revalidate: 604800 }, }); if (wRes.ok) { const wData = await wRes.json(); const img = wData.originalimage?.source || wData.thumbnail?.source; if (img && !img.includes('disambig') && !img.includes('Question_book')) { const result: ResolvedMotorcycleImage = { imageUrl: img, caption: wData.title || `${year ? year + ' ' : ''}${make} ${cleanModel}`, source: 'wikipedia', attribution: 'Wikipedia Lead Reference', }; return NextResponse.json(result, { headers: { 'Cache-Control': 'public, s-maxage=604800, stale-while-revalidate=86400', }, }); } } } catch (err) { console.warn('Wikipedia query error:', err); } } return NextResponse.json({ error: 'No stock photo found for this motorcycle' }, { status: 404 }); }