-- 095_canais_meta_dm.sql — Instagram Direct e Facebook Messenger (25/08/2026)
--
-- POR QUE EXISTE
-- O app Meta da casa (1331817815337918) foi ampliado em 25/08 e passou a ter os
-- TRÊS casos de uso: WhatsApp + Instagram + Messenger. O objetivo do dono é o
-- agente de IA (e o operador humano) respondendo pessoas nos três, dentro da
-- MESMA Central de Atendimento.
--
-- POR QUE UMA TABELA NOVA, e não `meta_cloud_connections`
-- Aquela tabela é WhatsApp POR CONSTRUÇÃO: waba_id, phone_number_id e pin são
-- NOT NULL, o UNIQUE de identidade é (owner, phone_number_id), e CINCO tabelas
-- satélites (chat_form_configs, handoff_configs, cloud_templates, cloud_messages,
-- cloud_connection_authorizations) apontam FK para lá justamente para RECUSAR
-- não-WhatsApp por construção. Uma conta do Instagram não tem número, WABA nem
-- PIN — enfiá-la ali significaria afrouxar as três NOT NULLs que protegem o
-- canal que fatura. Tabela própria, chave própria.
--
-- IDENTIDADE (decisão do dono, 25/08): Instagram e Messenger entram como canal
-- de ATENDIMENTO, FORA da Camada de Receita. A pessoa chega com IGSID/PSID, não
-- com telefone — logo não há global_contacts, opt-out por telefone, CAPI nem
-- Kanban nesta trilha. `ai_conversations.contact_phone` recebe o IGSID/PSID
-- (a coluna é varchar SEM limite; medido antes de decidir).
--
-- TERMÔMETRO: `conversation_events` nasce junto porque o sinal só existe se for
-- capturado NA HORA — visualizou-e-não-respondeu, reagiu, respondeu story. O
-- score em si não entra agora; a matéria-prima, sim.

-- ═══ 1. Conexões de mensageria Meta não-WhatsApp ═══
CREATE TABLE IF NOT EXISTS meta_messaging_connections (
  id varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_user_id varchar NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  service_id varchar NOT NULL REFERENCES services(id) ON DELETE CASCADE,
  -- "instagram" | "messenger"
  channel varchar(12) NOT NULL,
  -- Instagram: IG User ID (conta profissional). Messenger: Page ID.
  -- É o `recipient.id` que chega no webhook — a chave de resolução da conexão.
  account_id varchar(40) NOT NULL,
  -- Messenger: a própria Página. Instagram conectado via Facebook Login também
  -- tem página vinculada; via Instagram Business Login, fica NULL.
  page_id varchar(40),
  username varchar(150),
  display_name varchar(150),
  avatar_url text,
  -- AES-256-GCM (server/lib/crypto.ts) — mesmo cofre do token do WhatsApp.
  access_token_enc text NOT NULL,
  -- IG long-lived expira em 60 dias e PRECISA de refresh; Page token de System
  -- User não expira. NULL = sem expiração conhecida.
  token_expires_at timestamptz,
  last_refreshed_at timestamptz,
  status varchar(20) NOT NULL DEFAULT 'PENDING',
  last_error_code integer,
  last_error_message text,
  subscribed_at timestamptz,
  created_at timestamptz NOT NULL DEFAULT now(),
  updated_at timestamptz NOT NULL DEFAULT now()
);

-- Uma conta do Instagram / uma Página pertence a UM cliente. Sem isso, dois
-- clientes conectando a mesma conta brigariam pela mesma conversa.
-- UNIQUE como CONSTRAINT (espelha `unique()` do drizzle; index solto divergiria do db:push)
CREATE UNIQUE INDEX IF NOT EXISTS meta_msg_conn_channel_account_uniq
  ON meta_messaging_connections (channel, account_id);
CREATE INDEX IF NOT EXISTS idx_meta_msg_conn_owner
  ON meta_messaging_connections (owner_user_id);
CREATE INDEX IF NOT EXISTS idx_meta_msg_conn_status
  ON meta_messaging_connections (status);

-- ═══ 2. Canal persistido na conversa ═══
-- Hoje o canal é DERIVADO em JS por telefone/tipo de serviço
-- (shared/atendimento.ts resolveConversationChannel), com fallback final
-- "wa_oficial". Um IGSID não casa com telefone nenhum: sem coluna, toda
-- conversa de Instagram apareceria na Central rotulada como WhatsApp Oficial.
-- NULL = conversa antiga (WhatsApp), segue derivando como sempre.
ALTER TABLE ai_conversations ADD COLUMN IF NOT EXISTS channel varchar(16);

-- contact_name: no WhatsApp o identificador do card é o TELEFONE, e o nome vem
-- de global_contacts. No Instagram não há nem um nem outro — o cru é um IGSID
-- numérico de 17 dígitos. Sem esta coluna o atendente vê "17841400000000" e não
-- sabe com quem fala. Guarda o @usuario (IG) ou o nome do perfil (Messenger).
ALTER TABLE ai_conversations ADD COLUMN IF NOT EXISTS contact_name varchar(150);

-- ═══ 3. Sinais da conversa (matéria-prima do termômetro) ═══
-- Append-only e CANAL-AGNÓSTICA: o WhatsApp também pode alimentar depois.
-- Não é global_contacts (que é por telefone e por dono) — é por CONVERSA,
-- porque no Instagram não existe telefone para pendurar o sinal.
CREATE TABLE IF NOT EXISTS conversation_events (
  id bigserial PRIMARY KEY,
  conversation_id varchar NOT NULL REFERENCES ai_conversations(id) ON DELETE CASCADE,
  -- seen | reaction | postback | referral_ad | story_reply | story_mention |
  -- echo_agent | reply_latency
  type varchar(24) NOT NULL,
  payload jsonb,
  occurred_at timestamptz NOT NULL DEFAULT now(),
  created_at timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS idx_conversation_events_conv
  ON conversation_events (conversation_id, occurred_at);
CREATE INDEX IF NOT EXISTS idx_conversation_events_type
  ON conversation_events (type, occurred_at);
