import { serve } from "https://deno.land/std@0.168.0/http/server.ts" import { createClient } from "https://esm.sh/@supabase/supabase-js@2" import { JWT } from "https://esm.sh/google-auth-library@8.9.0" const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apiKey, content-type', } serve(async (req) => { // Gestione CORS per sicurezza if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }) } try { // 1. Inizializziamo il client Supabase con i poteri di Service Role (per scavalcare le RLS) const supabaseClient = createClient( Deno.env.get('SUPABASE_URL') ?? '', Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? '' ) // 2. Recuperiamo la chiave di Firebase dai Secrets const firebaseSecret = Deno.env.get('FIREBASE_SERVICE_ACCOUNT') if (!firebaseSecret) throw new Error('Missing FIREBASE_SERVICE_ACCOUNT secret') const credentials = JSON.parse(firebaseSecret) // 3. Prepariamo l'autenticazione OAuth2 per Firebase HTTP v1 const jwtClient = new JWT({ email: credentials.client_email, key: credentials.private_key, scopes: ['https://www.googleapis.com/auth/firebase.messaging'], }) const tokens = await jwtClient.getAccessToken() const fcmAccessToken = tokens.token // 4. Selezioniamo i reminder da inviare (trigger_at passato e non ancora inviati) const { data: reminders, error: fetchError } = await supabaseClient .from('task_reminders') .select('id, task_id, staff_id, channel, tasks(title, description)') .eq('channel', 'push') .eq('is_sent', false) .lte('trigger_at', new Date().toISOString()) if (fetchError) throw fetchError if (!reminders || reminders.length === 0) { return new Response(JSON.stringify({ message: 'Nessun promemoria push da inviare.' }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, }) } // 5. Ciclo sui promemoria per raccogliere i token ed inviare for (const reminder of reminders) { const taskTitle = reminder.tasks?.title || 'Nuovo Task!'; const taskBody = reminder.tasks?.description || 'Hai un task da completare.'; // Preleviamo tutti i dispositivi registrati per questo specifico membro dello staff const { data: devices } = await supabaseClient .from('staff_devices') .select('fcm_token') .eq('staff_id', reminder.staff_id) if (devices && devices.length > 0) { // Spediamo la notifica a OGNI dispositivo associato all'utente for (const device of devices) { try { await fetch( `https://fcm.googleapis.com/v1/projects/${credentials.project_id}/messages:send`, { method: 'POST', headers: { 'Authorization': `Bearer ${fcmAccessToken}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ message: { token: device.fcm_token, notification: { title: taskTitle, body: taskBody, }, data: { click_action: 'FLUTTER_NOTIFICATION_CLICK', taskId: reminder.task_id, // Fondamentale per far scattare il Deep Link all'apertura! }, }, }), } ) } catch (pushErr) { console.error(`Errore invio push al token ${device.fcm_token}:`, pushErr) } } } // 6. Segnamo il reminder come inviato per non riprocessarlo al prossimo giro await supabaseClient .from('task_reminders') .update({ is_sent: true, updated_at: new Date().toISOString() }) .eq('id', reminder.id) } return new Response(JSON.stringify({ success: true, processed: reminders.length }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 200, }) } catch (error) { return new Response(JSON.stringify({ error: error.message }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, status: 500, }) } })