-- 065 — Módulo LEADS: captação (anúncios) + onboarding (Meta/RCS)
--
-- Três entidades que NUNCA se misturam:
--   users            = clientes da Onsms (quem paga)
--   global_contacts  = contatos DOS clientes (a base deles)
--   platform_leads   = potenciais clientes DA ONSMS  ← esta migration
--
-- Um lead vira cliente por conversão explícita (botão), por casamento de
-- e-mail (cron) ou porque concluiu o onboarding. Nos três caminhos o lead
-- guarda converted_user_id e o histórico fica em lead_events.
--
-- A fila de onboarding (limite Meta de 10/200 ativações por janela de 7 dias)
-- é a coluna eligible_at do próprio request — relação 1:1, join desnecessário.

-- ── Formulários (conversão e onboarding) ────────────────────────────────────
CREATE TABLE IF NOT EXISTS lead_forms (
  id            varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  -- Hoje sempre um ADMIN. A coluna existe para o dia em que o formulário
  -- virar ferramenta do cliente, sem migração de dados.
  owner_user_id varchar NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  slug          varchar(60) NOT NULL,
  tipo          varchar(20) NOT NULL,            -- conversao | onboarding
  titulo        varchar(120) NOT NULL,
  subtitulo     varchar(300),
  copy          jsonb NOT NULL DEFAULT '{}'::jsonb,  -- headline, cta, sucesso…
  campos        jsonb NOT NULL DEFAULT '{}'::jsonb,  -- reservado p/ evolução
  pixel_meta    varchar(32),
  pixel_tiktok  varchar(32),
  utm_defaults  jsonb,
  ativo         boolean NOT NULL DEFAULT true,
  created_at    timestamptz NOT NULL DEFAULT now(),
  updated_at    timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS lead_forms_slug_idx ON lead_forms (slug);
CREATE INDEX IF NOT EXISTS lead_forms_owner_idx ON lead_forms (owner_user_id, ativo);

-- ── Leads (potenciais clientes da Onsms) ────────────────────────────────────
CREATE TABLE IF NOT EXISTS platform_leads (
  id            varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_user_id varchar NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  form_id       varchar REFERENCES lead_forms(id) ON DELETE SET NULL,
  nome          varchar(120) NOT NULL,
  whatsapp      varchar(20),                     -- E.164 (normalizeBrPhone)
  email         varchar(200),
  empresa       varchar(200),
  segmento      varchar(80),
  interesse     varchar(40),                     -- whatsapp | rcs | ambos | outro
  payload       jsonb NOT NULL DEFAULT '{}'::jsonb,
  -- Origem: é o que transforma a aba num painel de ROI por anúncio
  utm_source    varchar(80),
  utm_medium    varchar(80),
  utm_campaign  varchar(120),
  utm_content   varchar(120),
  utm_term      varchar(120),
  referrer      text,
  ip            varchar(64),
  user_agent    text,
  score         integer NOT NULL DEFAULT 0,
  status        varchar(20) NOT NULL DEFAULT 'novo',
                -- novo | em_conversa | qualificado | em_onboarding | convertido | perdido
  converted_user_id varchar REFERENCES users(id) ON DELETE SET NULL,
  converted_at  timestamptz,
  created_at    timestamptz NOT NULL DEFAULT now(),
  updated_at    timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS platform_leads_owner_status_idx ON platform_leads (owner_user_id, status, created_at DESC);
CREATE INDEX IF NOT EXISTS platform_leads_form_idx ON platform_leads (form_id, created_at DESC);
-- Dedupe por dono: o mesmo WhatsApp/e-mail não vira dois leads (o anúncio
-- reentrega, a pessoa clica duas vezes). Parcial porque os campos são opcionais.
CREATE UNIQUE INDEX IF NOT EXISTS platform_leads_owner_whatsapp_idx
  ON platform_leads (owner_user_id, whatsapp) WHERE whatsapp IS NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS platform_leads_owner_email_idx
  ON platform_leads (owner_user_id, lower(email)) WHERE email IS NOT NULL;

-- ── Timeline do lead ────────────────────────────────────────────────────────
CREATE TABLE IF NOT EXISTS lead_events (
  id       varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  lead_id  varchar NOT NULL REFERENCES platform_leads(id) ON DELETE CASCADE,
  tipo     varchar(30) NOT NULL,                 -- criado | status | nota | conversao | onboarding
  actor    varchar(20) NOT NULL DEFAULT 'system',-- system | human | lead
  payload  jsonb NOT NULL DEFAULT '{}'::jsonb,
  at       timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS lead_events_lead_idx ON lead_events (lead_id, at DESC);

-- ── Pedidos de onboarding (UM por canal; o formulário é único) ──────────────
CREATE TABLE IF NOT EXISTS onboarding_requests (
  id            varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  owner_user_id varchar NOT NULL REFERENCES users(id) ON DELETE CASCADE,
  lead_id       varchar REFERENCES platform_leads(id) ON DELETE SET NULL,
  -- Um formulário preenchido gera um request POR CANAL escolhido: as máquinas
  -- de estado são diferentes (Meta tem fila/ES/BRL; RCS é assistido via MKOM)
  -- e um canal travado não pode segurar o outro.
  canal         varchar(10) NOT NULL,            -- meta | rcs
  status        varchar(30) NOT NULL DEFAULT 'FORM_STARTED',
  score         integer,
  semaforo      varchar(10),                     -- verde | amarelo | vermelho
  rota          varchar(1),                      -- A|B|C|D (só Meta)
  payload       jsonb NOT NULL DEFAULT '{}'::jsonb,   -- tronco + ramo do canal
  blocked_reasons jsonb NOT NULL DEFAULT '[]'::jsonb,
  -- Retomada do formulário sem login (link mágico enviado por WhatsApp)
  magic_token   varchar(64) NOT NULL,
  requires_human boolean NOT NULL DEFAULT false,
  -- Conta criada para este onboarding (preenchida em VALIDATED)
  user_id       varchar REFERENCES users(id) ON DELETE SET NULL,
  -- Fila da janela de 7 dias: quando este request pode ir para o ES
  eligible_at   timestamptz,
  submitted_at  timestamptz,
  completed_at  timestamptz,
  created_at    timestamptz NOT NULL DEFAULT now(),
  updated_at    timestamptz NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX IF NOT EXISTS onboarding_requests_token_idx ON onboarding_requests (magic_token);
CREATE INDEX IF NOT EXISTS onboarding_requests_owner_idx ON onboarding_requests (owner_user_id, canal, status);
CREATE INDEX IF NOT EXISTS onboarding_requests_lead_idx ON onboarding_requests (lead_id);
CREATE INDEX IF NOT EXISTS onboarding_requests_fila_idx ON onboarding_requests (status, eligible_at);

-- ── Transições (funil, gargalo e SLA de graça) ──────────────────────────────
CREATE TABLE IF NOT EXISTS onboarding_events (
  id          varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  request_id  varchar NOT NULL REFERENCES onboarding_requests(id) ON DELETE CASCADE,
  from_status varchar(30),
  to_status   varchar(30) NOT NULL,
  actor       varchar(20) NOT NULL DEFAULT 'system',
  payload     jsonb NOT NULL DEFAULT '{}'::jsonb,
  at          timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS onboarding_events_request_idx ON onboarding_events (request_id, at);
CREATE INDEX IF NOT EXISTS onboarding_events_status_idx ON onboarding_events (to_status, at DESC);

-- ── Aceites (prova jurídica: quem aceitou o quê, quando, de onde) ───────────
CREATE TABLE IF NOT EXISTS onboarding_acceptances (
  id           varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  request_id   varchar NOT NULL REFERENCES onboarding_requests(id) ON DELETE CASCADE,
  aceite       varchar(60) NOT NULL,             -- dpa_lgpd, coexistencia, cobranca…
  versao_texto varchar(20) NOT NULL,
  ip           varchar(64),
  user_agent   text,
  at           timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS onboarding_acceptances_request_idx ON onboarding_acceptances (request_id);

-- ── OTP do responsável (etapa 1) ────────────────────────────────────────────
-- Número errado = onboarding órfão: todo o acompanhamento é por WhatsApp.
-- Guarda só o HASH do código; expira em minutos e limita tentativas.
CREATE TABLE IF NOT EXISTS onboarding_otps (
  id          varchar PRIMARY KEY DEFAULT gen_random_uuid(),
  request_id  varchar NOT NULL REFERENCES onboarding_requests(id) ON DELETE CASCADE,
  phone       varchar(20) NOT NULL,
  code_hash   varchar(128) NOT NULL,
  attempts    integer NOT NULL DEFAULT 0,
  expires_at  timestamptz NOT NULL,
  verified_at timestamptz,
  created_at  timestamptz NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS onboarding_otps_request_idx ON onboarding_otps (request_id, created_at DESC);
