import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.45.0' const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', } const SOURCE_TYPE_LABELS: Record = { public_form: 'Public form submission', client_request: 'Client request', homeowner_ticket: 'Homeowner ticket', violation_response: 'Violation response', registration_request: 'Registration request', } const SOURCE_TYPE_LINKS: Record = { public_form: '/dashboard/form-inbox', client_request: '/dashboard/client-requests', homeowner_ticket: '/dashboard/form-inbox', violation_response: '/dashboard/form-inbox', registration_request: '/dashboard/form-inbox', } Deno.serve(async (req) => { if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders }) try { const { inbox_id } = await req.json() if (!inbox_id) { return new Response(JSON.stringify({ error: 'inbox_id required' }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }) } const supabase = createClient( Deno.env.get('SUPABASE_URL')!, Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!, ) // Fetch the inbox entry const { data: inbox, error: inboxError } = await supabase .from('form_inbox') .select('*') .eq('id', inbox_id) .single() if (inboxError || !inbox) { console.error('Inbox lookup failed:', inboxError) return new Response(JSON.stringify({ error: 'inbox entry not found' }), { status: 404, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }) } const sourceLabel = SOURCE_TYPE_LABELS[inbox.source_type] || 'Form submission' const link = SOURCE_TYPE_LINKS[inbox.source_type] || '/dashboard/form-inbox' // Get admin + manager user IDs const { data: roleRows, error: roleError } = await supabase .from('user_roles') .select('user_id') .in('role', ['admin', 'manager']) if (roleError) { console.error('Role lookup failed:', roleError) return new Response(JSON.stringify({ error: 'failed to fetch staff' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }) } const userIds = Array.from(new Set((roleRows || []).map((r) => r.user_id).filter(Boolean))) if (userIds.length === 0) { return new Response(JSON.stringify({ ok: true, notified: 0 }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }) } // Insert in-app notifications for every staff user const notificationRows = userIds.map((uid) => ({ user_id: uid, type: 'form_submission_received', title: `New ${sourceLabel.toLowerCase()}`, message: `${inbox.submitter_name || 'Someone'} submitted: ${inbox.title}`, related_item_id: inbox.id, related_item_type: 'form_inbox', link, })) const { error: notifError } = await supabase .from('in_app_notifications') .insert(notificationRows) if (notifError) console.error('Notification insert error:', notifError) // Look up staff emails from auth.users const { data: authData, error: authError } = await supabase.auth.admin.listUsers({ page: 1, perPage: 1000, }) if (authError) { console.error('Auth list failed:', authError) } const staffEmails = (authData?.users || []) .filter((u) => userIds.includes(u.id) && u.email) .map((u) => ({ id: u.id, email: u.email as string })) const baseUrl = Deno.env.get('SUPABASE_URL') || '' const projectId = baseUrl.replace('https://', '').split('.')[0] const fullLink = `https://avria.cloud${link}` let emailsSent = 0 let emailsFailed = 0 for (const staff of staffEmails) { try { const { error: emailError } = await supabase.functions.invoke( 'send-transactional-email', { body: { templateName: 'ticket-submitted', recipientEmail: staff.email, idempotencyKey: `form-inbox-${inbox.id}-${staff.id}`, templateData: { recipientName: '', homeownerName: inbox.submitter_name || 'Anonymous', ticketTitle: inbox.title, category: sourceLabel, priority: '', summary: inbox.summary || '', link: fullLink, }, }, }, ) if (emailError) { emailsFailed++ console.error(`Email to ${staff.email} failed:`, emailError) } else { emailsSent++ } } catch (e) { emailsFailed++ console.error(`Email exception for ${staff.email}:`, e) } } return new Response( JSON.stringify({ ok: true, notified: userIds.length, emails_sent: emailsSent, emails_failed: emailsFailed, }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }, ) } catch (e) { console.error('notify-staff-new-form error:', e) return new Response(JSON.stringify({ error: String(e) }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }) } })