defmodule BilldogEng.Messaging do @moduledoc """ Messaging dispatch (BillDog advantage over PostHog) — server-side delivery across push / email / sms / in-app / live-activity. Note: `messaging-dispatch` authenticates with a Supabase session **Bearer JWT** + project membership, not the `x-api-key` key used by the other modules. Pass the JWT as `:access_token` per call. Mirrors the Node SDK `messaging.ts`. """ alias BilldogEng.Transport @doc """ Dispatch a message. Returns `{:ok, %{"sent" => .., "failed" => ..}}` (or a `{:error, ...}` envelope when no recipients match). Required params (keyword list): * `:project_id` — project UUID * `:channel` — one of `push|email|sms|in-app|live-activity` * `:content` — channel-specific content map * `:access_token` — Bearer JWT Optional: `:targeting`, `:scheduling`, `:template_id`. """ @spec dispatch(BilldogEng.t(), keyword()) :: {:ok, term()} | {:error, BilldogEng.Error.t()} def dispatch(client, params) do body = %{ action: "send", project_id: Keyword.fetch!(params, :project_id), channel: Keyword.fetch!(params, :channel), content: Keyword.fetch!(params, :content) } |> put_if(:targeting, Keyword.get(params, :targeting)) |> put_if(:scheduling, Keyword.get(params, :scheduling)) |> put_if(:template_id, Keyword.get(params, :template_id)) access_token = Keyword.fetch!(params, :access_token) Transport.request(client.transport, path: "/messaging-dispatch", body: body, headers: [{"authorization", "Bearer #{access_token}"}], gzip: false ) end defp put_if(map, _key, nil), do: map defp put_if(map, key, value), do: Map.put(map, key, value) end