/*
|--------------------------------------------------------------------------
| Agência PSI — Edge Function: create-whatsapp-credit-charge
|--------------------------------------------------------------------------
| Cria cobrança PIX no Asaas pra compra de pacote de créditos WhatsApp.
|
| Input: { package_id: UUID }
| Output: {
|   ok: true,
|   purchase: { id, amount_brl, credits, package_name, asaas_pix_qrcode,
|               asaas_pix_copy_paste, asaas_payment_link, expires_at }
| }
|
| Env vars:
|   ASAAS_API_KEY      — API key da conta Asaas
|   ASAAS_API_URL      — https://sandbox.asaas.com/api/v3 ou https://api.asaas.com/v3
|--------------------------------------------------------------------------
*/

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

// ── Asaas helpers ─────────────────────────────────────────
const ASAAS_API_URL = (Deno.env.get('ASAAS_API_URL') || 'https://sandbox.asaas.com/api/v3').replace(/\/+$/, '')
const ASAAS_API_KEY = Deno.env.get('ASAAS_API_KEY') || ''

async function asaasRequest(path: string, method: string, body?: unknown) {
    const resp = await fetch(`${ASAAS_API_URL}${path}`, {
        method,
        headers: {
            'Content-Type': 'application/json',
            'access_token': ASAAS_API_KEY,
            'User-Agent': 'AgenciaPSI/1.0'
        },
        body: body ? JSON.stringify(body) : undefined
    })
    const text = await resp.text()
    let data: unknown = null
    try { data = JSON.parse(text) } catch { /* noop */ }
    if (!resp.ok) {
        return { ok: false, status: resp.status, error: data || text }
    }
    return { ok: true, data }
}

// Cria ou reutiliza cliente Asaas pro tenant. Se existente estiver sem CPF/CNPJ
// mas nós temos um (ex: sandbox fallback), atualiza antes de retornar.
async function getOrCreateAsaasCustomer(
    tenantName: string,
    tenantEmail: string | null,
    tenantDoc: string | null,
    tenantId: string
): Promise<{ ok: boolean; id?: string; error?: string }> {
    // Tenta buscar por externalReference (tenant_id)
    const search = await asaasRequest(`/customers?externalReference=${encodeURIComponent(tenantId)}`, 'GET')
    if (search.ok) {
        const list = (search.data as { data?: Array<{ id: string; cpfCnpj?: string; email?: string; name?: string }> })?.data || []
        const existing = list[0]
        if (existing?.id) {
            // Se falta CPF/CNPJ no customer existente e nós temos um, atualiza
            const needsUpdate = !existing.cpfCnpj && tenantDoc
            if (needsUpdate) {
                const patchPayload: Record<string, unknown> = { cpfCnpj: tenantDoc }
                if (tenantEmail && !existing.email) patchPayload.email = tenantEmail
                if (tenantName && !existing.name) patchPayload.name = tenantName
                const upd = await asaasRequest(`/customers/${existing.id}`, 'POST', patchPayload)
                if (!upd.ok) {
                    return { ok: false, error: `update_customer: ${JSON.stringify(upd.error).slice(0, 300)}` }
                }
            }
            return { ok: true, id: existing.id }
        }
    }

    // Cria
    const payload: Record<string, unknown> = {
        name: tenantName || `Tenant ${tenantId.slice(0, 8)}`,
        externalReference: tenantId
    }
    if (tenantEmail) payload.email = tenantEmail
    if (tenantDoc) payload.cpfCnpj = tenantDoc

    const create = await asaasRequest('/customers', 'POST', payload)
    if (!create.ok) return { ok: false, error: JSON.stringify(create.error).slice(0, 300) }
    const id = (create.data as { id?: string })?.id
    if (!id) return { ok: false, error: 'no_customer_id' }
    return { ok: true, id }
}

Deno.serve(async (req: Request) => {
    console.log('[create-charge] request received, method:', req.method)
    if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders })
    if (req.method !== 'POST') return json({ ok: false, error: 'method_not_allowed' }, 405)

    console.log('[create-charge] ASAAS_API_KEY length:', ASAAS_API_KEY.length, 'URL:', ASAAS_API_URL)
    if (!ASAAS_API_KEY) {
        return json({ ok: false, error: 'Asaas não configurado. Contate o suporte.' }, 503)
    }

    try {
        console.log('[create-charge] parsing body')
        const body = await req.json().catch(() => null) as { package_id?: string; cpf_cnpj?: string } | null
        console.log('[create-charge] body:', JSON.stringify(body))
        const packageId = body?.package_id
        if (!packageId) return json({ ok: false, error: 'package_id ausente' }, 400)
        const providedDoc = (body?.cpf_cnpj || '').replace(/\D/g, '')

        // Auth
        const authHeader = req.headers.get('Authorization')
        console.log('[create-charge] authHeader present:', !!authHeader)
        if (!authHeader) return json({ ok: false, error: 'unauthorized' }, 401)

        console.log('[create-charge] creating supaAuth client')
        const supaAuth = createClient(
            Deno.env.get('SUPABASE_URL')!,
            Deno.env.get('SUPABASE_ANON_KEY')!,
            { global: { headers: { Authorization: authHeader } } }
        )
        console.log('[create-charge] calling auth.getUser')
        const { data: authData, error: authErr } = await supaAuth.auth.getUser()
        console.log('[create-charge] authErr:', authErr?.message, 'userId:', authData?.user?.id)
        if (authErr || !authData?.user) return json({ ok: false, error: 'unauthorized' }, 401)
        const userId = authData.user.id

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

        // Descobre tenant do usuário (assume ativo — frontend passa via session)
        console.log('[create-charge] querying tenant membership for user', userId)
        const { data: membership, error: memErr } = await supaSvc
            .from('tenant_members')
            .select('tenant_id')
            .eq('user_id', userId)
            .eq('status', 'active')
            .limit(1)
            .maybeSingle()
        console.log('[create-charge] membership:', membership, 'err:', memErr?.message)
        if (!membership?.tenant_id) return json({ ok: false, error: 'no_active_tenant' }, 403)
        const tenantId = membership.tenant_id

        // Busca pacote
        console.log('[create-charge] querying package', packageId)
        const { data: pkg, error: pkgErr } = await supaSvc
            .from('whatsapp_credit_packages')
            .select('*')
            .eq('id', packageId)
            .eq('is_active', true)
            .maybeSingle()
        console.log('[create-charge] pkg:', pkg?.name, 'err:', pkgErr?.message)
        if (!pkg) return json({ ok: false, error: 'package_not_found_or_inactive' }, 404)

        // Busca dados do tenant
        const { data: tenant } = await supaSvc
            .from('tenants')
            .select('id, name, kind, cpf_cnpj')
            .eq('id', tenantId)
            .maybeSingle()
        const tenantName = tenant?.name || `Cliente ${tenantId.slice(0, 8)}`

        // Email do tenant: pega do usuário que está comprando (está autenticado)
        const tenantEmail = authData.user.email || null

        // CPF/CNPJ: prioridade 1) body (user informou agora), 2) coluna tenants.cpf_cnpj
        // Asaas exige esse campo. Se ainda nao tem, front deve coletar.
        const storedDoc = (tenant?.cpf_cnpj || '').replace(/\D/g, '')
        let tenantDoc: string | null = providedDoc || storedDoc || null

        // Valida comprimento (11 CPF, 14 CNPJ) — sem checksum aqui, UI valida.
        if (tenantDoc && tenantDoc.length !== 11 && tenantDoc.length !== 14) {
            return json({
                ok: false,
                error: 'cpf_cnpj_invalid',
                message: 'CPF/CNPJ inválido. Informe 11 dígitos (CPF) ou 14 (CNPJ).'
            }, 400)
        }

        if (!tenantDoc) {
            return json({
                ok: false,
                error: 'cpf_cnpj_required',
                message: 'Informe o CPF/CNPJ do titular pra gerar a cobrança.'
            }, 400)
        }

        // Persiste no tenant quando usuario informa novo doc (ou corrige um errado)
        if (providedDoc && providedDoc !== storedDoc) {
            const { error: upErr } = await supaSvc
                .from('tenants')
                .update({ cpf_cnpj: providedDoc })
                .eq('id', tenantId)
            if (upErr) console.warn('[create-charge] update tenant cpf_cnpj failed:', upErr.message)
        }

        // Cria ordem de compra (pending)
        console.log('[create-charge] creating purchase record')
        const expiresAt = new Date(Date.now() + 24 * 3600 * 1000).toISOString()  // 24h
        const { data: purchase, error: purErr } = await supaSvc
            .from('whatsapp_credit_purchases')
            .insert({
                tenant_id: tenantId,
                package_id: pkg.id,
                package_name: pkg.name,
                credits: pkg.credits,
                amount_brl: pkg.price_brl,
                status: 'pending',
                expires_at: expiresAt,
                created_by: userId
            })
            .select('id')
            .single()
        console.log('[create-charge] purchase:', purchase?.id, 'err:', purErr?.message)
        if (purErr || !purchase) return json({ ok: false, error: `db_insert: ${purErr?.message}` }, 500)

        // Cria/reutiliza customer Asaas
        console.log('[create-charge] calling getOrCreateAsaasCustomer')
        const custRes = await getOrCreateAsaasCustomer(tenantName, tenantEmail, tenantDoc, tenantId)
        console.log('[create-charge] customer result:', custRes)
        if (!custRes.ok) {
            // Marca purchase como failed
            await supaSvc.from('whatsapp_credit_purchases').update({
                status: 'failed', failed_at: new Date().toISOString()
            }).eq('id', purchase.id)
            return json({ ok: false, error: `asaas_customer: ${custRes.error}` }, 502)
        }
        const customerId = custRes.id!

        // Cria pagamento PIX no Asaas
        const dueDate = new Date()
        dueDate.setDate(dueDate.getDate() + 1)
        const paymentPayload = {
            customer: customerId,
            billingType: 'PIX',
            value: Number(pkg.price_brl),
            dueDate: dueDate.toISOString().slice(0, 10),
            description: `Créditos WhatsApp — ${pkg.name} (${pkg.credits} mensagens)`,
            externalReference: purchase.id
        }
        console.log('[create-charge] creating Asaas payment, payload:', JSON.stringify(paymentPayload))
        const payRes = await asaasRequest('/payments', 'POST', paymentPayload)
        console.log('[create-charge] payment result ok:', payRes.ok, 'status:', (payRes as any).status, 'data/error:', JSON.stringify(payRes.ok ? payRes.data : payRes.error).slice(0, 500))
        if (!payRes.ok) {
            await supaSvc.from('whatsapp_credit_purchases').update({
                status: 'failed', failed_at: new Date().toISOString()
            }).eq('id', purchase.id)
            return json({ ok: false, error: `asaas_payment: ${JSON.stringify(payRes.error).slice(0, 300)}` }, 502)
        }
        const payment = payRes.data as { id: string; invoiceUrl?: string }
        console.log('[create-charge] payment created:', payment.id)

        // Busca QR Code PIX
        console.log('[create-charge] fetching PIX QR code')
        const qrRes = await asaasRequest(`/payments/${payment.id}/pixQrCode`, 'GET')
        console.log('[create-charge] qr result ok:', qrRes.ok, 'has encodedImage:', !!(qrRes.ok && (qrRes.data as any)?.encodedImage))
        const qr = qrRes.ok ? (qrRes.data as { encodedImage?: string; payload?: string; expirationDate?: string }) : null

        // Atualiza purchase com dados Asaas
        console.log('[create-charge] updating purchase with Asaas data')
        const { error: updErr } = await supaSvc
            .from('whatsapp_credit_purchases')
            .update({
                asaas_customer_id: customerId,
                asaas_payment_id: payment.id,
                asaas_payment_link: payment.invoiceUrl ?? null,
                asaas_pix_qrcode: qr?.encodedImage ?? null,
                asaas_pix_copy_paste: qr?.payload ?? null
            })
            .eq('id', purchase.id)
        console.log('[create-charge] update purchase err:', updErr?.message)

        console.log('[create-charge] returning success')
        return json({
            ok: true,
            purchase: {
                id: purchase.id,
                package_name: pkg.name,
                credits: pkg.credits,
                amount_brl: pkg.price_brl,
                asaas_payment_link: payment.invoiceUrl ?? null,
                asaas_pix_qrcode: qr?.encodedImage ?? null,
                asaas_pix_copy_paste: qr?.payload ?? null,
                expires_at: expiresAt
            }
        })
    } catch (err) {
        const msg = err instanceof Error ? `${err.message}\n${err.stack}` : String(err)
        console.error('[create-whatsapp-credit-charge] fatal:', msg)
        return json({ ok: false, error: String(err), stack: msg }, 500)
    }
})
