// WhatsApp through the Cloud API: a text, a template with its variables, and the webhook: Meta's
// verify handshake, the signature checked, and incoming messages answered and marked read.
//
//   WHATSAPP_TOKEN=... WHATSAPP_PHONE_NUMBER_ID=... WHATSAPP_APP_SECRET=... WHATSAPP_VERIFY_TOKEN=... quillo run whatsapp.qwe
//   then open http://localhost:8080/text, /template, /hook-check and /failures
//
// Point the app's webhook at /whatsapp/hook. WHATSAPP_API_URL reaches a test server.

use "whatsapp.qwer"

let TO = "+1 (555) 123-4567"
let VERIFY = env("WHATSAPP_VERIFY_TOKEN", "")

route GET /text {
    let r = whatsapp_text(TO, "Your order has shipped", { preview_url: false })?
    { id: r.id, to: r.wa_id }
}

route GET /template {
    let components = [
        whatsapp_header_image("https://example.com/box.png"),
        whatsapp_body(["Ada", "1001"]),
        whatsapp_button(0, "url", "track/1001")?,
    ]
    let r = whatsapp_template(TO, "order_update", "en_US", components, {})?
    { id: r.id, status: r.status, plain: whatsapp_template(TO, "hello_world", "en_US", [], {})?.status }
}

route GET /image {
    let r = whatsapp_send(TO, { type: "image", image: { link: "https://example.com/box.png", caption: "Your box" } }, {})?
    { id: r.id }
}

route GET /failures = {
    window: whatsapp_text("15550000001", "Hi", {}).error,
    template: whatsapp_template(TO, "no_such_template", "en_US", [], {}).error,
    bad_token: whatsapp_text(TO, "Hi", { token: "expired" }).error,
    bad_number: whatsapp_text("0123", "Hi", {}).error,
    retried: whatsapp_text("15550000002", "Hi", {})?.wa_id,
}

// Meta calls this once when the webhook is set.
route GET /whatsapp/hook {
    let challenge = whatsapp_verify(request.query, VERIFY)
    if is_err(challenge) { reply 403 challenge.error }
    challenge
}

route POST /whatsapp/hook {
    if !whatsapp_signature_ok(request.body, request.headers["x-hub-signature-256"] ?? "", "") { reply 401 "bad signature" }
    let hook = whatsapp_read_webhook(request.body)?
    for m in hook.messages {
        whatsapp_mark_read(m.id, {})?
        whatsapp_text(m.from, `You said: ${m.text}`, { reply_to: m.id })?
    }
    { messages: len(hook.messages), statuses: len(hook.statuses) }
}

// Signature vectors made outside the plugin, and a body shaped as Meta sends it.
let sample = "{\"object\":\"whatsapp_business_account\",\"entry\":[{\"id\":\"1\",\"changes\":[{\"field\":\"messages\",\"value\":{\"metadata\":{\"phone_number_id\":\"106\"},\"contacts\":[{\"wa_id\":\"15551234567\",\"profile\":{\"name\":\"Ada\"}}],\"messages\":[{\"id\":\"wamid.A\",\"from\":\"15551234567\",\"timestamp\":\"1790000000\",\"type\":\"text\",\"text\":{\"body\":\"Hello\"}},{\"id\":\"wamid.B\",\"from\":\"15551234567\",\"timestamp\":\"1790000001\",\"type\":\"button\",\"button\":{\"text\":\"Yes\",\"payload\":\"confirm\"}}],\"statuses\":[{\"id\":\"wamid.C\",\"status\":\"delivered\",\"recipient_id\":\"15551234567\",\"timestamp\":\"1790000002\"}]}}]}]}"

route GET /hook-check {
    let hook = whatsapp_read_webhook(sample)?
    let body = "{\"object\":\"whatsapp_business_account\"}"
    {
        good: whatsapp_signature_ok(body, "sha256=0bf7374433906636bed1653bc7c64affb42fa5da9a39e251ab95c2e3a9c06923", "app-secret"),
        tampered: whatsapp_signature_ok(body + " ", "sha256=0bf7374433906636bed1653bc7c64affb42fa5da9a39e251ab95c2e3a9c06923", "app-secret"),
        verify_ok: whatsapp_verify({ "hub.mode": "subscribe", "hub.verify_token": "tok", "hub.challenge": "1158201444" }, "tok")?,
        verify_bad: whatsapp_verify({ "hub.mode": "subscribe", "hub.verify_token": "guess", "hub.challenge": "1" }, "tok").error,
        from: hook.messages[0].name,
        said: map(hook.messages, (m) => m.text),
        button: hook.messages[1].button,
        status: hook.statuses[0].status,
    }
}
