import { NextResponse } from 'next/server'; import { createMemberNotificationService } from '@kit/member-management/services'; import { getLogger } from '@kit/shared/logger'; import { getSupabaseServerAdminClient } from '@kit/supabase/server-admin-client'; const CRON_SECRET = process.env.CRON_SECRET; /** * Internal cron endpoint for member scheduled jobs. * Called hourly by pg_cron or external scheduler. * * POST /api/internal/cron/member-jobs * Header: Authorization: Bearer */ export async function POST(request: Request) { const logger = await getLogger(); // Verify cron secret const authHeader = request.headers.get('authorization'); const token = authHeader?.replace('Bearer ', ''); if (!CRON_SECRET || token !== CRON_SECRET) { return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }); } try { const client = getSupabaseServerAdminClient(); const notificationService = createMemberNotificationService(client); // 1. Process pending notification queue const queueResult = await notificationService.processPendingNotifications(); // 2. Run scheduled jobs for all accounts with enabled jobs const { data: accounts } = await (client.from as any)( 'scheduled_job_configs', ) .select('account_id') .eq('is_enabled', true) .or(`next_run_at.is.null,next_run_at.lte.${new Date().toISOString()}`); const uniqueAccountIds = [ ...new Set((accounts ?? []).map((a: any) => a.account_id)), ] as string[]; const jobResults: Record = {}; for (const accountId of uniqueAccountIds) { try { const result = await notificationService.runScheduledJobs(accountId); jobResults[accountId] = result; } catch (e) { logger.error( { accountId, error: e, context: 'cron-member-jobs' }, 'Failed to run jobs for account', ); jobResults[accountId] = { error: e instanceof Error ? e.message : 'Unknown error', }; } } const summary = { timestamp: new Date().toISOString(), queue: queueResult, accounts_processed: uniqueAccountIds.length, jobs: jobResults, }; logger.info( { context: 'cron-member-jobs', ...summary }, 'Member cron jobs completed', ); return NextResponse.json(summary); } catch (err) { logger.error( { error: err, context: 'cron-member-jobs' }, 'Cron job failed', ); return NextResponse.json( { error: 'Internal server error' }, { status: 500 }, ); } }