# Migração do sistema legislativo antigo para o Leggov

Este documento é o passo a passo para **você** executar no servidor de produção. Nada aqui foi executado nesta sessão — o comando foi criado, testado com fixtures locais, e revisado estaticamente, mas nunca rodou contra um banco MariaDB real nem contra produção.

## 1. Visão geral

```
MariaDB (servidor)
├── leggov_antigo      ← origem, SOMENTE LEITURA, nunca alterado
└── leggov_arapiraca   ← destino, banco atual do Leggov em produção

php artisan leggov:migrar-legado --dry-run   ← primeiro comando a rodar
php artisan leggov:migrar-legado             ← só depois de aprovar o dry-run
```

O migrador é **aditivo**: nunca faz `TRUNCATE`/`DELETE` em massa. Cada entidade (legislatura, vereador, matéria, sessão, lei...) é casada por **chave natural** (e-mail, número+ano+tipo, etc.) com o que já existe no Leggov — se encontra, reaproveita; se não encontra, cria. Rodar o comando mais de uma vez não duplica nada.

## 2. Preparar o banco legado no servidor

```bash
# 1. Criar o banco (nome sugerido: leggov_antigo)
mysql -u root -p -e "CREATE DATABASE leggov_antigo CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"

# 2. Criar um usuário SOMENTE LEITURA pra esse banco (recomendado — ver seção 5)
mysql -u root -p -e "
  CREATE USER 'leggov_legado_ro'@'localhost' IDENTIFIED BY 'SENHA_FORTE_AQUI';
  GRANT SELECT ON leggov_antigo.* TO 'leggov_legado_ro'@'localhost';
  FLUSH PRIVILEGES;
"

# 3. Restaurar o dump do sistema antigo nesse banco
mysql -u root -p leggov_antigo < /caminho/para/antigo.sql
```

**IMPORTANTE**: nunca restaure esse dump por cima de `leggov_arapiraca`. É um banco novo, separado, só para servir de origem de leitura.

## 3. Configurar a conexão `legacy` no `.env`

Adicione (ou confirme, se já tiver copiado este `.env`) ao final do `.env` de produção:

```
LEGACY_DB_HOST=127.0.0.1
LEGACY_DB_PORT=3306
LEGACY_DB_DATABASE=leggov_antigo
LEGACY_DB_USERNAME=leggov_legado_ro
LEGACY_DB_PASSWORD=SENHA_FORTE_AQUI
```

Nunca use aqui as mesmas credenciais/banco do `DB_DATABASE` de produção — o comando **bloqueia automaticamente** se `LEGACY_DB_DATABASE` for igual a `DB_DATABASE` (mesmo host+porta+nome), como proteção contra apontar os dois pro mesmo lugar por engano.

## 4. Limpar cache de configuração e testar a conexão

```bash
cd /var/www/leggov-arapiraca
php artisan config:clear

php artisan tinker --execute="DB::connection('legacy')->select('SELECT 1'); echo 'OK';"
```

Se der erro aqui, revise host/porta/usuário/senha antes de continuar — não adianta rodar o comando com a conexão quebrada.

## 5. Por que um usuário MariaDB só-leitura, além da proteção no código

O comando já trava a sessão da conexão `legacy` com `SET SESSION TRANSACTION READ ONLY` assim que valida as conexões — a partir daí, o próprio MariaDB rejeita qualquer `INSERT`/`UPDATE`/`DELETE`/`TRUNCATE`/`ALTER`/`DROP`/`CREATE` tentado nela, mesmo que fosse por um bug futuro em algum Importador. Ainda assim, a recomendação de usar um usuário `GRANT SELECT` (passo 2) é a proteção mais forte que existe, porque não depende de nenhuma linha de código do Leggov — funciona mesmo se alguém rodar SQL manual usando essas credenciais.

## 6. Rodar o dry-run (primeiro comando, sempre)

```bash
php artisan leggov:migrar-legado --dry-run
```

Isso:

- valida que origem ≠ destino;
- testa as duas conexões;
- trava a conexão legacy em somente leitura;
- roda a análise completa (contagens, conflitos, plano) **sem escrever nada em nenhum dos dois bancos**;
- imprime o relatório no terminal;
- grava uma cópia em `storage/logs/migracao_legado_dry_run_AAAAMMDD_HHMMSS.log`.

## 7. Como interpretar o relatório

- **Legado / Seriam importados / Conflitos** — por entidade. "Seriam importados" inclui tanto registros novos quanto os que já existem no Leggov (casados por chave natural, reaproveitados).
- **PROBLEMAS** — classificados em `AVISO` (não bloqueia nada, só informa uma decisão automática tomada, ex.: tipo de comissão sem equivalente exato), `CONFLITO` (um registro específico foi ignorado — normalmente FK sem correspondência) e `CRITICO` (bloqueia o modo real inteiro).
- **RESULTADO: PRONTO PARA MIGRAÇÃO** — `SIM` só quando não há nenhum `CRITICO`. Se estiver `NÃO`, resolva os itens críticos (normalmente exigem ajuste manual no legado ou no destino) e rode o dry-run de novo.

## 8. Só depois de aprovar o dry-run: modo real

```bash
php artisan leggov:migrar-legado
```

O comando:

1. roda a mesma análise de novo (sempre fresca, nunca reaproveita um dry-run antigo);
2. se achar qualquer `CRITICO`, bloqueia — nem chega a perguntar a confirmação;
3. senão, avisa que vai alterar dados, pede para confirmar que existe backup recente, e pede a frase exata `MIGRAR LEGGOV`;
4. qualquer resposta diferente cancela, sem alterar nada;
5. confirmado, roda tudo dentro de uma transação no banco de destino — qualquer erro no meio faz rollback completo (nada fica pela metade);
6. grava o relatório final em `storage/logs/migracao_legado_real_AAAAMMDD_HHMMSS.log`.

**Confirme que existe um backup recente do `leggov_arapiraca` antes de digitar a confirmação** — mesmo sendo aditivo e transacional, é a prática correta antes de qualquer migração de dados em produção.

## 9. Depois da migração

- Os PDFs referenciados (leis, matérias) **não são copiados por este comando** — só a referência ao caminho é migrada, preservando o nome original do arquivo. Copie os arquivos físicos manualmente para `storage/app/public/leis/`, `storage/app/public/materias/` etc., usando exatamente os mesmos nomes já gravados no banco.
- Vereadores recém-criados pela migração nascem com uma senha aleatória inutilizável — eles precisam passar pelo fluxo de "definir senha" do Leggov (usa o mesmo `setup_token` já usado para qualquer usuário novo do sistema).
- Revise a seção `PROBLEMAS` do log real gerado — `AVISO`s não impediram a migração, mas podem indicar dados que valem uma checagem manual (ex.: matérias/leis onde o ano teve que ser recuperado a partir do número por falta de data válida no legado).

## 10. Rodando os testes automatizados deste módulo

A maior parte da suíte (`tests/Feature/Migracao/*ImportadorTest.php`) valida a lógica de mapeamento usando um SQLite em memória como origem de teste — roda em qualquer ambiente, inclusive sem MariaDB:

```bash
php artisan test --filter=Migracao
```

Um pequeno grupo de testes (`LegacyGuardTest::test_trava_somente_leitura...`, e a maioria de `MigrarLegadoCommandTest`) testa comportamento exclusivo do MySQL/MariaDB (`SET SESSION TRANSACTION READ ONLY`) e por segurança **só roda com opt-in explícito**:

```bash
MIGRACAO_TESTES_MARIADB_REAL=true php artisan test --filter=Migracao
```

Só ligue essa variável quando `LEGACY_DB_DATABASE` apontar para uma cópia **descartável** do legado (nunca o dump real de produção) — esses testes criam e removem tabelas próprias (`legislaturas`, `usuarios`, `materias` etc.) na conexão `legacy` configurada.

## 11. O que este comando NUNCA faz

- Nunca roda `migrate:fresh`, `migrate:refresh` ou `db:wipe`.
- Nunca executa `DROP DATABASE`.
- Nunca faz `TRUNCATE` em nenhuma tabela.
- Nunca escreve na conexão `legacy` (nem em modo real).
- Nunca altera operadores/administradores existentes no Leggov.
- Nunca cria ou altera protocolos existentes.
- Nunca infere vínculo Lei↔Matéria ou Lei↔Protocolo por coincidência de número — só quando há evidência real no legado.
- Nunca continua em modo real se houver um problema `CRITICO` pendente, mesmo com a confirmação correta.
