import { createClient } from 'npm:@supabase/supabase-js@2'
import { JWT } from 'npm:google-auth-library@9'
import serviceAccount from './service-account.json' with { type: 'json' }

// 1. MUST DEFINE CORS HEADERS FOR CLIENT INVOCATION
const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
}

interface ClientPayload {
  user_ids: string[]
  tokens?: string[]
  title: string
  body: string
  data: Record<string, string>
}

const supabase = createClient(
  Deno.env.get('SUPABASE_URL')!,
  Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)

Deno.serve(async (req) => {
  // 2. INTERCEPT CORS PREFLIGHT REQUEST
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  try {
    const payload: ClientPayload = await req.json()

    // Ensure we have users to send to
    if (!payload.user_ids || payload.user_ids.length === 0) {
      return new Response('No user_ids provided', { 
        status: 400, 
        headers: corsHeaders 
      })
    }

    // Optional Idempotency (if you pass notification_id inside the data payload)
    if (payload.data && payload.data.notification_id) {
      const { data: markData, error: markErr } = await supabase
        .rpc('try_mark_notification_pushed', { p_notification_id: payload.data.notification_id })
      
      if (markData === false) {
        console.log('Notification already pushed, skipping:', payload.data.notification_id)
        return new Response('Already pushed', { status: 200, headers: corsHeaders })
      }
    }

    // 3. Get all tokens for these users using the .in() filter
    const { data: tokenData, error } = await supabase
      .from('fcm_tokens')
      .select('token')
      .in('user_id', payload.user_ids)

    if (error || !tokenData || tokenData.length === 0) {
      console.log('No active FCM tokens found for users:', payload.user_ids)
      return new Response('No tokens', { status: 200, headers: corsHeaders })
    }

    // Auth with Google
    const accessToken = await getAccessToken({
      clientEmail: serviceAccount.client_email,
      privateKey: serviceAccount.private_key,
    })

    // 4. Dedupe tokens and send concurrently
    const uniqueTokens = Array.from(new Set(tokenData.map((r: any) => r.token)));
    
    const sendPromises = uniqueTokens.map(async (token) => {
      const res = await fetch(
        `https://fcm.googleapis.com/v1/projects/${serviceAccount.project_id}/messages:send`,
        {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            Authorization: `Bearer ${accessToken}`,
          },
          body: JSON.stringify({
            message: {
              token,
              // Send Data-Only payload so Flutter handles the sound/UI
              data: {
                title: payload.title,
                body: payload.body,
                ...payload.data // Merges ticket_id, task_id, type, etc.
              },
              android: {
                priority: 'high',
              },
              apns: {
                payload: {
                  aps: {
                    sound: 'tasq_notification.wav',
                    contentAvailable: 1,
                  },
                },
              },
            },
          }),
        }
      )

      let resData: any = null
      try {
        const text = await res.text()
        if (text && text.length > 0) {
          try {
            resData = JSON.parse(text)
          } catch (parseErr) {
            resData = { rawText: text }
          }
        }
      } catch (readErr) {
        console.warn('Failed to read FCM response body', { token, err: readErr })
      }

      // Cleanup dead tokens
      const isUnregistered = !!(
        resData &&
        (
          resData.error?.details?.[0]?.errorCode === 'UNREGISTERED' ||
          (typeof resData.error?.message === 'string' && resData.error.message.toLowerCase().includes('unregistered')) ||
          (typeof resData.rawText === 'string' && resData.rawText.toLowerCase().includes('unregistered'))
        )
      )

      if (isUnregistered) {
        console.log(`Dead token detected. Removing from DB: ${token}`)
        await supabase.from('fcm_tokens').delete().eq('token', token)
      }

      return { token, status: res.status, response: resData }
    })

    const results = await Promise.all(sendPromises)

    // 5. MUST ATTACH CORS HEADERS TO SUCCESS RESPONSE
    return new Response(JSON.stringify(results), {
      headers: { ...corsHeaders, 'Content-Type': 'application/json' },
    })
    
  } catch (err) {
    console.error('FCM Error:', err)
    // MUST ATTACH CORS HEADERS TO ERROR RESPONSE
    return new Response(JSON.stringify({ error: String(err) }), { 
      status: 500, 
      headers: corsHeaders 
    })
  }
})

// JWT helper (unchanged)
const getAccessToken = ({
  clientEmail,
  privateKey,
}: {
  clientEmail: string
  privateKey: string
}): Promise<string> => {
  return new Promise((resolve, reject) => {
    const jwtClient = new JWT({
      email: clientEmail,
      key: privateKey,
      scopes: ['https://www.googleapis.com/auth/firebase.messaging'],
    })
    jwtClient.authorize((err, tokens) => {
      if (err) {
        reject(err)
        return
      }
      resolve(tokens!.access_token!)
    })
  })
}