import { NextRequest, NextResponse } from 'next/server'; import { createClient } from '@/lib/supabase/server'; import { resolveActiveTenant, restGet } from '@/lib/tenant-context'; import { isAgencyRole, userRole } from '@/lib/agency'; import { AdDailyRow, KpiWeeklyRow } from '@/lib/metrics'; import { SimChannel, simulateFromTenantMetrics, } from '@/lib/simulate'; export const dynamic = 'force-dynamic'; async function loadTenantMetrics(tenantId: string, agencyView: boolean) { let daily: AdDailyRow[] = []; let weekly: KpiWeeklyRow[] = []; if (agencyView) { const tid = encodeURIComponent(tenantId); const [d, w] = await Promise.all([ restGet( `/rest/v1/ad_daily?tenant_id=eq.${tid}&select=*&order=date.desc&limit=400` ), restGet( `/rest/v1/kpi_weekly?tenant_id=eq.${tid}&select=*&order=week.desc&limit=52` ), ]); daily = d.data || []; weekly = w.data || []; } else { const supabase = await createClient(); const [{ data: d }, { data: w }] = await Promise.all([ supabase .from('ad_daily') .select('*') .order('date', { ascending: false }) .limit(400), supabase .from('kpi_weekly') .select('*') .order('week', { ascending: false }) .limit(52), ]); daily = (d as AdDailyRow[]) || []; weekly = (w as KpiWeeklyRow[]) || []; } return { daily, weekly }; } export async function POST(req: NextRequest) { const supabase = await createClient(); const { data: { user }, } = await supabase.auth.getUser(); if (!user) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } const ctx = await resolveActiveTenant(user); if (!ctx.tenantId || ctx.portfolioWide) { return NextResponse.json( { error: 'Selecciona un cliente en Contexto para simular.' }, { status: 400 } ); } try { const body = await req.json(); const spend = parseFloat(body.spend || 1000); let channel = String(body.channel || 'blended').toLowerCase(); if (channel === 'tiktok') { return NextResponse.json( { error: 'TikTok no está activo aún en este portafolio. Usa Meta, Google o blended.', }, { status: 400 } ); } if (!['meta', 'google', 'blended'].includes(channel)) { channel = 'blended'; } const agency = isAgencyRole(userRole(user)); const { daily, weekly } = await loadTenantMetrics( ctx.tenantId, agency && ctx.viaView ); const sim = simulateFromTenantMetrics({ spend: Number.isFinite(spend) && spend > 0 ? spend : 1000, channel: channel as SimChannel, daily, weekly, }); return NextResponse.json({ ...sim, tenant_label: ctx.label, hint: 'Estimación con CPL, cierre y ticket del cliente en contexto (ad_daily + kpi_weekly).', }); } catch (e: unknown) { const message = e instanceof Error ? e.message : 'Error'; return NextResponse.json({ error: message }, { status: 500 }); } }