/*
|--------------------------------------------------------------------------
| Agência PSI — Edge Function: evolution-webhook-provision
|--------------------------------------------------------------------------
| Configura automaticamente o webhook MESSAGES_UPSERT numa instância da
| Evolution API pra apontar pra edge function `evolution-whatsapp-inbound`.
|
| Body JSON:
|   {
|     "tenant_id":     "<uuid>",
|     "api_url":       "http://localhost:8080",
|     "api_key":       "<apikey global da evolution>",
|     "instance_name": "<nome da instance>",
|     "public_url":    "https://seu-projeto.supabase.co"  (opcional)
|   }
|
| Usa SUPABASE_URL como fallback do public_url.
|--------------------------------------------------------------------------
*/

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',
}

function json(body: unknown, status = 200) {
    return new Response(JSON.stringify(body), {
        status,
        headers: { ...corsHeaders, 'Content-Type': 'application/json' }
    })
}

// Edge function roda em container — localhost aponta pra ele mesmo, não pro host.
// Substitui localhost/127.0.0.1 por host.docker.internal pra alcançar o host.
function rewriteForContainer(apiUrl: string): string {
    try {
        const u = new URL(apiUrl)
        if (u.hostname === 'localhost' || u.hostname === '127.0.0.1') {
            u.hostname = 'host.docker.internal'
            return u.toString().replace(/\/+$/, '')
        }
        return apiUrl.replace(/\/+$/, '')
    } catch {
        return apiUrl
    }
}

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

    try {
        const body = await req.json().catch(() => null)
        if (!body || typeof body !== 'object') return json({ ok: false, error: 'body invalido' }, 400)

        const { tenant_id, api_url, api_key, instance_name, public_url } = body as Record<string, string>

        if (!tenant_id || !api_url || !api_key || !instance_name) {
            return json({ ok: false, error: 'faltam campos obrigatorios (tenant_id, api_url, api_key, instance_name)' }, 400)
        }

        // Verifica caller: precisa ser member do tenant ou saas_admin
        const auth = req.headers.get('Authorization') ?? ''
        const supaAuthed = createClient(
            Deno.env.get('SUPABASE_URL')!,
            Deno.env.get('SUPABASE_ANON_KEY')!,
            { global: { headers: { Authorization: auth } } }
        )
        const { data: authData, error: authErr } = await supaAuthed.auth.getUser()
        if (authErr || !authData?.user) return json({ ok: false, error: 'auth' }, 401)

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

        const userId = authData.user.id
        // check membro ativo ou saas_admin
        const { data: isAdmin } = await supaSvc.rpc('is_saas_admin')
        if (!isAdmin) {
            const { data: membership } = await supaSvc
                .from('tenant_members')
                .select('id')
                .eq('tenant_id', tenant_id)
                .eq('user_id', userId)
                .eq('status', 'active')
                .maybeSingle()
            if (!membership) return json({ ok: false, error: 'forbidden' }, 403)
        }

        // Monta a URL publica do webhook
        const basePublic = public_url || Deno.env.get('SUPABASE_URL')
        if (!basePublic) return json({ ok: false, error: 'public_url nao definido' }, 400)
        const webhookUrl = `${basePublic.replace(/\/+$/, '')}/functions/v1/evolution-whatsapp-inbound?tenant_id=${encodeURIComponent(tenant_id)}`

        // Configura via Evolution API (rewrite localhost → host.docker.internal pra container)
        const evoEndpoint = `${rewriteForContainer(api_url)}/webhook/set/${encodeURIComponent(instance_name)}`

        // Evolution v2 payload (wrapped em "webhook")
        const evoBodyV2 = {
            webhook: {
                enabled: true,
                url: webhookUrl,
                byEvents: false,
                base64: false,
                events: ['MESSAGES_UPSERT', 'MESSAGES_UPDATE']
            }
        }

        // Evolution v1 payload (flat)
        const evoBodyV1 = {
            enabled: true,
            url: webhookUrl,
            webhook_by_events: false,
            events: ['MESSAGES_UPSERT', 'MESSAGES_UPDATE']
        }

        async function tryPost(bodyObj: Record<string, unknown>) {
            const r = await fetch(evoEndpoint, {
                method: 'POST',
                headers: { 'Content-Type': 'application/json', 'apikey': api_key },
                body: JSON.stringify(bodyObj)
            })
            const t = await r.text()
            let j: unknown = t
            try { j = JSON.parse(t) } catch { /* keep text */ }
            return { resp: r, json: j }
        }

        // Tenta v2 primeiro (user tem Evolution v2 pela resposta do state)
        let attempt = await tryPost(evoBodyV2)
        let payloadFormatUsed = 'v2'
        if (!attempt.resp.ok) {
            // Fallback v1
            const v1Attempt = await tryPost(evoBodyV1)
            if (v1Attempt.resp.ok) {
                attempt = v1Attempt
                payloadFormatUsed = 'v1'
            } else {
                // Retorna o erro da segunda tentativa
                return json({
                    ok: false,
                    error: `Evolution retornou ${attempt.resp.status} (v2) e ${v1Attempt.resp.status} (v1)`,
                    evolution_response_v2: attempt.json,
                    evolution_response_v1: v1Attempt.json,
                    webhook_url: webhookUrl,
                    evolution_endpoint: evoEndpoint
                }, 502)
            }
        }

        const respJson = attempt.json

        return json({
            ok: true,
            webhook_url: webhookUrl,
            payload_format: payloadFormatUsed,
            evolution_response: respJson
        })
    } catch (err) {
        return json({ ok: false, error: String(err) }, 500)
    }
})
