import { NextRequest, NextResponse } from 'next/server'; import { createClient } from '@/lib/supabase/server'; async function requireAdmin(request: NextRequest) { const supabase = await createClient(); const { data: { user } } = await supabase.auth.getUser(); if (!user) return null; const { data: profile } = await supabase .from('user_profiles') .select('role') .eq('id', user.id) .single(); if (!profile || !['administrator', 'admin'].includes(profile.role)) return null; return user; } // POST /api/adops/cron/end-campaigns — daily midnight check export async function POST(request: NextRequest) { const cronSecret = request.headers.get('x-cron-secret'); const isValidCron = cronSecret && cronSecret === process.env.CRON_SECRET; if (!isValidCron) { const user = await requireAdmin(request); if (!user) return NextResponse.json({ error: 'Not found' }, { status: 404 }); } const supabase = await createClient(); const today = new Date().toISOString().split('T')[0]; // Find campaigns that should end today or earlier const { data: expiredCampaigns } = await supabase .from('ad_campaigns') .select('*') .eq('status', 'active') .lte('end_date', today); if (!expiredCampaigns?.length) { return NextResponse.json({ success: true, ended: 0 }); } let ended = 0; for (const campaign of expiredCampaigns) { await supabase .from('ad_campaigns') .update({ status: 'ended', deactivated_at: new Date().toISOString(), updated_at: new Date().toISOString(), }) .eq('id', campaign.id); // Send end notification try { const { sendToJeffAndRyan, sendToRyanOnly } = await import('@/lib/adops/adOpsEmailSender'); const { campaignEndedEmailJeff, campaignEndedEmailRyan } = await import('@/lib/adops/emailTemplates'); const jeffEmail = campaignEndedEmailJeff({ clientName: campaign.client_name, publication: campaign.publication_id, endDate: campaign.end_date, impressions: campaign.impressions || 0, clicks: campaign.clicks || 0, ctr: campaign.ctr || 0, campaignId: campaign.id, }); await sendToJeffAndRyan({ subject: jeffEmail.subject, html: jeffEmail.html }); if (campaign.agreed_rate) { const ryanEmail = campaignEndedEmailRyan({ clientName: campaign.client_name, publication: campaign.publication_id, endDate: campaign.end_date, impressions: campaign.impressions || 0, clicks: campaign.clicks || 0, ctr: campaign.ctr || 0, campaignId: campaign.id, agreedRate: campaign.agreed_rate, invoiceId: campaign.mooninvoice_invoice_id, invoiceStatus: 'sent', }); await sendToRyanOnly({ subject: ryanEmail.subject, html: ryanEmail.html }); } } catch (err: any) { console.error('[Cron] Email error for campaign', campaign.id, err.message); } ended++; } return NextResponse.json({ success: true, ended }); }