import { NextRequest, NextResponse } from 'next/server'; import { createMetaMCPClient } from '@/lib/mcp/client'; import { getCampaignDetails } from '@/lib/mcp/tools'; import { getAccessToken } from '@/lib/auth/session'; import { getAIClient } from '@/lib/ai/client'; const ANALYSIS_MODEL = 'gpt-5.4-mini'; export async function POST(request: NextRequest) { try { const token = await getAccessToken(); if (!token) { return NextResponse.json({ success: false, error: 'Not authenticated' }, { status: 401 }); } const { campaignId } = await request.json(); if (!campaignId) { return NextResponse.json({ success: false, error: 'Campaign ID required' }, { status: 400 }); } const client = await createMetaMCPClient(token); let campaignData: any; try { const result = await getCampaignDetails(client, campaignId); campaignData = Array.isArray(result) ? result[0] : result; } finally { await client.close(); } if (!campaignData || !campaignData.id) { return NextResponse.json({ success: false, error: 'Campaign not found on Meta' }, { status: 404 }); } // Prepare data for the AI model const insights = campaignData.insights?.data?.[0] || {}; const adsets = campaignData.adsets?.data || []; let totalSpend = parseFloat(insights.spend || '0'); let roas = parseFloat(insights.purchase_roas?.[0]?.value || '0'); // Extract Ads & Creatives const adsToAnalyze = []; for (const adset of adsets) { const ads = adset.ads?.data || []; for (const ad of ads) { const adInsights = ad.insights?.data?.[0] || {}; const creative = ad.creative || {}; // Extract texts let body = creative.body || ''; let title = creative.title || ''; let imageUrl = creative.image_url || creative.thumbnail_url || ''; // Handle asset_feed_spec (Dynamic Creative) if (creative.asset_feed_spec) { const feed = creative.asset_feed_spec; body = feed.bodies?.map((b: any) => b.text).join(' | ') || body; title = feed.titles?.map((t: any) => t.text).join(' | ') || title; if (feed.images && feed.images.length > 0) { imageUrl = feed.images[0].url || feed.images[0].thumbnail_url || imageUrl; // Just take the first image for now } } adsToAnalyze.push({ ad_name: ad.name, spend: adInsights.spend || '0', roas: adInsights.purchase_roas?.[0]?.value || '0', cpc: adInsights.cpc || '0', ctr: adInsights.ctr || '0', body, title, image_url: imageUrl, }); } } const openai = getAIClient(); const prompt = ` Você é um Especialista Sênior em Tráfego Pago e Copywriting. Abaixo estão os dados reais extraídos de uma Campanha no Facebook Ads. Por favor, faça uma auditoria completa. DADOS DA CAMPANHA: Nome: ${campaignData.name} Gasto Total (30d): R$ ${totalSpend} ROAS Total: ${roas} ANÚNCIOS ATIVOS (CRIATIVOS E MÉTRICAS): ${JSON.stringify(adsToAnalyze, null, 2)} Sua tarefa é retornar um JSON ESTRITAMENTE VÁLIDO com a seguinte estrutura de análise (NÃO adicione formatação markdown \`\`\`json no início ou no fim). Importante: Para as análises e ações, retorne um ARRAY de strings (cada string é um bullet point claro, curto e direto). { "diagnostico_geral": "Um parágrafo forte resumindo a saúde da campanha.", "analise_copy": ["Ponto 1 sobre a copy...", "Sugestão de melhoria de texto..."], "analise_imagem": ["O que achei do visual...", "Ideia de novo formato (vídeo/carrossel)..."], "analise_metricas": ["ROAS está X...", "CPA está Y..."], "acao_recomendada": ["Ação imediata 1 (ex: Pausar Ad X)...", "Ação 2 (ex: Testar público Y)..."], "nova_estrategia_sugerida": { "nicho_sugerido": "ex: ecommerce, info_produto, negocios_locais, advogado...", "produto_foco": "Nome ou tipo do produto que deve ser focado na próxima campanha", "publico_alvo": "Qual deve ser o público alvo ideal", "angulos_de_venda": ["Ângulo 1", "Ângulo 2"] } } `; const completion = await openai.chat.completions.create({ model: ANALYSIS_MODEL, messages: [{ role: 'user', content: prompt }], response_format: { type: 'json_object' }, }); const textRes = completion.choices[0]?.message?.content || ''; let jsonRes; try { // Clean up markdown fences if model ignored instruction const cleanedText = textRes.replace(/^```json/m, '').replace(/```$/m, '').trim(); jsonRes = JSON.parse(cleanedText); } catch (e) { console.error('Failed to parse AI response:', textRes); return NextResponse.json({ success: false, error: 'Failed to parse AI response' }, { status: 500 }); } return NextResponse.json({ success: true, data: { campaign_metrics: { spend: totalSpend, roas }, ads_count: adsToAnalyze.length, ads: adsToAnalyze, analysis: jsonRes } }); } catch (error) { console.error('[Analysis] API Error:', error); return NextResponse.json( { success: false, error: error instanceof Error ? error.message : 'Unknown error' }, { status: 500 } ); } }