import { serve } from "https://deno.land/std@0.190.0/http/server.ts"; import { createEdgeFunction, type EdgeFunctionContext } from '../_shared/edgeFunctionWrapper.ts'; import { corsHeaders } from '../_shared/cors.ts'; import { addSpanEvent } from '../_shared/logger.ts'; import { withEdgeRetry } from '../_shared/retryHelper.ts'; interface EscalationRequest { submissionId: string; escalationReason: string; escalatedBy: string; } const handler = async (req: Request, { supabase, span, requestId }: EdgeFunctionContext) => { const { submissionId, escalationReason, escalatedBy }: EscalationRequest = await req.json(); addSpanEvent(span, 'processing_escalation', { submissionId, escalatedBy }); // Fetch submission details const { data: submission, error: submissionError } = await supabase .from('content_submissions') .select('*, profiles:user_id(username, display_name, id)') .eq('id', submissionId) .single(); if (submissionError || !submission) { throw new Error(`Failed to fetch submission: ${submissionError?.message || 'Not found'}`); } // Fetch escalator details const { data: escalator, error: escalatorError } = await supabase .from('profiles') .select('username, display_name') .eq('user_id', escalatedBy) .single(); if (escalatorError) { addSpanEvent(span, 'escalator_profile_fetch_failed', { error: escalatorError.message }); } // Fetch submission items count const { count: itemsCount, error: countError } = await supabase .from('submission_items') .select('*', { count: 'exact', head: true }) .eq('submission_id', submissionId); if (countError) { addSpanEvent(span, 'items_count_fetch_failed', { error: countError.message }); } // Prepare email content const escalatorName = escalator?.display_name || escalator?.username || 'Unknown User'; const submitterName = submission.profiles?.display_name || submission.profiles?.username || 'Unknown User'; const submissionType = submission.submission_type || 'Unknown'; const itemCount = itemsCount || 0; const emailSubject = `🚨 Submission Escalated: ${submissionType} - ID: ${submissionId.substring(0, 8)}`; const emailHtml = `

⚠️ Submission Escalated

Admin review required

Submission ID: ${submissionId}
Submission Type: ${submissionType}
Items Count: ${itemCount}
Submitted By: ${submitterName}
Escalated By: ${escalatorName}
📝 Escalation Reason:

${escalationReason}

Review Submission →
`; const emailText = ` SUBMISSION ESCALATED - Admin Review Required Submission ID: ${submissionId} Submission Type: ${submissionType} Items Count: ${itemCount} Submitted By: ${submitterName} Escalated By: ${escalatorName} Escalation Reason: ${escalationReason} Please review this submission in the admin panel. `; // Send email via ForwardEmail API with retry const forwardEmailApiKey = Deno.env.get('FORWARDEMAIL_API_KEY'); const adminEmail = Deno.env.get('ADMIN_EMAIL_ADDRESS'); const fromEmail = Deno.env.get('FROM_EMAIL_ADDRESS'); if (!forwardEmailApiKey || !adminEmail || !fromEmail) { throw new Error('Email configuration is incomplete. Please check environment variables.'); } addSpanEvent(span, 'sending_escalation_email', { adminEmail }); const emailResult = await withEdgeRetry( async () => { const emailResponse = await fetch('https://api.forwardemail.net/v1/emails', { method: 'POST', headers: { 'Authorization': 'Basic ' + btoa(forwardEmailApiKey + ':'), 'Content-Type': 'application/json', }, body: JSON.stringify({ from: fromEmail, to: adminEmail, subject: emailSubject, html: emailHtml, text: emailText, }), }); if (!emailResponse.ok) { let errorText; try { errorText = await emailResponse.text(); } catch { errorText = 'Unable to parse error response'; } const error = new Error(`Failed to send email: ${emailResponse.status} - ${errorText}`); (error as any).status = emailResponse.status; throw error; } return await emailResponse.json(); }, { maxAttempts: 3, baseDelay: 1500, maxDelay: 10000 }, requestId, 'send-escalation-email' ); addSpanEvent(span, 'email_sent', { emailId: emailResult.id }); // Update submission with escalation status const { error: updateError } = await supabase .from('content_submissions') .update({ escalated: true, escalated_at: new Date().toISOString(), escalated_by: escalatedBy, escalation_reason: escalationReason }) .eq('id', submissionId); if (updateError) { addSpanEvent(span, 'submission_update_failed', { error: updateError.message }); } addSpanEvent(span, 'escalation_notification_complete', { emailId: emailResult.id, submissionId }); return { success: true, message: 'Escalation notification sent successfully', emailId: emailResult.id, }; }; serve(createEdgeFunction({ name: 'send-escalation-notification', requireAuth: false, useServiceRole: true, corsHeaders, enableTracing: true, logRequests: true, }, handler));