# Instrução: Migrar links WhatsApp para Grapnel Sticky Routing

## O que fazer

Substituir TODOS os links `wa.me/{phone}` deste projeto por `grapnel.com.br/wa/G00008?text={mensagem}`.

O Grapnel resolve o destino do WhatsApp no servidor e usa um cookie para reconhecer visitas seguintes. A atribuição é mantida enquanto a identificação persistir e a vendedora continuar elegível. O cookie tem duração configurada de até 400 dias, sujeita às regras do navegador e à limpeza pelo visitante.

## Código da conta

O código `G00008` é apenas um exemplo. Substitua-o pelo código real da conta em todos os trechos antes de publicar.

(Se o código da conta não estiver disponível no projeto, pergunte ao usuário. O formato é `G` + cinco dígitos.)

## Passo 1: Descobrir todos os pontos de integração

Execute estes comandos e analise os resultados:

```bash
grep -rn "wa\.me" --include="*.ts" --include="*.tsx" --include="*.js" --include="*.jsx" .
grep -rn "next-instance" --include="*.ts" --include="*.tsx" .
grep -rn "whatsapp://send" --include="*.ts" --include="*.tsx" .
```

Identifique:
- Links `wa.me/{phone}` (hardcoded ou dinâmicos)
- Chamadas fetch ao `/next-instance` ou APIs que retornam números de WhatsApp
- Números de telefone hardcoded usados em links WhatsApp
- Context providers que distribuem `phone` para componentes
- Páginas de conversão/tracking (tipo `/sucesso-whatsapp`) que redirecionam para `wa.me`

## Passo 2: Adicionar a função utilitária

Criar ou adicionar em `lib/utils.ts` (ou equivalente):

```typescript
export function buildGrapnelUrl(ownerCode: string, message?: string): string {
  const base = `https://grapnel.com.br/wa/${ownerCode}`;
  if (message) return `${base}?text=${encodeURIComponent(message)}`;
  return base;
}

export function normalizeWhatsAppPhone(value: string): string {
  return value.replace(/\D/g, "").replace(/^00/, "");
}
```

## Passo 3: Adicionar env var

Adicionar no `.env` e `.env.local`:

```
GRAPNEL_OWNER_CODE=G00008
```

## Passo 4: Aplicar as substituições

Para CADA link `wa.me` encontrado no Passo 1, identificar se a mensagem é **fixa** ou **dinâmica** e aplicar o padrão correto:

### Mensagem fixa (hardcoded no HTML ou string literal)

Só trocar o domínio e remover o telefone. A mensagem fica igual:

```diff
- href="https://wa.me/{telefone-com-DDI-e-DDD}?text=Olá!%20Quero%20participar"
+ href="https://grapnel.com.br/wa/G00008?text=Olá!%20Quero%20participar"
```

Não precisa de `buildGrapnelUrl` — é só trocar a URL base.

### Mensagem dinâmica (montada em JS com variáveis)

Usar `buildGrapnelUrl` porque ela faz `encodeURIComponent` internamente:

```diff
- const link = `https://wa.me/${phone}?text=${encodeURIComponent(msg)}`;
+ const link = buildGrapnelUrl(process.env.GRAPNEL_OWNER_CODE!, msg);
```

`msg` deve ser texto puro (com espaços reais), NÃO url-encoded.

### Se o site chama `/next-instance` via fetch

Remover o fetch inteiro. O código da conta é constante — não precisa de chamada de API.

```diff
- const res = await fetch(`https://grapnel.com.br/api/public/next-instance?owner_code=G00008`);
- const { phone } = await res.json();
- const link = `https://wa.me/${phone}?text=${msg}`;
+ const link = buildGrapnelUrl(process.env.GRAPNEL_OWNER_CODE!, msg);
```

### Se o site tem WhatsApp context provider

Mudar a interface de `{ phone: string }` para `{ ownerCode: string | null, fallbackPhone: string }`.

Em cada componente consumidor, trocar:

```diff
- const { phone } = useWhatsApp();
- const url = `https://wa.me/${phone}?text=${msg}`;
+ const { ownerCode, fallbackPhone } = useWhatsApp();
+ const url = ownerCode
+   ? buildGrapnelUrl(ownerCode, msg)
+   : `https://wa.me/${normalizeWhatsAppPhone(fallbackPhone)}?text=${encodeURIComponent(msg)}`;
```

### Links inline com `+` para espaços

Vários sites montam URLs inline com `+` no lugar de espaços:

```
href={`wa.me/${phone}?text=Olá!+Gostaria+de+participar`}
```

Ao migrar, passar texto puro (com espaços reais) para `buildGrapnelUrl`:

```diff
- href={`/sucesso?url=${encodeURIComponent(`https://wa.me/${phone}?text=Olá!+Gostaria+de+participar`)}`}
+ href={`/sucesso?url=${encodeURIComponent(buildGrapnelUrl(ownerCode, "Olá! Gostaria de participar"))}`}
```

`buildGrapnelUrl` faz `encodeURIComponent` internamente. NÃO passar strings já encoded.

### Conditional rendering

Se algum componente condiciona renderização no phone:

```diff
- {phone && <Button>WhatsApp</Button>}
+ {(ownerCode || fallbackPhone) && <Button>WhatsApp</Button>}
```

## O que NÃO migrar

- Links para telefone de devs/suporte interno (são contatos fixos, não vendedoras)
- Páginas de conversão/tracking (tipo `/sucesso-whatsapp`) — elas só leem `?url=` e redirecionam, funcionam com qualquer URL
- Componentes que recebem URL pronta via prop (não geram links)
- Formatadores de mensagem que só geram texto (não URLs)
- Admin panels

## Fallback

Sempre manter fallback para `wa.me/{phone}` quando `GRAPNEL_OWNER_CODE` não está configurado:

```typescript
const url = ownerCode
  ? buildGrapnelUrl(ownerCode, msg)
  : `https://wa.me/${normalizeWhatsAppPhone(fallbackPhone)}?text=${encodeURIComponent(msg)}`;
```

O valor usado em `wa.me` deve ser DDI + número, somente dígitos, sem `+`, espaços, parênteses ou hífens. A função também remove o prefixo internacional `00`.

## Passo 5: Verificar

```bash
# Não deve ter wa.me/{phone} em código customer-facing (exceto fallbacks)
grep -rn "wa\.me/[0-9]" --include="*.ts" --include="*.tsx" .

# Deve ter URLs do Grapnel
grep -rn "grapnel\.com\.br/wa" --include="*.ts" --include="*.tsx" .

# Build deve passar
bun run build  # ou npm run build
```

## Passo 6: Teste E2E

Após implementar, rodar testes end-to-end para garantir que tudo funciona.

### Iniciar o servidor de desenvolvimento

Antes de testar, verificar se já tem um servidor rodando:

```bash
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/ 2>/dev/null || echo "offline"
```

Se não estiver rodando, detectar o package manager e iniciar:

```bash
# Detectar package manager
if [ -f "bun.lockb" ] || [ -f "bun.lock" ]; then
  bun run dev &
elif [ -f "pnpm-lock.yaml" ]; then
  pnpm dev &
elif [ -f "yarn.lock" ]; then
  yarn dev &
else
  npm run dev &
fi
```

Aguardar o servidor iniciar e identificar a porta correta (pode ser 3000, 3001, 3002, etc.):

```bash
# Esperar até responder
for i in 3000 3001 3002; do
  if curl -s -o /dev/null -w "%{http_code}" "http://localhost:$i/" 2>/dev/null | grep -q "200\|301\|302\|307"; then
    echo "Servidor rodando na porta $i"
    break
  fi
done
```

Usar a porta encontrada em todos os testes abaixo (substituir `3000` pela porta correta).

### Testes

1. **Verificar que o server-side gera URLs do Grapnel:**

```bash
# Se o site tem API de geração de link (tipo /api/whatsapp-link), testar:
curl -s "http://localhost:3000/api/whatsapp-link" -X POST -H "Content-Type: application/json" -d '{"key":"cta_vip"}' | grep grapnel
```

2. **Verificar que as páginas contêm URLs do Grapnel e NÃO wa.me/{phone}:**

```bash
# Para cada página principal do site:
curl -s "http://localhost:3000/" | grep -c "grapnel"
curl -s "http://localhost:3000/" | grep -o "wa\.me/[0-9]*" | head -3  # deve retornar vazio
```

3. **Verificar que a página de conversão/tracking (se existir) funciona com URL do Grapnel:**

```bash
# Se o site tem /sucesso-whatsapp ou similar:
curl -s "http://localhost:3000/sucesso-whatsapp?url=https%3A%2F%2Fgrapnel.com.br%2Fwa%2FG00008%3Ftext%3DTeste" | grep grapnel
```

4. **Verificar o redirect chain completo:**

Abrir o site no browser → clicar em qualquer botão WhatsApp → verificar que o redirect passa por `grapnel.com.br/wa/G00008` antes de chegar no `wa.me`.

5. **Verificar que links do dev/suporte NÃO foram migrados** (devem continuar com wa.me direto).
