# Modulo Marketing Gamma (Plano de implementacao)

## Objetivo

Adicionar um modulo "Marketing (Gamma)" dentro do mini banco para gerar:

- paginas (`format=webpage`) com link rastreavel interno.
- criativos (`social`, `presentation`, `document`) com export para arquivos.

Sem quebrar o modulo de marketing atual e sem duplicar rastreio.

## Estado atual do projeto (base para o desenho)

- Ja existe modulo de marketing local:
  - controller: `MarketingController`
  - tabelas: `marketing_templates`, `marketing_user_profiles`
- Ja existe rastreio de links em `lead_capture_links` com contadores de `views_count` e `submissions_count`.
- Ja existe tela de `Configuracoes > Integracoes` com bloco especifico (ex.: Crefaz) e suporte a segredo protegido.
- Ja existe infraestrutura de automacao (`automation.php`, `automation_jobs`) para processamento assinc.

## Decisoes de arquitetura (ajustadas ao projeto)

1. Nao substituir o marketing atual  
   O Gamma entra como submodulo dentro de Marketing, sem remover o estudio de artes local.

2. Reaproveitar infra existente de fila  
   Em vez de criar processo isolado, usar `automation.php` + job type para polling de geracoes Gamma.

3. Reaproveitar rastreio de links existente  
   Para `webpage`, criar link interno no `lead_capture_links` e rota publica `/go/{slug}`.

4. Guardar configuracoes em `settings`  
   Usar chaves dedicadas (`gamma_*`) e segredo criptografado (padrao similar ao Crefaz).

5. Evitar redundancia de nomenclatura  
   Usar tabelas com prefixo `marketing_gamma_*` para nao confundir com `marketing_templates` atual.

## Escopo tecnico (v1)

### 1) Configuracoes

Criar bloco "Gamma" em `Configuracoes > Integracoes` com:

- `gamma_enabled` (bool)
- `gamma_api_key` (secret)
- `gamma_default_theme_id`
- `gamma_default_folder_id`
- `gamma_default_image_source`
- `gamma_default_export_as` (`pdf|pptx`)
- `gamma_default_language` (default `pt-BR`)
- `gamma_max_generations_per_hour` (default inicial: 10)
- botao `Testar conexao` (GET `/themes` ou `/folders`)

### 2) Modelo de dados

Criar migrations para:

- `marketing_gamma_templates`
- `marketing_gamma_generations`
- `marketing_gamma_assets`
- `marketing_gamma_themes_cache` (opcional)
- `marketing_gamma_folders_cache` (opcional)

Campos principais:

- template: defaults de `format`, `theme`, `folder`, `textMode`, `exportAs` e `use_template_api`.
- generation: `user_id`, `template_id`, `generation_id`, `status`, `gamma_url`, `export_urls`, `tracked_link_id`, `poll_attempts`, `next_poll_at`, `last_request_id`, `error_message`.
- assets: arquivo persistido no servidor (`storage_path`, `mime_type`, `size_bytes`).

### 3) Servicos

- `App\Services\Gamma\GammaApiService`
  - `createGeneration(array $payload): array`
  - `createFromTemplate(array $payload): array`
  - `getGeneration(string $generationId): array`
  - `listThemes(?string $cursor, ?string $query): array`
  - `listFolders(?string $cursor, ?string $query): array`

- `App\Services\Gamma\GammaGenerationService`
  - `enqueueGeneration(int $userId, int $templateId, array $userInputs): array`
  - `pollPendingGenerations(int $limit = 50): array`
  - `downloadAndStoreExports(array $generation): array`

### 4) API Gamma

- Base: `https://public-api.gamma.app/v1.0/`
- Header obrigatorio: `X-API-KEY: {key}`
- `Content-Type: application/json`
- Fluxo: `create -> generationId -> status polling -> gammaUrl/export urls`

Contratos recebidos (amostras reais):

`POST /generations` minimo:

```json
{
  "inputText": "Best hikes in the United States",
  "textMode": "generate"
}
```

`POST /generations` completo:

```json
{
  "inputText": "Best hikes in the United States",
  "textMode": "generate",
  "format": "presentation",
  "themeId": "<your-theme-id>",
  "numCards": 10,
  "cardSplit": "auto",
  "additionalInstructions": "Make the titles catchy",
  "folderIds": ["<your-folder-id>"],
  "exportAs": "pdf",
  "textOptions": {
    "amount": "detailed",
    "tone": "professional, inspiring",
    "audience": "outdoors enthusiasts, adventure seekers",
    "language": "en"
  },
  "imageOptions": {
    "source": "aiGenerated",
    "model": "imagen-4-pro",
    "style": "photorealistic"
  },
  "cardOptions": {
    "dimensions": "fluid",
    "headerFooter": {
      "topRight": { "type": "image", "source": "themeLogo", "size": "sm" },
      "bottomRight": { "type": "cardNumber" },
      "hideFromFirstCard": true,
      "hideFromLastCard": false
    }
  },
  "sharingOptions": {
    "workspaceAccess": "view",
    "externalAccess": "noAccess",
    "emailOptions": {
      "recipients": ["email@example.com"],
      "access": "comment"
    }
  }
}
```

Resposta de sucesso no create:

```json
{
  "generationId": "yyyyyyyyyy"
}
```

Erros conhecidos no create:

```json
{
  "message": "Input validation errors: 1. ...",
  "statusCode": 400
}
```

```json
{
  "message": "Forbidden",
  "statusCode": 403
}
```

`GET /generations/{generationId}`:

- pendente:

```json
{
  "status": "pending",
  "generationId": "XXXXXXXXXXX"
}
```

- concluido:

```json
{
  "generationId": "XXXXXXXXXXX",
  "status": "completed",
  "gammaUrl": "https://gamma.app/docs/yyyyyyyyyy",
  "credits": { "deducted": 150, "remaining": 3000 }
}
```

- erro 404:

```json
{
  "message": "Generation ID not found. generationId: xxxxxx",
  "statusCode": 404,
  "credits": { "deducted": 0, "remaining": 3000 }
}
```

Mapeamento sugerido de status interno:

- `queued` (interno antes de criar no Gamma)
- `processing` (quando Gamma retornar `pending`)
- `completed` (quando Gamma retornar `completed`)
- `failed` (erros sem recuperacao)
- `expired` (export url expirou antes do download)

Obs.: ainda falta uma amostra real do `completed` com links de export para fechar parser de `export_urls`.

Pontos adicionais do resumo tecnico recebido (incorporados como referencia):

- possivel alias de criacao: `POST /generate` (alem de `POST /generations`).
- possivel endpoint dedicado de URLs: `GET /gamma-files/{generationId}/urls`.
- campos opcionais citados: `title`, `outputLanguage`.
- status adicional citado: `running` (além de `pending`).
- erros gerais citados: `400`, `401`, `403`, `404`, `429`, `500`.
- warnings possiveis citados: `content_truncated`, `image_generation_failed`, `theme_not_found`.
- modelos de imagem citados: `imagen-4-pro`, `imagen-basic`, `dalle`, `stable-diffusion`.

Tratamento recomendado para implementacao:

- usar `POST /generations` como endpoint principal.
- implementar fallback configuravel para `POST /generate` somente se ambiente retornar 404/405 no principal.
- priorizar `GET /generations/{id}` para status.
- se `GET /gamma-files/{id}/urls` existir no ambiente, usar como complemento para `view_url/edit_url/download_url/embed_url`.
- aceitar `title` e `outputLanguage` como opcionais no payload interno, mapeando idioma tambem para `textOptions.language` quando presente.
- tratar `pending` e `running` como `processing` internamente.
- aplicar retry com backoff para `429` e `5xx`.

### 5) Rastreio sem redundancia

Para `format=webpage`:

- criar `lead_capture_links` para o dono da geracao.
- salvar `tracked_link_id` em `marketing_gamma_generations`.
- rota publica `GET /go/{slug}`:
  - valida link ativo
  - incrementa `views_count`
  - resolve geracao
  - redireciona 302 para `gamma_url`

### 6) Permissoes

- Usuario comum: apenas registros `user_id = usuario logado`.
- Admin: enxerga tudo.
- Biblioteca de templates: visivel para todos com `is_active = 1`.

### 7) Integracao com Comunicados (foco em corretores)

Objetivo: permitir transformar um material gerado no Gamma em comunicado para corretores de forma simples.

Fluxo recomendado (1 clique):

1. usuario gera criativo no Gamma e conclui geracao.
2. na tela "Minhas criacoes", acao `Criar comunicado`.
3. sistema abre formulario de `/comunicados/criar` ja preenchido com:
   - titulo sugerido
   - resumo sugerido
   - corpo com link rastreavel (webpage) e/ou download de asset
   - anexo principal (imagem/pdf/pptx) quando disponivel
4. usuario escolhe publico interno e publica.

Reuso do modulo existente:

- manter `InternalWallController` e `internal_wall_posts` como canal unico de comunicados.
- nao criar canal paralelo para mensagem interna.

Ajustes necessarios para "enviar para corretores":

- incluir segmentacao interna por papel no comunicado:
  - `brokers` (obrigatorio para este requisito)
  - opcional: `employees`, `operations`, `admin`
- armazenar segmentacao em campo dedicado (json) no post, ex.:
  - `target_internal_roles` = `["broker"]`
- no feed interno, exibir comunicado apenas para papeis elegiveis.

Atalhos de UX recomendados:

- botao `Enviar para corretores` na linha da geracao concluida.
- preset automatico:
  - `audience = internal`
  - `target_internal_roles = ["broker"]`
  - `status = published` (com confirmacao)

Campos de template para comunicado com marketing:

- `title` (titulo do comunicado)
- `summary` (texto curto)
- `body` (conteudo com placeholders)
- `default_target_internal_roles` (ex.: apenas corretores)
- `include_assets` (bool)

## Rotas previstas (v1)

Usuario:

- `GET /marketing/gamma/templates`
- `GET /marketing/gamma/templates/{id}`
- `POST /marketing/gamma/generate`
- `GET /marketing/gamma/my-generations`
- `GET /marketing/gamma/generations/{id}`
- `GET /marketing/gamma/assets/{assetId}/download`
- `GET /go/{slug}`

Admin:

- `GET /admin/gamma/templates`
- `POST /admin/gamma/templates`
- `PUT /admin/gamma/templates/{id}`
- `GET /admin/gamma/generations`

Automacao:

- comando recomendado no projeto: `php automation.php gamma:poll`
- opcionalmente expor alias externo `php /path/to/cron/gamma_poll.php` chamando o comando acima.

## Ordem de implementacao (o que criar primeiro)

### Fase 1 (MVP obrigatorio)

1. Configuracao Gamma em Integracoes + teste de conexao.  
2. Migrations `marketing_gamma_*` + models basicos.  
3. `GammaApiService` com `create` e `get status`.  
4. `GammaGenerationService` com enfileiramento, polling e limites (`poll_attempts`, `next_poll_at`).  
5. Rota `/go/{slug}` integrada ao `lead_capture_links` para rastreio.  
6. Tela minima "Minhas criacoes" com status e link rastreavel.

Criterio de pronto da Fase 1:

- gerar `webpage` assinc, salvar `gamma_url`, criar `/go/{slug}` e contar view.
- gerar `social/presentation/document`, salvar status e erro corretamente.

### Fase 2

1. CRUD completo de templates Gamma no admin.  
2. Sincronizacao/cache de themes e folders.  
3. Download de export (`pdf/pptx`) e persistencia em `marketing_gamma_assets`.  
4. Download de arquivo pela UI com permissao.

### Fase 3

1. Conversao opcional `pdf -> imagens` (se ferramenta disponivel).  
2. Tela admin de observabilidade (filtros por usuario/status/tentativas).  
3. Acao de reprocessar expirados e regerar payload.

### Fase 4 (Comunicados para corretores)

1. Integrar geracoes Gamma com criacao de comunicado no fluxo existente `/comunicados`.  
2. Adicionar segmentacao interna por perfil (minimo: `broker`).  
3. Criar acao rapida `Enviar para corretores` em "Minhas criacoes".  
4. Garantir que assets/link gerados possam ser anexados/referenciados no comunicado.

## Regras de protecao de custo

- Limite por usuario/hora (`gamma_max_generations_per_hour`).
- Polling com backoff (ex.: 30s -> 60s -> 120s -> max 5min).
- Max tentativas por geracao (ex.: 60).
- Nao logar API key.
- Logar `request_id` de resposta do Gamma quando disponivel.

## Checklist de validacao

- Teste de conexao retorna sucesso com chave valida.
- Usuario comum nao acessa geracoes de outro usuario.
- Admin visualiza todas as geracoes.
- `webpage` cria link `/go/{slug}` e incrementa view.
- `pdf/pptx` baixado e salvo localmente.
- expiracao de export marcada como `expired` com acao de regerar.

## Amostras que ainda faltam para fechar implementacao

1. resposta real de `POST /generations/from-template` (sucesso e erro).
2. resposta real de `GET /generations/{generationId}` com `exportAs` preenchido e links de arquivo.
3. exemplo de expiracao de link de export (quando existir) para mapear `expired`.

Pode mascarar dados sensiveis; o importante e manter os nomes de campos.
