/*
|--------------------------------------------------------------------------
| Agência PSI — Edge Function: process-notification-queue
|--------------------------------------------------------------------------
| Processa a notification_queue para channel = 'whatsapp' via Evolution API.
|
| Fluxo por item:
|   1. Busca pendentes (channel='whatsapp', status='pendente', scheduled_at <= now)
|   2. Marca como 'processando' (lock otimista)
|   3. Busca credenciais Evolution API em notification_channels
|   4. Resolve template: tenant → global fallback
|   5. Renderiza variáveis {{var}}
|   6. Envia via Evolution API (sendText)
|   7. Atualiza queue + insere notification_logs
|   8. Em erro: retry com backoff ou marca 'falhou'
|--------------------------------------------------------------------------
*/

import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

const corsHeaders = {
  'Access-Control-Allow-Origin':  '*',
  'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
  'Access-Control-Allow-Methods': 'POST, OPTIONS',
}

// ── Template renderer ──────────────────────────────────────────

function renderTemplate(template: string, variables: Record<string, unknown>): string {
  if (!template) return ''
  return template.replace(/\{\{([\w.]+)\}\}/g, (_, key) => {
    const val = variables[key]
    return val !== undefined && val !== null ? String(val) : ''
  })
}

// ── Evolution API sender ───────────────────────────────────────

interface EvolutionCredentials {
  api_url: string
  api_key: string
  instance_name: string
}

async function sendWhatsapp(
  credentials: EvolutionCredentials,
  recipient: string,
  message: string
): Promise<{ messageId?: string; status: string }> {
  const url = `${credentials.api_url}/message/sendText/${credentials.instance_name}`

  const res = await fetch(url, {
    method: 'POST',
    headers: {
      'apikey': credentials.api_key,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      number: recipient,
      text: message,
    }),
  })

  const data = await res.json()

  if (!res.ok) {
    throw new Error(data?.message || `Evolution API error ${res.status}`)
  }

  return {
    messageId: data?.key?.id || data?.messageId || null,
    status: 'sent',
  }
}

// ── Main handler ───────────────────────────────────────────────

Deno.serve(async (req: Request) => {
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

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

  const now = new Date().toISOString()

  // 1. Busca itens pendentes de WhatsApp
  const { data: items, error: fetchErr } = await supabase
    .from('notification_queue')
    .select('*')
    .eq('channel', 'whatsapp')
    .eq('status', 'pendente')
    .lte('scheduled_at', now)
    .lt('attempts', 5)
    .order('scheduled_at', { ascending: true })
    .limit(20)

  if (fetchErr) {
    return new Response(
      JSON.stringify({ error: fetchErr.message }),
      { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
  }

  if (!items?.length) {
    return new Response(
      JSON.stringify({ message: 'Nenhum WhatsApp na fila', processed: 0 }),
      { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
    )
  }

  const results: Array<{ id: string; status: string; error?: string }> = []

  // Cache de credenciais por owner para evitar queries repetidas
  const credentialsCache = new Map<string, EvolutionCredentials | null>()

  for (const item of items) {
    // 2. Lock otimista
    const { error: lockErr } = await supabase
      .from('notification_queue')
      .update({ status: 'processando', attempts: item.attempts + 1 })
      .eq('id', item.id)
      .eq('status', 'pendente')

    if (lockErr) {
      results.push({ id: item.id, status: 'skip', error: 'lock failed' })
      continue
    }

    try {
      // 3. Busca credenciais Evolution API (com cache)
      let credentials = credentialsCache.get(item.owner_id)

      if (credentials === undefined) {
        const { data: channel } = await supabase
          .from('notification_channels')
          .select('credentials')
          .eq('owner_id', item.owner_id)
          .eq('channel', 'whatsapp')
          .eq('is_active', true)
          .is('deleted_at', null)
          .maybeSingle()

        // Fallback: busca por tenant_id
        if (!channel?.credentials && item.tenant_id) {
          const { data: tenantChannel } = await supabase
            .from('notification_channels')
            .select('credentials')
            .eq('tenant_id', item.tenant_id)
            .eq('channel', 'whatsapp')
            .eq('is_active', true)
            .is('deleted_at', null)
            .maybeSingle()

          credentials = tenantChannel?.credentials as EvolutionCredentials | null
        } else {
          credentials = channel?.credentials as EvolutionCredentials | null
        }

        credentialsCache.set(item.owner_id, credentials ?? null)
      }

      if (!credentials) {
        throw new Error('Canal WhatsApp não encontrado ou inativo para este owner')
      }

      // 4. Resolve template: tenant → global fallback
      let templateBody: string | null = null

      const { data: tenantTpl } = await supabase
        .from('notification_templates')
        .select('body_text, is_active')
        .eq('tenant_id', item.tenant_id)
        .eq('key', item.template_key)
        .eq('channel', 'whatsapp')
        .eq('is_active', true)
        .is('deleted_at', null)
        .maybeSingle()

      if (tenantTpl) {
        templateBody = tenantTpl.body_text
      } else {
        const { data: globalTpl } = await supabase
          .from('notification_templates')
          .select('body_text')
          .is('tenant_id', null)
          .eq('key', item.template_key)
          .eq('channel', 'whatsapp')
          .eq('is_default', true)
          .eq('is_active', true)
          .is('deleted_at', null)
          .maybeSingle()

        templateBody = globalTpl?.body_text || null
      }

      if (!templateBody) {
        throw new Error(`Template WhatsApp não encontrado: ${item.template_key}`)
      }

      // 5. Renderiza variáveis
      const vars = item.resolved_vars || {}
      const message = renderTemplate(templateBody, vars)

      // 6. Envia via Evolution API
      const sendResult = await sendWhatsapp(credentials, item.recipient_address, message)

      // 7. Sucesso
      await supabase
        .from('notification_queue')
        .update({
          status:              'enviado',
          sent_at:             new Date().toISOString(),
          provider_message_id: sendResult.messageId || null,
        })
        .eq('id', item.id)

      await supabase.from('notification_logs').insert({
        tenant_id:           item.tenant_id,
        owner_id:            item.owner_id,
        queue_id:            item.id,
        agenda_evento_id:    item.agenda_evento_id,
        patient_id:          item.patient_id,
        channel:             'whatsapp',
        template_key:        item.template_key,
        schedule_key:        item.schedule_key,
        recipient_address:   item.recipient_address,
        resolved_message:    message,
        resolved_vars:       vars,
        status:              'sent',
        provider:            'evolution_api',
        provider_message_id: sendResult.messageId || null,
        sent_at:             new Date().toISOString(),
      })

      results.push({ id: item.id, status: 'enviado' })

    } catch (err) {
      // 8. Erro — retry com backoff
      const attempts = item.attempts + 1
      const maxAttempts = item.max_attempts || 5
      const isExhausted = attempts >= maxAttempts
      const retryMs = attempts * 2 * 60 * 1000

      await supabase
        .from('notification_queue')
        .update({
          status:        isExhausted ? 'falhou' : 'pendente',
          last_error:    err.message,
          next_retry_at: isExhausted ? null : new Date(Date.now() + retryMs).toISOString(),
        })
        .eq('id', item.id)

      await supabase.from('notification_logs').insert({
        tenant_id:         item.tenant_id,
        owner_id:          item.owner_id,
        queue_id:          item.id,
        agenda_evento_id:  item.agenda_evento_id,
        patient_id:        item.patient_id,
        channel:           'whatsapp',
        template_key:      item.template_key,
        schedule_key:      item.schedule_key,
        recipient_address: item.recipient_address,
        status:            'failed',
        failure_reason:    err.message,
        failed_at:         new Date().toISOString(),
      })

      results.push({ id: item.id, status: isExhausted ? 'falhou' : 'retry', error: err.message })
    }
  }

  const sent    = results.filter(r => r.status === 'enviado').length
  const failed  = results.filter(r => r.status === 'falhou').length
  const retried = results.filter(r => r.status === 'retry').length

  return new Response(
    JSON.stringify({ processed: results.length, sent, failed, retried, details: results }),
    { status: 200, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }
  )
})
