-- 038: Programa Alta Vazão — índices dos hot paths do webhook + tabelas de arquivo
--
-- Contexto (2026-07-15): para 1M msgs/dia (2-3M eventos de entrega/dia), o
-- webhook fazia seq scan por evento (lookup por infobip_message_id sem índice
-- nas duas trilhas) e a checagem de conclusão varria o lote inteiro
-- (multibm_messages sem índice de campaign_id). Estes índices transformam os
-- três hot paths em Index Scan.
--
-- NOTA: índices criados SEM "CONCURRENTLY" de propósito — o runner do
-- deploy.sh aplica este arquivo antes do restart e as tabelas atuais são
-- pequenas (< 1M linhas); o lock é de milissegundos. Se um dia for preciso
-- recriar com a tabela grande, usar CONCURRENTLY manualmente fora do runner.
--
-- Aplicado automaticamente pelo deploy.sh (runner de migrations).

-- Lookup por evento de webhook (1 por evento — o caminho mais quente do sistema)
CREATE UNIQUE INDEX IF NOT EXISTS uidx_multibm_messages_infobip_id
  ON multibm_messages (infobip_message_id)
  WHERE infobip_message_id IS NOT NULL;

CREATE UNIQUE INDEX IF NOT EXISTS uidx_waba_messages_infobip_id
  ON waba_messages (infobip_message_id)
  WHERE infobip_message_id IS NOT NULL;

-- Checagem de conclusão do lote ("existe alguma não-terminal?") + dispatchedPhones
CREATE INDEX IF NOT EXISTS idx_multibm_messages_campaign_status
  ON multibm_messages (campaign_id, status);

-- Índice PARCIAL das não-terminais: alimenta hasNonTerminalMultibmMessages
-- (a checagem de conclusão do webhook). Contém SÓ linhas PENDING/SENT — fica
-- minúsculo e encolhe conforme o lote entrega. A lista de status precisa
-- espelhar TERMINAL_MULTIBM_STATUSES (server/multibmDispatch.ts).
CREATE INDEX IF NOT EXISTS idx_multibm_messages_nonterminal
  ON multibm_messages (campaign_id)
  WHERE status NOT IN ('DELIVERED', 'SEEN', 'FAILED');

-- Métricas de vazão (F5): contagens por janela de tempo (hoje/última hora)
CREATE INDEX IF NOT EXISTS idx_multibm_messages_sent_at
  ON multibm_messages (sent_at);

-- ─── F4: tabelas de arquivo (retenção de 90 dias no caminho quente) ─────────
-- Mesmas colunas das tabelas quentes, SEM foreign keys (campanhas/senders
-- antigos podem ser removidos sem travar o arquivo). O job noturno move
-- mensagens de campanhas finalizadas com sent_at > MESSAGES_RETENTION_DAYS.

CREATE TABLE IF NOT EXISTS multibm_messages_archive
  (LIKE multibm_messages INCLUDING DEFAULTS);

CREATE TABLE IF NOT EXISTS waba_messages_archive
  (LIKE waba_messages INCLUDING DEFAULTS);

-- Consulta ocasional do arquivo (auditoria/relatório antigo) por campanha/fone
CREATE INDEX IF NOT EXISTS idx_multibm_archive_campaign
  ON multibm_messages_archive (campaign_id);
CREATE INDEX IF NOT EXISTS idx_multibm_archive_phone
  ON multibm_messages_archive (phone);
CREATE INDEX IF NOT EXISTS idx_waba_archive_campaign
  ON waba_messages_archive (campaign_id);
CREATE INDEX IF NOT EXISTS idx_waba_archive_phone
  ON waba_messages_archive (phone);
