-- ============================================================================
-- MÓDULO AGENTE — SQL CONSOLIDADO PARA PRODUÇÃO (tefnet_erp)
-- ============================================================================
-- Gerado em: 11/05/2026
-- Origem:    /Applications/MAMP/htdocs/modulo_agente/sql/migrations/
-- Total:     38 migrations (núcleo + seeds essenciais)
-- Excluído:  seeds DEV de carteira REDE HG (ver arquivo agente_seeds_DEV_REDEHG.sql)
--            backfill 278/417 (agentes específicos do MAMP)
--            alter_idcep_bigint_to_varchar (ver agente_fix_OPCIONAL_idcep.sql)
--
-- ORDEM DE EXECUÇÃO:
--   1. BACKUP do banco de produção
--   2. Aplicar este arquivo: mysql tefnet_erp < agente_modulo_PRODUCAO.sql
--   3. Sincronizar 6 pontos de tbl_Permissao no PHP do newportaltefnet
--      (view + inserirPerfil + updatePerfil + updateUsuario + selectUserEdit + selectUserEditPerm)
--      conforme CLAUDE.md item 24 — flags adicionadas pela Migration 009.
--   4. Deploy do código PHP/JS do módulo agente
--
-- NÃO RODAR EM TRANSAÇÃO ÚNICA: contém ALTER TABLE (DDL) que faz commit
-- implícito, mais várias migrations independentes. Roda sequencialmente.
--
-- IDEMPOTÊNCIA:
--   - Tabela agente_migrations registra aplicação.
--   - Cada migration termina com INSERT IGNORE em agente_migrations.
--   - Re-rodar este arquivo APÓS aplicado mostra erros "Duplicate column"
--     etc. — esperado. Use INFORMATION_SCHEMA pra confirmar estado.
--
-- COMPATIBILIDADE:
--   - MySQL 5.7+ / 8.x
--   - Strict mode: tratado caso a caso (SET SESSION sql_mode = '' nas
--     migrations que precisam, restaurado no fim).
--   - Engine: InnoDB (default no projeto), MyISAM legacy preservada onde
--     existe (tbl_Pedido, tbl_HistPedido).
--
-- ============================================================================

-- ============================================================================
-- TABELA DE CONTROLE
-- ============================================================================
CREATE TABLE IF NOT EXISTS agente_migrations (
    id INT UNSIGNED NOT NULL AUTO_INCREMENT,
    version VARCHAR(160) NOT NULL,
    applied_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    applied_by VARCHAR(160) DEFAULT NULL,
    duration_ms INT UNSIGNED DEFAULT NULL,
    direction ENUM('up','down') NOT NULL DEFAULT 'up',
    notes TEXT DEFAULT NULL,
    PRIMARY KEY (id),
    UNIQUE KEY uq_version (version, direction)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;


-- ============================================================================
-- 20260505_001_alter_tbl_representante
-- ============================================================================
-- Migration 001 — ALTER tbl_Representante para suportar tipo Agente (idNatureza=3)
-- PRD: docs/PRDs/PRD-0002-modelo-agente/PRD-0002-modelo-agente.md
-- DT:  docs/DTs/DT-0001-impacto-schema-tefnet-erp.md
-- ADR: docs/ADRs/ADR-0001-representacao-agente-tbl-representante.md
-- Card: INT#1 (roadmap)
-- Data: 05/05/2026
--
-- AJUSTE: o indice em idNatureza ja existe como `fk_IdNaturzaRepresentante`.
-- Por isso NAO criamos `idx_repr_natureza` (seria duplicado).
-- Criamos apenas `idx_repr_agente_vinculado` (campo novo).

ALTER TABLE tbl_Representante
  ADD COLUMN cod_Agente_vinculado INT NULL DEFAULT NULL
    COMMENT 'FK pra outro tbl_Representante.id quando vinculado a um Agente (Premium/Standard ↔ Agente)',
  ADD COLUMN agente_modalidade ENUM('pct_venda','pct_comissao','tabela_preco') NULL DEFAULT NULL
    COMMENT 'Aplicavel quando idNatureza=3 (Agente)',
  ADD COLUMN agente_pct_padrao DECIMAL(8,4) NULL DEFAULT NULL
    COMMENT 'Percentual padrao quando modalidade=pct_venda ou pct_comissao',
  ADD COLUMN agente_ativo TINYINT(1) NOT NULL DEFAULT 0
    COMMENT '0=inativo, 1=ativo. So tem efeito quando idNatureza=3',
  ADD INDEX idx_repr_agente_vinculado (cod_Agente_vinculado);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_001_alter_tbl_representante', 'up', 'consolidado producao');


-- ============================================================================
-- 20260505_002_alter_tbl_pedido
-- ============================================================================
-- Migration 002 — ALTER tbl_Pedido para snapshot do agente
-- Card: INT#2
-- Data: 05/05/2026

ALTER TABLE tbl_Pedido
  ADD COLUMN cod_Agente INT NULL DEFAULT NULL
    COMMENT 'Snapshot do agente vinculado a revenda no momento do pedido (FK soft tbl_Representante.id idNatureza=3)',
  ADD COLUMN pct_agente DECIMAL(8,4) NULL DEFAULT NULL
    COMMENT 'Snapshot do percentual aplicado',
  ADD COLUMN modalidade_agente_snap ENUM('pct_venda','pct_comissao','tabela_preco') NULL DEFAULT NULL,
  ADD INDEX idx_pedido_agente (cod_Agente);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_002_alter_tbl_pedido', 'up', 'consolidado producao');


-- ============================================================================
-- 20260505_003_create_agente_detalhe
-- ============================================================================
-- Migration 003 — CREATE agente_detalhe
-- 1:1 com tbl_Representante quando idNatureza=3 (Agente)
-- Card: AG#1 / INT#1 (parte 2)

CREATE TABLE IF NOT EXISTS agente_detalhe (
  id INT PRIMARY KEY AUTO_INCREMENT,
  cod_Representante INT NOT NULL,
  observacao TEXT NULL,
  banco_pagamento VARCHAR(120) NULL,
  pix_chave VARCHAR(120) NULL,
  conta_corrente VARCHAR(40) NULL,
  agencia VARCHAR(20) NULL,
  data_inicio DATE NOT NULL,
  data_fim DATE NULL,
  situacao TINYINT(1) NOT NULL DEFAULT 1 COMMENT '0=inativo,1=ativo,2=excluido (soft)',
  UNIQUE KEY uk_agente_repr (cod_Representante),
  INDEX idx_agente_situacao (situacao)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_003_create_agente_detalhe', 'up', 'consolidado producao');


-- ============================================================================
-- 20260505_004_create_agente_tabela_preco
-- ============================================================================
-- Migration 004 — CREATE agente_tabela_preco
-- Tabela de precos quando agente_modalidade=tabela_preco
-- Card: AG#3 (parte schema)

CREATE TABLE IF NOT EXISTS agente_tabela_preco (
  id INT PRIMARY KEY AUTO_INCREMENT,
  cod_Representante INT NOT NULL,
  tipo_chave ENUM('produto','categoria') NOT NULL,
  chave_valor VARCHAR(80) NOT NULL,
  tipo_valor ENUM('percentual','fixo') NOT NULL,
  valor DECIMAL(14,4) NOT NULL,
  data_inicio DATE NOT NULL,
  data_fim DATE NULL,
  situacao TINYINT(1) NOT NULL DEFAULT 1,
  INDEX idx_atp_repr_chave (cod_Representante, tipo_chave, chave_valor),
  INDEX idx_atp_situacao (situacao)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_004_create_agente_tabela_preco', 'up', 'consolidado producao');


-- ============================================================================
-- 20260505_005_create_agente_apuracao
-- ============================================================================
-- Migration 005 — CREATE agente_apuracao_periodos + agente_apuracao_itens
-- Snapshot por agente×competencia + breakdown linha-a-linha por titulo pago
-- Espelha apuracao_periodos + apuracao_detalhes do ApuraComercial
-- Card: AP#1

CREATE TABLE IF NOT EXISTS agente_apuracao_periodos (
  id INT PRIMARY KEY AUTO_INCREMENT,
  cod_Representante INT NOT NULL COMMENT 'O agente (idNatureza=3)',
  competencia CHAR(7) NOT NULL COMMENT 'YYYY-MM',
  modalidade_snap ENUM('pct_venda','pct_comissao','tabela_preco') NOT NULL,
  pct_padrao_snap DECIMAL(8,4) NULL,
  total_titulos_pagos DECIMAL(14,2) NOT NULL DEFAULT 0,
  total_comissao DECIMAL(14,2) NOT NULL DEFAULT 0,
  total_disponivel DECIMAL(14,2) NOT NULL DEFAULT 0,
  total_em_lote DECIMAL(14,2) NOT NULL DEFAULT 0,
  total_liquidado DECIMAL(14,2) NOT NULL DEFAULT 0,
  status_ciclo ENUM('prevista','apurada','fechada') NOT NULL DEFAULT 'prevista',
  apurada_at DATETIME NULL,
  apurada_by INT NULL,
  fechada_at DATETIME NULL,
  fechada_by INT NULL,
  reaberta_at DATETIME NULL,
  reaberta_by INT NULL,
  dirty TINYINT(1) NOT NULL DEFAULT 0,
  dirty_em DATETIME NULL,
  dirty_motivo VARCHAR(200) NULL,
  situacao TINYINT(1) NOT NULL DEFAULT 1,
  UNIQUE KEY uk_apur_agente_competencia (cod_Representante, competencia),
  INDEX idx_apur_status (status_ciclo, dirty),
  INDEX idx_apur_competencia (competencia)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS agente_apuracao_itens (
  id INT PRIMARY KEY AUTO_INCREMENT,
  apuracao_id INT NOT NULL,
  cod_Pedido_snap INT NOT NULL,
  id_titulo_snap INT NOT NULL COMMENT 'tbl_Boleto.id ou tbl_Faturamento.id',
  fonte_titulo ENUM('boleto','faturamento') NOT NULL,
  cod_Cliente INT NOT NULL,
  data_pag DATE NOT NULL,
  valor_base DECIMAL(14,2) NOT NULL,
  pct_aplicado DECIMAL(8,4) NULL,
  comissao DECIMAL(14,2) NOT NULL,
  regra_aplicada VARCHAR(160) NOT NULL COMMENT 'Texto humano-legivel da regra',
  status_item ENUM('disponivel','em_lote','liquidado','estornado') NOT NULL DEFAULT 'disponivel',
  lote_id INT NULL,
  situacao TINYINT(1) NOT NULL DEFAULT 1,
  UNIQUE KEY uk_apur_titulo (id_titulo_snap, fonte_titulo) COMMENT 'idempotencia: 1 titulo so pode estar em 1 apuracao',
  INDEX idx_apur_item_apur (apuracao_id, status_item),
  INDEX idx_apur_item_lote (lote_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_005_create_agente_apuracao', 'up', 'consolidado producao');


-- ============================================================================
-- 20260505_006_create_agente_lote
-- ============================================================================
-- Migration 006 — CREATE agente_lote_resgate + agente_lote_item + agente_critica_resgate
-- Lote (entidade transacional unica do ciclo de pagamento) + vinculo com itens + critica blocker
-- Card: AP#5

CREATE TABLE IF NOT EXISTS agente_lote_resgate (
  id INT PRIMARY KEY AUTO_INCREMENT,
  numero_humano VARCHAR(20) NOT NULL COMMENT 'LR-YYYY-NNNN',
  cod_Representante INT NOT NULL,
  data_resgate DATETIME NOT NULL COMMENT 'capturado no cliente',
  total DECIMAL(14,2) NOT NULL,
  status_lote ENUM('aguardando_pagamento','pago','liquidado','estornado') NOT NULL DEFAULT 'aguardando_pagamento',
  data_pag DATETIME NULL,
  forma_pag ENUM('pix','ted','boleto','outros') NULL,
  comprovante_hash VARCHAR(64) NULL COMMENT 'hash_temp pos-upload',
  observacao TEXT NULL,
  liquidado_at DATETIME NULL,
  liquidado_by INT NULL,
  estornado_at DATETIME NULL,
  estornado_by INT NULL,
  estorno_motivo VARCHAR(240) NULL,
  situacao TINYINT(1) NOT NULL DEFAULT 1,
  UNIQUE KEY uk_lote_numero (numero_humano),
  INDEX idx_lote_repr_status (cod_Representante, status_lote),
  INDEX idx_lote_data (data_resgate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS agente_lote_item (
  id INT PRIMARY KEY AUTO_INCREMENT,
  lote_id INT NOT NULL,
  apuracao_item_id INT NOT NULL,
  valor_snap DECIMAL(14,2) NOT NULL,
  UNIQUE KEY uk_lote_item (apuracao_item_id) COMMENT '1 item de apuracao em no maximo 1 lote nao-estornado',
  INDEX idx_lote_item_lote (lote_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS agente_critica_resgate (
  id INT PRIMARY KEY AUTO_INCREMENT,
  cod_Representante INT NOT NULL,
  competencia CHAR(7) NULL COMMENT 'NULL=critica geral; preenchido=especifica',
  motivo VARCHAR(200) NOT NULL,
  bloqueia_resgate TINYINT(1) NOT NULL DEFAULT 1,
  ativa TINYINT(1) NOT NULL DEFAULT 1,
  criado_at DATETIME NOT NULL,
  criado_by INT NOT NULL,
  resolvido_at DATETIME NULL,
  resolvido_by INT NULL,
  INDEX idx_critica_repr (cod_Representante, ativa)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_006_create_agente_lote', 'up', 'consolidado producao');


-- ============================================================================
-- 20260505_007_create_agente_hist
-- ============================================================================
-- Migration 007 — CREATE 4 tabelas historico-sombra
-- Estrutura comum: campo, valor_antigo, valor_novo, alterado_at/by, origem
-- Card: AP#11

CREATE TABLE IF NOT EXISTS agente_hist_detalhe (
  id INT PRIMARY KEY AUTO_INCREMENT,
  cod_Representante INT NOT NULL,
  campo VARCHAR(80) NOT NULL,
  valor_antigo TEXT NULL,
  valor_novo TEXT NULL,
  alterado_at DATETIME NOT NULL,
  alterado_by INT NOT NULL,
  origem VARCHAR(120) NOT NULL,
  INDEX idx_hist_det_repr (cod_Representante, alterado_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS agente_hist_apuracao (
  id INT PRIMARY KEY AUTO_INCREMENT,
  apuracao_id INT NOT NULL,
  campo VARCHAR(80) NOT NULL,
  valor_antigo TEXT NULL,
  valor_novo TEXT NULL,
  alterado_at DATETIME NOT NULL,
  alterado_by INT NOT NULL,
  origem VARCHAR(120) NOT NULL,
  INDEX idx_hist_apur (apuracao_id, alterado_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS agente_hist_lote (
  id INT PRIMARY KEY AUTO_INCREMENT,
  lote_id INT NOT NULL,
  campo VARCHAR(80) NOT NULL,
  valor_antigo TEXT NULL,
  valor_novo TEXT NULL,
  alterado_at DATETIME NOT NULL,
  alterado_by INT NOT NULL,
  origem VARCHAR(120) NOT NULL,
  INDEX idx_hist_lote (lote_id, alterado_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

CREATE TABLE IF NOT EXISTS agente_hist_tabela_preco (
  id INT PRIMARY KEY AUTO_INCREMENT,
  agente_tabela_preco_id INT NOT NULL,
  campo VARCHAR(80) NOT NULL,
  valor_antigo TEXT NULL,
  valor_novo TEXT NULL,
  alterado_at DATETIME NOT NULL,
  alterado_by INT NOT NULL,
  origem VARCHAR(120) NOT NULL,
  INDEX idx_hist_atp (agente_tabela_preco_id, alterado_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260505_007_create_agente_hist', 'up', 'consolidado producao');


-- ============================================================================
-- 20260506_008_rename_agente_columns
-- ============================================================================
-- Migration 008 — RENAME colunas para prefixo padrao `agente_` (ADR-0004) — FASE 1
-- PRD: docs/PRDs/PRD-0002-modelo-agente/PRD-0002-modelo-agente.md
-- ADR: docs/ADRs/ADR-0004-prefixo-colunas-projeto-agente.md
-- Card: INT#3 (roadmap)
-- Data: 06/05/2026
--
-- ESCOPO FASE 1 (esta migration): renomeia apenas colunas em `tbl_Pedido` —
-- nenhuma delas e usada por sistemas correlatos (verificado por grep em
-- newportaltefnet/, ApuraComercial/, new-dashboard-tef/, ticket-grupo-porto/).
--
-- Renomeia:
--   tbl_Pedido.cod_Agente              -> agente_cod_snap
--   tbl_Pedido.pct_agente              -> agente_pct_snap
--   tbl_Pedido.modalidade_agente_snap  -> agente_modalidade_snap
--
-- E renomeia o indice correspondente:
--   idx_pedido_agente  -> idx_pedido_agente_cod_snap
--
-- FASE 2 (NAO inclusa aqui): renomeio de tbl_Representante.cod_Agente_vinculado
-- depende de coordenacao com AG#2-M (toca newportaltefnet — sistema vivo,
-- ja le/escreve essa coluna em revenda.php e updateRevenda_V16.php).
-- Sera tratado em migration futura quando AG#2-M for executado.

ALTER TABLE tbl_Pedido
  CHANGE COLUMN cod_Agente             agente_cod_snap         INT NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot do agente vinculado a revenda no momento do pedido (FK soft tbl_Representante.id idNatureza=3)',
  CHANGE COLUMN pct_agente             agente_pct_snap         DECIMAL(8,4) NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot do percentual aplicado',
  CHANGE COLUMN modalidade_agente_snap agente_modalidade_snap  ENUM('pct_venda','pct_comissao','tabela_preco') NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot da modalidade de comissao no momento do pedido',
  RENAME INDEX idx_pedido_agente TO idx_pedido_agente_cod_snap;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260506_008_rename_agente_columns', 'up', 'consolidado producao');


-- ============================================================================
-- 20260506_009_alter_tbl_permissao_flags_agente
-- ============================================================================
-- Migration 009 — ALTER tbl_Permissao adicionando 11 flags do satelite agente
-- PRD: docs/PRDs/PRD-0002-modelo-agente/PRD-0002-modelo-agente.md
-- ADR: docs/ADRs/ADR-0004-prefixo-colunas-projeto-agente.md
-- Card: AUTH#1 (roadmap — em 🔵 progresso)
-- Data: 06/05/2026
--
-- ESCOPO: adiciona 11 colunas char(1) 'S'/'N' em tbl_Permissao (tabela do
-- newportaltefnet) seguindo padrao ADR-0004 (prefixo `agente_`). Cada flag
-- corresponde a uma autorizacao verificada por `auth_required()` nos
-- endpoints do satelite agente.
--
-- NOMENCLATURA: snake_case com prefixo `agente_` (decisao consolidada
-- 06/05/2026 entre dono e dev — vide PERGUNTAS.md de AUTH#1). Quebra padrao
-- camelCase historico do tbl_Permissao deliberadamente, em troca de
-- identidade cristalina do dono do satelite.
--
-- DEFAULT 'N': nenhum perfil ganha permissao automatica. Admin habilita
-- explicitamente quem precisa. Usuarios logados precisam relogar pra ver
-- permissao nova (limitacao do mecanismo $_SESSION existente — abordado
-- pelo endpoint refreshPermissao.php em passo posterior do AUTH#1).
--
-- ROLLBACK: vide 20260506_009_alter_tbl_permissao_flags_agente.down.sql
--
-- AGRUPAMENTO LOGICO (refletido em tblPermission.php):
--   Cadastro:  agente_ver, agente_criar, agente_editar, agente_vincular, agente_externo
--   Apuracao:  agente_pct_editar, agente_apurar, agente_fechar, agente_diretoria
--   Lote:      agente_lote_ver, agente_lote_liquidar

ALTER TABLE tbl_Permissao
  ADD COLUMN agente_ver           CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Ver listagem de agentes externos',
  ADD COLUMN agente_criar         CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Cadastrar novo agente',
  ADD COLUMN agente_editar        CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Editar dados de agente existente',
  ADD COLUMN agente_vincular      CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Vincular agente a revenda Premium/Standard',
  ADD COLUMN agente_externo       CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Marca perfil como Agente Externo (acesso reduzido a proprio painel)',
  ADD COLUMN agente_pct_editar    CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Editar percentual do agente em pedido especifico',
  ADD COLUMN agente_apurar        CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Rodar apuracao de competencia',
  ADD COLUMN agente_fechar        CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Fechar competencia apurada (B7)',
  ADD COLUMN agente_diretoria     CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Reabrir competencia fechada / estornar lote (privilegio elevado)',
  ADD COLUMN agente_lote_ver      CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Ver lotes de resgate',
  ADD COLUMN agente_lote_liquidar CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] Liquidar lote (marcar pago + anexar comprovante)';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260506_009_alter_tbl_permissao_flags_agente', 'up', 'consolidado producao');


-- ============================================================================
-- 20260506_010_rename_cod_agente_vinculado
-- ============================================================================
-- Migration 010 — Fase 2 do INT#3 / ADR-0004 (snake_case agente_*)
-- Card: AG#2-M (em 🔵 Em progresso)
-- Aplicada em: 06/05/2026 turno tarde
--
-- Objetivo: renomear tbl_Representante.cod_Agente_vinculado -> agente_cod_vinculado
-- e ajustar o nome do indice associado pra seguir o mesmo padrao.
--
-- Pre-requisito: zero referencias a cod_Agente_vinculado no PHP do newportaltefnet
-- (verificado via grep em 06/05/2026 turno tarde — confirmado limpo em /novo/ e /cadastro/).

ALTER TABLE tbl_Representante
    CHANGE COLUMN cod_Agente_vinculado agente_cod_vinculado INT NULL;

ALTER TABLE tbl_Representante
    DROP INDEX idx_repr_agente_vinculado,
    ADD INDEX idx_repr_agente_cod_vinculado (agente_cod_vinculado);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260506_010_rename_cod_agente_vinculado', 'up', 'consolidado producao');


-- ============================================================================
-- 20260507_011_create_agente_usuario_vinculo
-- ============================================================================
-- Migration 011 — CREATE TABLE `agente_usuario_vinculo`
-- PRD: docs/PRDs/PRD-0002-modelo-agente/PRD-0002-modelo-agente.md
-- ADR: docs/ADRs/ADR-0003-autenticacao-agente-externo.md
-- Card: AUTH#2 (roadmap) — Passo 0 (parte A)
-- Data: 07/05/2026
--
-- Tabela de juncao entre `tbl_Usuario` (idUsuario) e `tbl_Representante`
-- (cod_Representante onde idNatureza=3). Decisao D5 do AUTH#2: nao reutilizar
-- `tbl_Usuario.idRevenda`, manter vinculo Agente em tabela separada.
--
-- Sem FK fisica para nao acoplar com tabelas legacy do newportaltefnet —
-- integridade garantida em codigo (controller de cadastro de usuario).
--
-- ESCOPO: tabela satelite — nao toca nada do newportaltefnet.

CREATE TABLE `agente_usuario_vinculo` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `id_usuario` INT NOT NULL COMMENT '[satelite:agente] FK soft -> tbl_Usuario.idUsuario (tpUser=Agente)',
  `cod_Representante` INT NOT NULL COMMENT '[satelite:agente] FK soft -> tbl_Representante.id (idNatureza=3)',
  `criado_em` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `criado_por` INT NULL COMMENT '[satelite:agente] FK soft -> tbl_Usuario.idUsuario do admin que cadastrou',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uq_agente_uv_id_usuario` (`id_usuario`),
  KEY `idx_agente_uv_cod_repr` (`cod_Representante`),
  KEY `idx_agente_uv_criado_em` (`criado_em`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='[satelite:agente] AUTH#2 - vinculo entre usuario do tpUser=Agente e revenda agente em tbl_Representante';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260507_011_create_agente_usuario_vinculo', 'up', 'consolidado producao');


-- ============================================================================
-- 20260507_012_alter_tbl_usuario_senha_provisoria
-- ============================================================================
-- Migration 012 — ALTER `tbl_Usuario` ADD `senha_provisoria`
-- PRD: docs/PRDs/PRD-0002-modelo-agente/PRD-0002-modelo-agente.md
-- ADR: docs/ADRs/ADR-0003-autenticacao-agente-externo.md
-- Card: AUTH#2 (roadmap) — Passo 0 (parte B)
-- Data: 07/05/2026
--
-- ESCOPO: ALTER em tabela COMPARTILHADA com newportaltefnet.
-- Autorizacao explicita do Stakeholder Leader em 06/05/2026 turno noite
-- ("pode passo 0 AUTH#2 — autorizar Migration 012", apos disclaimer
-- explicito sobre risco de tabela compartilhada).
--
-- Por que ENUM('S','N'):
--   * Padrao do newportaltefnet (nao usa BOOLEAN).
--   * Default 'N' = compativel com usuarios existentes (nao foram criados
--     com senha provisoria; nao serao forcados a trocar).
--
-- Coluna nullable=NO + default 'N' = backfill automatico em todas as linhas
-- existentes na hora do ALTER. Sem janela inconsistente.
--
-- Sem prefixo `agente_` porque a flag e generica de seguranca de senha
-- (vale para qualquer tpUser, nao so Agente). Aplica ADR-0004 ao contexto:
-- prefixo so quando a coluna e exclusiva do satelite agente.

ALTER TABLE tbl_Usuario
  ADD COLUMN `senha_provisoria` ENUM('S','N') NOT NULL DEFAULT 'N'
    COMMENT 'AUTH#2 - S=usuario deve trocar senha no proximo login (default N)';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260507_012_alter_tbl_usuario_senha_provisoria', 'up', 'consolidado producao');


-- ============================================================================
-- 20260507_013_seed_natureza_agente
-- ============================================================================
-- Migration 013 — seed da Natureza/TipoRevenda "Agente" (id=3)
-- Justificativa: o satélite agente classifica parceiros em tbl_Representante via idNatureza=3.
-- O dropdown "Natureza" da tela de revenda do newportaltefnet (cadastro/view/revenda.php)
-- popula a partir de tbl_TipoRevenda; já as listagens (selectRevenda.php) e selectRevendaEdit
-- fazem INNER JOIN com tbl_Natureza. Sem o registro pai em ambas, parceiros marcados como
-- Agente desaparecem da consulta e não há opção para promover/editar via UI.
-- Seed idempotente.

INSERT INTO tbl_Natureza (id, natureza)
VALUES (3, 'Agente')
ON DUPLICATE KEY UPDATE natureza = VALUES(natureza);

INSERT INTO tbl_TipoRevenda (id, nome)
VALUES (3, 'Agente')
ON DUPLICATE KEY UPDATE nome = VALUES(nome);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260507_013_seed_natureza_agente', 'up', 'consolidado producao');


-- ============================================================================
-- 20260508_014_alter_tbl_faturamento_snapshot_trigger_e_tbl_pedido_override
-- ============================================================================
-- ============================================================================
-- Migration 014 — Propagacao do snapshot do agente para tbl_Faturamento via TRIGGER
--                + Flag agente_snap_override em tbl_Pedido
-- ============================================================================
-- PRD:  docs/PRDs/PRD-0006-propagacao-snapshot-agente/PRD-0006-propagacao-snapshot-agente.md
-- ADR:  docs/ADRs/ADR-0005-trigger-propagacao-snapshot-faturamento.md
-- Card: INT#5 (roadmap) — Passo 2
-- Data: 08/05/2026
-- Decidido por: Giovanny Porto (Stakeholder Leader) em 08/05/2026
--
-- ============================================================================
-- ESCOPO
-- ============================================================================
-- 1. ALTER TABLE tbl_Faturamento ADD 3 colunas snapshot do agente.
-- 2. ALTER TABLE tbl_Pedido      ADD coluna agente_snap_override (flag override manual).
-- 3. CREATE TRIGGER trg_agente_snapshot_faturamento_bi (BEFORE INSERT em tbl_Faturamento).
-- 4. CREATE INDEX em tbl_Faturamento.agente_cod_snap (relatorios filtram por agente).
--
-- ESCOPO: ALTER em 2 tabelas COMPARTILHADAS com newportaltefnet/ApuraComercial.
-- Autorizacao explicita do Stakeholder Leader em 08/05/2026 para o ALTER nas 2 tabelas.
-- Procedures pr_generate_standart / pr_generate_premium / variantes _rev permanecem
-- INTACTAS. Zero risco de regressao em codigo legado nao testado ha anos (ADR-0005 D-13).
--
-- ============================================================================
-- DECISAO ARQUITETURAL — POR QUE TRIGGER (ADR-0005)
-- ============================================================================
-- 3 alternativas analisadas em sessao 08/05/2026 com o Stakeholder Leader:
--
-- (A) ALTER PROCEDURE pr_generate_standart / pr_generate_premium / *_rev
--     Vantagem: snapshot consistente desde o nascimento da linha.
--     Desvantagem: alto risco em legado (procedures nao testadas ha anos);
--                  4+ procedures alteradas multiplica vetores de erro;
--                  se quebrar, faturamento mensal inteiro para.
--     Veredito: descartada.
--
-- (B) UPDATE pos-CALL no PHP (gerar_faturamento.php)
--     Vantagem: zero alteracao em procedure; reversivel em segundos.
--     Desvantagem CRITICA: erro silencioso por dependencia humana
--                         (caller futuro esquece UPDATE -> snapshot perdido sem ninguem
--                          notar ate alguem reclamar de comissao errada meses depois);
--                         janela de NULL nao-teorica (UPDATE pode falhar por timeout/lock).
--     Veredito: descartada (Stakeholder Leader apontou a fragilidade em 08/05/2026).
--
-- (C) TRIGGER BEFORE INSERT em tbl_Faturamento  <-- ESCOLHIDA
--     Vantagem: atomicidade real (mesma transacao do INSERT);
--               a prova de caller (qualquer rota que insira recebe snapshot);
--               resiliente a refactor das procedures (atua no NEW.* independente da forma);
--               zero alteracao em procedure legada;
--               rollback simetrico (DROP TRIGGER + DROP COLUMN em 2 comandos).
--     Mitigacoes: COMMENT em colunas apontando pro trigger;
--                 documentacao no PRD-0006 e CLAUDE.md da pasta faturamento;
--                 entrada no inventario de objetos DB.
--
-- ============================================================================

-- ----------------------------------------------------------------------------
-- 0) Workaround sql_mode strict (MySQL 8 + dados legados com '0000-00-00')
-- ----------------------------------------------------------------------------
-- Linhas legadas em tbl_Pedido tem date_solic_cancel='0000-00-00' (formato pre-strict).
-- ALTER TABLE em MySQL 8 com sql_mode strict (ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,
-- NO_ZERO_IN_DATE,NO_ZERO_DATE) recusa a operacao com erro 1292.
-- Solucao: relaxar sql_mode SO PARA ESTA SESSAO. Nao afeta nada fora desta migration.
-- Padrao registrado em memory: project_descompasso_schema_mamp_remoto + ambiente_mamp_local.

SET SESSION sql_mode = '';

-- ----------------------------------------------------------------------------
-- 1) ALTER TABLE tbl_Faturamento — adicionar 3 colunas snapshot do agente
-- ----------------------------------------------------------------------------
-- Tipos espelham EXATAMENTE tbl_Pedido.agente_*_snap (definidos em Migration 002 -> 008).
-- COMMENT em cada coluna aponta pro trigger (defesa contra "esquecimento" por dev novo).

ALTER TABLE tbl_Faturamento
  ADD COLUMN agente_cod_snap INT NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot do agente vinculado ao pedido pai. Populado por trigger trg_agente_snapshot_faturamento_bi (ADR-0005). FK soft -> tbl_Representante.id (idNatureza=3)',
  ADD COLUMN agente_pct_snap DECIMAL(8,4) NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot do percentual do agente. Populado por trigger trg_agente_snapshot_faturamento_bi (ADR-0005)',
  ADD COLUMN agente_modalidade_snap ENUM('pct_venda','pct_comissao','tabela_preco') NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot da modalidade do agente. Populado por trigger trg_agente_snapshot_faturamento_bi (ADR-0005)',
  ADD INDEX idx_faturamento_agente_cod_snap (agente_cod_snap);

-- ----------------------------------------------------------------------------
-- 2) ALTER TABLE tbl_Pedido — adicionar flag de override manual
-- ----------------------------------------------------------------------------
-- Flag setada por UI#13 (insertPedido.php) quando o operador tpUser='Tef.Net' escolhe
-- agente diferente do padrao da revenda. Default 'N' (heranca normal). Override 'S'.
-- Visivel apenas para tpUser='Tef.Net' (D-08 do PRD-0006).
-- Padrao S/N (em vez de TINYINT) por consistencia com newportaltefnet (senha_provisoria etc).

ALTER TABLE tbl_Pedido
  ADD COLUMN agente_snap_override CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] S=snapshot escolhido manualmente diferente do padrao da revenda (UI#13). Default N. Visibilidade restrita a tpUser=Tef.Net (D-08 PRD-0006).';

-- ----------------------------------------------------------------------------
-- 3) CREATE TRIGGER trg_agente_snapshot_faturamento_bi
-- ----------------------------------------------------------------------------
-- BEFORE INSERT em tbl_Faturamento (unico momento em MySQL onde SET NEW.* funciona).
-- Le snapshot do pedido pai via NEW.pedido_id e popula NEW.agente_*_snap.
--
-- Defesa em profundidade:
--   * IF NEW.pedido_id IS NOT NULL  -> gate seguro contra linhas orfas
--   * IF NEW.agente_cod_snap IS NULL -> caller que envia explicitamente sobrescreve
--                                       (overrideable; util para backfill controlado)
--   * LIMIT 1 -> garantia tecnica (pedido_id e FK soft, pode duplicar na pratica)
--
-- IMPORTANTE — RELACIONAMENTO tbl_Faturamento.pedido_id -> tbl_Pedido.cod_Pedido
-- (PK de tbl_Pedido e cod_Pedido, NAO id). Confirmado em probe 08/05/2026:
--   SELECT COLUMN_KEY FROM information_schema.COLUMNS
--   WHERE TABLE_SCHEMA='tefnet_erp' AND TABLE_NAME='tbl_Pedido' AND COLUMN_KEY='PRI';
--   -> retorna apenas cod_Pedido (auto_increment).
--
-- Pedidos pre-AG#4 com agente_cod_snap=NULL em tbl_Pedido -> SELECT retorna NULL ->
-- coluna em tbl_Faturamento fica NULL. Comportamento desejado (apuracao ignora).
--
-- Naming: trg_<namespace>_<funcao>_<tabela>_<tipo>
--   trg_                         -> prefixo padrao MySQL para trigger
--   agente_                      -> namespace satelite (ADR-0004)
--   snapshot_faturamento         -> funcao do trigger
--   _bi                          -> sufixo "before insert"

-- ----------------------------------------------------------------------------
-- IMPORTANTE — POR QUE O TRIGGER USA `SET ... IFNULL(...)` EM VEZ DE BEGIN/END/IF
-- ----------------------------------------------------------------------------
-- O runner (sql/migrate.php) usa PDO::exec(), que NAO suporta a instrucao DELIMITER
-- do mysql client. Sem DELIMITER, o ';' interno de BEGIN/END/IF e interpretado como
-- fim de statement, e o SQL quebra com erro 1327 "Undeclared variable: NEW".
--
-- Solucao funcionalmente equivalente: trigger com UM unico statement SET,
-- usando IFNULL(NEW.x, (SELECT...)) para implementar o "if NULL then look up".
-- Vantagens: sem DELIMITER, sem BEGIN/END, sem IF/THEN — 1 statement so;
-- engolido por PDO::exec sem problema.
-- Custo: 3 lookups separados em tbl_Pedido por linha em vez de 1 — todos por
-- PK indexada (cod_Pedido), microssegundos cada. Desprezivel.
--
-- Comportamento:
--   * Se NEW.agente_cod_snap ja vier preenchido -> IFNULL devolve o valor existente
--     (caller que envia explicitamente sobrescreve; overrideable, igual ao plano original).
--   * Se NEW.pedido_id IS NULL -> SELECT nao acha match -> retorna NULL ->
--     IFNULL(NULL, NULL) = NULL. Coluna em tbl_Faturamento fica NULL (esperado).
--   * Se pedido pre-AG#4 (snapshot NULL em tbl_Pedido) -> IFNULL(NULL, NULL) = NULL.
-- ----------------------------------------------------------------------------

DROP TRIGGER IF EXISTS trg_agente_snapshot_faturamento_bi;

CREATE TRIGGER trg_agente_snapshot_faturamento_bi
BEFORE INSERT ON tbl_Faturamento
FOR EACH ROW
SET
    NEW.agente_cod_snap = IFNULL(
        NEW.agente_cod_snap,
        (SELECT p.agente_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)
    ),
    NEW.agente_pct_snap = IFNULL(
        NEW.agente_pct_snap,
        (SELECT p.agente_pct_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)
    ),
    NEW.agente_modalidade_snap = IFNULL(
        NEW.agente_modalidade_snap,
        (SELECT p.agente_modalidade_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)
    );

-- ============================================================================
-- VERIFICACAO POS-MIGRATION (rodar manualmente apos `php sql/migrate.php up`)
-- ============================================================================
-- 1) Conferir colunas em tbl_Faturamento:
--    SHOW COLUMNS FROM tbl_Faturamento LIKE 'agente_%';
--    -> deve retornar: agente_cod_snap, agente_pct_snap, agente_modalidade_snap
--
-- 2) Conferir coluna em tbl_Pedido:
--    SHOW COLUMNS FROM tbl_Pedido LIKE 'agente_snap_override';
--    -> deve retornar: agente_snap_override (CHAR(1) NOT NULL DEFAULT 'N')
--
-- 3) Conferir trigger criado:
--    SHOW TRIGGERS LIKE 'tbl_Faturamento';
--    -> deve listar: trg_agente_snapshot_faturamento_bi (BEFORE INSERT)
--
-- 4) Smoke teste (opcional, se houver pedido de teste com snapshot):
--    INSERT INTO tbl_Faturamento (pedido_id, ...) VALUES (<id_pedido_com_agente>, ...);
--    SELECT agente_cod_snap, agente_pct_snap, agente_modalidade_snap
--    FROM tbl_Faturamento WHERE id = LAST_INSERT_ID();
--    -> 3 colunas devem estar populadas conforme tbl_Pedido do pedido_id.

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260508_014_alter_tbl_faturamento_snapshot_trigger_e_tbl_pedido_override', 'up', 'consolidado producao');


-- ============================================================================
-- 20260508_015_rename_idx_repr_agente_vinculado
-- ============================================================================
-- ============================================================================
-- Migration 015 — Rename do índice `idx_repr_agente_vinculado` em tbl_Representante
-- ============================================================================
-- DT:   docs/DTs/DT-0007-rename-indice-agente-vinculado.md
-- Card: DT#7 (roadmap)
-- Data: 08/05/2026
-- Origem: débito cosmético da Migration 010 (RENAME INDEX falhou no multi-statement
--         por erro espúrio de '0000-00-00' em outra tabela durante o ALTER).
--
-- Coluna `agente_cod_vinculado` (renomeada de `cod_Agente_vinculado` em Migration 010)
-- tem índice ainda chamado `idx_repr_agente_vinculado` (nome legado). Este single-statement
-- resolve sem o bug do multi-statement original.
--
-- Sem ALTER COLUMN. Sem mudança em dados. Sem afeitar queries da aplicação
-- (índice é transparente — MySQL escolhe pelo nome da coluna ou cardinalidade).

-- AJUSTE PRODUCAO (11/05/2026): tornado idempotente pq a Migration 010 já
-- droppa idx_repr_agente_vinculado e cria idx_repr_agente_cod_vinculado.
-- Em prod fresca (rodando todas as migrations em sequência), o índice antigo
-- já foi removido pela 010 — RENAME falharia.
SET @sql = (SELECT IF(
  (SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS
    WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'tbl_Representante'
      AND INDEX_NAME = 'idx_repr_agente_vinculado') > 0,
  'ALTER TABLE tbl_Representante RENAME INDEX idx_repr_agente_vinculado TO idx_repr_agente_cod_vinculado',
  'SELECT "Migration 015 noop — indice ja renomeado pela 010" AS status'
));
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;

-- ============================================================================
-- VERIFICACAO POS-MIGRATION
-- ============================================================================
-- SHOW INDEX FROM tbl_Representante WHERE Key_name LIKE 'idx_repr_agente%';
-- -> Key_name deve ser idx_repr_agente_cod_vinculado (nome canonico ADR-0004).

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260508_015_rename_idx_repr_agente_vinculado', 'up', 'consolidado producao');


-- ============================================================================
-- 20260508_016_alter_tbl_histpedido_snapshot_trigger
-- ============================================================================
-- ============================================================================
-- Migration 016 -- Propagacao do snapshot do agente para tbl_HistPedido via TRIGGER
-- ============================================================================
-- PRD:  docs/PRDs/PRD-0006-propagacao-snapshot-agente/PRD-0006-propagacao-snapshot-agente.md
-- ADR:  docs/ADRs/ADR-0006-trigger-propagacao-snapshot-histpedido.md
--       (extensao do ADR-0005 -- mesmo padrao aplicado a tbl_HistPedido)
-- Card: INT#4 (roadmap)
-- Data: 08/05/2026
-- Decidido por: Giovanny Porto (Stakeholder Leader) em 08/05/2026 noite,
--               apos sessao consolidada da squad agente-pdd-engine.
--
-- ============================================================================
-- ESCOPO
-- ============================================================================
-- 1. ALTER TABLE tbl_HistPedido ADD 3 colunas snapshot do agente.
-- 2. ADD INDEX em tbl_HistPedido.agente_cod_snap.
-- 3. CREATE TRIGGER trg_agente_snapshot_histpedido_bi (BEFORE INSERT em tbl_HistPedido).
--
-- Tabela alterada eh COMPARTILHADA com newportaltefnet (controllers PHP fazem
-- INSERT via setProdutos() em insertPedido.php:234 e updatePedido.php:269).
-- Com trigger, ZERO edit em controller eh necessario -- snapshot eh herdado
-- automaticamente de tbl_Pedido pelo cod_Pedido.
--
-- ============================================================================
-- DECISAO ARQUITETURAL -- POR QUE TRIGGER (ADR-0006, extensao de ADR-0005)
-- ============================================================================
-- A squad analisou 3 opcoes em 08/05/2026 noite:
--
-- (A) Edit-only PHP (caminho original do roadmap)
--     Vantagem: simples, explicito.
--     Desvantagem: caller-fragil (mesmo erro que ADR-0005 rejeitou); precisaria
--                  SELECT extra em updatePedido.php pra pegar snapshot atual de
--                  tbl_Pedido (insertPedido tem $agCodSnap na mao, updatePedido nao).
--                  Amplia superficie de bugs futuros (5+ versoes .bak no diretorio).
--     Veredito: descartada -- mesma fragilidade de (B) do ADR-0005.
--
-- (B) TRIGGER BEFORE INSERT em tbl_HistPedido  <-- ESCOLHIDA
--     Vantagem: atomicidade real (mesma transacao do INSERT);
--               a prova de caller (qualquer rota PHP que insira recebe snapshot);
--               consistente com ADR-0005 (tbl_Faturamento usa o mesmo padrao);
--               zero alteracao em insertPedido.php / updatePedido.php;
--               resiliente a refactor dos controllers.
--
-- (C) Trigger + edit PHP redundante
--     Vantagem: defesa em profundidade dupla.
--     Desvantagem: over-engineering pra ganho marginal.
--     Veredito: descartada.
--
-- ============================================================================
-- WORKAROUNDS APLICADOS
-- ============================================================================
-- 1. SET SESSION sql_mode = '';
--    tbl_HistPedido tem dados legados; ALTER em MySQL 8 strict pode quebrar
--    em qualquer linha com valor invalido em coluna NOT NULL. Padrao registrado
--    em memory: feedback_pdo_runner_nao_suporta_delimiter.md.
--
-- 2. Trigger usa single-statement SET ... IFNULL (sem BEGIN/END/IF):
--    runner sql/migrate.php usa PDO::exec() que NAO suporta DELIMITER.
--    Funcionalidade identica via IFNULL(NEW.x, (SELECT...)) em 1 statement.
--
-- ============================================================================

SET SESSION sql_mode = '';

-- ----------------------------------------------------------------------------
-- 1) ALTER TABLE tbl_HistPedido -- adicionar 3 colunas snapshot
-- ----------------------------------------------------------------------------
-- Tipos espelham EXATAMENTE tbl_Pedido.agente_*_snap (definidos em Migration 002 -> 008)
-- e tbl_Faturamento.agente_*_snap (definidos em Migration 014).
-- COMMENT em cada coluna aponta pro trigger (defesa contra "esquecimento" por dev novo).

ALTER TABLE tbl_HistPedido
  ADD COLUMN agente_cod_snap INT NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot do agente vinculado ao pedido pai (heranca de tbl_Pedido por cod_Pedido). Populado por trigger trg_agente_snapshot_histpedido_bi (ADR-0006). FK soft -> tbl_Representante.id (idNatureza=3)',
  ADD COLUMN agente_pct_snap DECIMAL(8,4) NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot do percentual do agente. Populado por trigger trg_agente_snapshot_histpedido_bi (ADR-0006)',
  ADD COLUMN agente_modalidade_snap ENUM('pct_venda','pct_comissao','tabela_preco') NULL DEFAULT NULL
    COMMENT '[satelite:agente] Snapshot da modalidade do agente. Populado por trigger trg_agente_snapshot_histpedido_bi (ADR-0006)',
  ADD INDEX idx_histpedido_agente_cod_snap (agente_cod_snap);

-- ----------------------------------------------------------------------------
-- 2) CREATE TRIGGER trg_agente_snapshot_histpedido_bi
-- ----------------------------------------------------------------------------
-- BEFORE INSERT em tbl_HistPedido (unico momento em MySQL onde SET NEW.* funciona).
-- Le snapshot do pedido pai via NEW.cod_Pedido e popula NEW.agente_*_snap.
--
-- Naming: trg_<namespace>_<funcao>_<tabela>_<tipo>
--   trg_                            -> prefixo padrao MySQL para trigger
--   agente_                         -> namespace satelite (ADR-0004)
--   snapshot_histpedido             -> funcao do trigger
--   _bi                             -> sufixo "before insert"
--
-- IMPORTANTE -- RELACIONAMENTO tbl_HistPedido.cod_Pedido -> tbl_Pedido.cod_Pedido
-- (PK de tbl_Pedido eh cod_Pedido, NAO id -- mesmo padrao do INT#5).
-- tbl_HistPedido.cod_Pedido eh INT NULL (callers de transicao podem omitir);
-- nesse caso o SELECT retorna NULL e as 3 colunas em HistPedido ficam NULL.
-- Comportamento desejado (apuracao ignora linhas sem snapshot).
--
-- Pedidos pre-AG#4 com agente_cod_snap=NULL em tbl_Pedido -> SELECT retorna NULL ->
-- coluna em tbl_HistPedido fica NULL. Comportamento desejado.
--
-- IFNULL(NEW.x, ...) garante OVERRIDE EXPLICITO: se caller envia o valor explicitamente,
-- trigger respeita (defesa pra backfill controlado e testes).

DROP TRIGGER IF EXISTS trg_agente_snapshot_histpedido_bi;

CREATE TRIGGER trg_agente_snapshot_histpedido_bi
BEFORE INSERT ON tbl_HistPedido
FOR EACH ROW
SET
    NEW.agente_cod_snap = IFNULL(
        NEW.agente_cod_snap,
        (SELECT p.agente_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)
    ),
    NEW.agente_pct_snap = IFNULL(
        NEW.agente_pct_snap,
        (SELECT p.agente_pct_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)
    ),
    NEW.agente_modalidade_snap = IFNULL(
        NEW.agente_modalidade_snap,
        (SELECT p.agente_modalidade_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)
    );

-- ============================================================================
-- VERIFICACAO POS-MIGRATION (rodar manualmente apos `php sql/migrate.php up`)
-- ============================================================================
-- 1) Conferir colunas em tbl_HistPedido:
--    SHOW COLUMNS FROM tbl_HistPedido LIKE 'agente_%';
--    -> deve retornar: agente_cod_snap, agente_pct_snap, agente_modalidade_snap
--
-- 2) Conferir indice criado:
--    SHOW INDEX FROM tbl_HistPedido WHERE Key_name='idx_histpedido_agente_cod_snap';
--    -> deve retornar 1 linha
--
-- 3) Conferir trigger criado:
--    SHOW TRIGGERS LIKE 'tbl_HistPedido';
--    -> deve listar: trg_agente_snapshot_histpedido_bi (BEFORE INSERT)
--
-- 4) Smoke teste (T2 do plano da Fernanda):
--    SELECT cod_Pedido, agente_cod_snap, agente_pct_snap, agente_modalidade_snap
--    FROM tbl_Pedido WHERE agente_cod_snap IS NOT NULL LIMIT 1;
--    -- assumir cod_Pedido = X
--    INSERT INTO tbl_HistPedido (cod_Pedido, incrementoRev, cod_Cliente, cod_Sublinha,
--      cod_Revenda, cod_Produto, propriedadeEquip, tipoEquip, qtd_equip, valorEquip,
--      vTotalLic, vfinal, formPag, condPag, obs, altPosAtual, nameConsultor,
--      cpfConsultor, nameComprador, cpfComprador, nameDiretor, cpfDiretor, dataPed, statusPed)
--    VALUES (X, 0, 0, 0, 0, 0, '', 0, 0, '', '', '', 0, 0, '', 0, '', '', '', '', '', '', NOW(), 'TESTE-INT4');
--    SELECT id, cod_Pedido, agente_cod_snap, agente_pct_snap, agente_modalidade_snap
--    FROM tbl_HistPedido WHERE id = LAST_INSERT_ID();
--    -- esperado: 3 colunas populadas iguais as de tbl_Pedido WHERE cod_Pedido=X
--    DELETE FROM tbl_HistPedido WHERE statusPed='TESTE-INT4';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260508_016_alter_tbl_histpedido_snapshot_trigger', 'up', 'consolidado producao');


-- ============================================================================
-- 20260508_017_create_triggers_protecao_apuracao_fechada
-- ============================================================================
-- ============================================================================
-- Migration 017 — AP#10.1: Triggers BEFORE de protecao contra edicao em
--                 apuracao fechada (rede de seguranca final do AP#10).
-- ============================================================================
-- PRD:   docs/PRDs/PRD-0002-modelo-agente/PRD-TECNICA-0002-modelo-agente.md
-- Card:  AP#10.1 (roadmap) — estrategia long-tail do AP#10
-- Data:  08/05/2026 noite
-- Decidido por: Giovanny Porto (Stakeholder Leader) em batch 08/05/2026 noite
--
-- ============================================================================
-- ESCOPO
-- ============================================================================
-- 6 triggers BEFORE em 3 tabelas (UPDATE + DELETE per tabela):
--   1. trg_agente_proteger_pedido_bu        (BEFORE UPDATE em tbl_Pedido)
--   2. trg_agente_proteger_pedido_bd        (BEFORE DELETE em tbl_Pedido)
--   3. trg_agente_proteger_boleto_bu        (BEFORE UPDATE em tbl_Boleto)
--   4. trg_agente_proteger_boleto_bd        (BEFORE DELETE em tbl_Boleto)
--   5. trg_agente_proteger_faturamento_bu   (BEFORE UPDATE em tbl_Faturamento)
--   6. trg_agente_proteger_faturamento_bd   (BEFORE DELETE em tbl_Faturamento)
--
-- Cada trigger:
--   * Verifica se OLD.<pk> aparece em agente_apuracao_itens vinculado a uma
--     apuracao com status_ciclo='fechada'.
--   * Se sim -> SIGNAL SQLSTATE '45000' com mensagem 'APURACAO_FECHADA_AFETADA'.
--   * Se nao -> deixa a operacao seguir normal.
--
-- Filosofia: ROW-LEVEL (qualquer UPDATE/DELETE bloqueia, independente da coluna).
-- Conservador por design — espelha o helper PHP agente_proteger_edicao() que
-- trabalha row-level. False positives em edicoes benignas (ex.: update de obs
-- em pedido fechado) sao aceitaveis: operador deve usar o fluxo de "solicitar
-- reabertura" pra qualquer mudanca em apuracao fechada.
--
-- ============================================================================
-- POR QUE A MIGRATION USA DELIMITER (precisa mysql CLI, nao runner PDO)
-- ============================================================================
-- Triggers com SIGNAL exigem BEGIN/END/IF — sintaxe que o runner PDO nao aceita
-- (memory: feedback_pdo_runner_nao_suporta_delimiter.md).
--
-- Aplicacao manual:
--   /Applications/MAMP/Library/bin/mysql80/bin/mysql -h 127.0.0.1 -P 3306 \
--     -u root -proot tefnet_erp \
--     < sql/migrations/20260508_017_create_triggers_protecao_apuracao_fechada.up.sql
--
--   php sql/migrate.php register-applied 20260508_017_create_triggers_protecao_apuracao_fechada
--
-- ============================================================================
-- INTERACAO COM O TRIGGER trg_agente_snapshot_faturamento_bi (Migration 014)
-- ============================================================================
-- A Migration 014 ja criou trg_agente_snapshot_faturamento_bi (BEFORE INSERT em
-- tbl_Faturamento). Esta migration adiciona BEFORE UPDATE/DELETE — eventos
-- distintos, sem conflito. MySQL aceita 1 trigger por (tabela, evento, momento).
-- ============================================================================

DELIMITER $$

-- ----------------------------------------------------------------------------
-- 1) tbl_Pedido — BEFORE UPDATE
-- ----------------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_proteger_pedido_bu$$

CREATE TRIGGER trg_agente_proteger_pedido_bu
BEFORE UPDATE ON tbl_Pedido
FOR EACH ROW
BEGIN
    IF EXISTS (
        SELECT 1
        FROM agente_apuracao_itens i
        JOIN agente_apuracao_periodos p ON p.id = i.apuracao_id
        WHERE i.cod_Pedido_snap = OLD.cod_Pedido
          AND p.status_ciclo = 'fechada'
    ) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'APURACAO_FECHADA_AFETADA: edicao em tbl_Pedido bloqueada — pedido vinculado a apuracao fechada (AP#10.1)';
    END IF;
END$$

-- ----------------------------------------------------------------------------
-- 2) tbl_Pedido — BEFORE DELETE
-- ----------------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_proteger_pedido_bd$$

CREATE TRIGGER trg_agente_proteger_pedido_bd
BEFORE DELETE ON tbl_Pedido
FOR EACH ROW
BEGIN
    IF EXISTS (
        SELECT 1
        FROM agente_apuracao_itens i
        JOIN agente_apuracao_periodos p ON p.id = i.apuracao_id
        WHERE i.cod_Pedido_snap = OLD.cod_Pedido
          AND p.status_ciclo = 'fechada'
    ) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'APURACAO_FECHADA_AFETADA: delete em tbl_Pedido bloqueado — pedido vinculado a apuracao fechada (AP#10.1)';
    END IF;
END$$

-- ----------------------------------------------------------------------------
-- 3) tbl_Boleto — BEFORE UPDATE
-- ----------------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_proteger_boleto_bu$$

CREATE TRIGGER trg_agente_proteger_boleto_bu
BEFORE UPDATE ON tbl_Boleto
FOR EACH ROW
BEGIN
    IF EXISTS (
        SELECT 1
        FROM agente_apuracao_itens i
        JOIN agente_apuracao_periodos p ON p.id = i.apuracao_id
        WHERE i.id_titulo_snap = OLD.id
          AND i.fonte_titulo = 'boleto'
          AND p.status_ciclo = 'fechada'
    ) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'APURACAO_FECHADA_AFETADA: edicao em tbl_Boleto bloqueada — titulo vinculado a apuracao fechada (AP#10.1)';
    END IF;
END$$

-- ----------------------------------------------------------------------------
-- 4) tbl_Boleto — BEFORE DELETE
-- ----------------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_proteger_boleto_bd$$

CREATE TRIGGER trg_agente_proteger_boleto_bd
BEFORE DELETE ON tbl_Boleto
FOR EACH ROW
BEGIN
    IF EXISTS (
        SELECT 1
        FROM agente_apuracao_itens i
        JOIN agente_apuracao_periodos p ON p.id = i.apuracao_id
        WHERE i.id_titulo_snap = OLD.id
          AND i.fonte_titulo = 'boleto'
          AND p.status_ciclo = 'fechada'
    ) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'APURACAO_FECHADA_AFETADA: delete em tbl_Boleto bloqueado — titulo vinculado a apuracao fechada (AP#10.1)';
    END IF;
END$$

-- ----------------------------------------------------------------------------
-- 5) tbl_Faturamento — BEFORE UPDATE
-- ----------------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_proteger_faturamento_bu$$

CREATE TRIGGER trg_agente_proteger_faturamento_bu
BEFORE UPDATE ON tbl_Faturamento
FOR EACH ROW
BEGIN
    IF EXISTS (
        SELECT 1
        FROM agente_apuracao_itens i
        JOIN agente_apuracao_periodos p ON p.id = i.apuracao_id
        WHERE i.id_titulo_snap = OLD.id
          AND i.fonte_titulo = 'faturamento'
          AND p.status_ciclo = 'fechada'
    ) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'APURACAO_FECHADA_AFETADA: edicao em tbl_Faturamento bloqueada — titulo vinculado a apuracao fechada (AP#10.1)';
    END IF;
END$$

-- ----------------------------------------------------------------------------
-- 6) tbl_Faturamento — BEFORE DELETE
-- ----------------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_proteger_faturamento_bd$$

CREATE TRIGGER trg_agente_proteger_faturamento_bd
BEFORE DELETE ON tbl_Faturamento
FOR EACH ROW
BEGIN
    IF EXISTS (
        SELECT 1
        FROM agente_apuracao_itens i
        JOIN agente_apuracao_periodos p ON p.id = i.apuracao_id
        WHERE i.id_titulo_snap = OLD.id
          AND i.fonte_titulo = 'faturamento'
          AND p.status_ciclo = 'fechada'
    ) THEN
        SIGNAL SQLSTATE '45000'
        SET MESSAGE_TEXT = 'APURACAO_FECHADA_AFETADA: delete em tbl_Faturamento bloqueado — titulo vinculado a apuracao fechada (AP#10.1)';
    END IF;
END$$

DELIMITER ;

-- ============================================================================
-- VERIFICACAO POS-MIGRATION
-- ============================================================================
-- 1) Confirmar 6 triggers criados:
--    SELECT TRIGGER_NAME, EVENT_MANIPULATION, EVENT_OBJECT_TABLE, ACTION_TIMING
--    FROM information_schema.TRIGGERS
--    WHERE TRIGGER_SCHEMA='tefnet_erp' AND TRIGGER_NAME LIKE 'trg_agente_proteger_%'
--    ORDER BY EVENT_OBJECT_TABLE, EVENT_MANIPULATION;
--
-- 2) Smoke teste — UPDATE em pedido SEM apuracao fechada deve passar:
--    UPDATE tbl_Pedido SET obs='trigger smoke 1' WHERE cod_Pedido = <id_sem_apuracao>;
--    -> deve atualizar normalmente.
--
-- 3) Smoke teste — UPDATE em pedido COM apuracao fechada deve falhar com 1644:
--    -- Setup: garantir apuracao fechada com cod_Pedido_snap conhecido
--    UPDATE tbl_Pedido SET obs='trigger smoke 2' WHERE cod_Pedido = <id_em_apuracao_fechada>;
--    -> ERROR 1644 (45000): APURACAO_FECHADA_AFETADA: edicao em tbl_Pedido bloqueada...
--
-- 4) Confirmar que trigger de Migration 014 (snapshot BEFORE INSERT) continua intacto:
--    SHOW TRIGGERS LIKE 'tbl_Faturamento';
--    -> deve listar AMBOS: trg_agente_snapshot_faturamento_bi (BI) E
--                        trg_agente_proteger_faturamento_bu (BU) E
--                        trg_agente_proteger_faturamento_bd (BD).

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260508_017_create_triggers_protecao_apuracao_fechada', 'up', 'consolidado producao');


-- ============================================================================
-- 20260509_020_rename_enum_modalidade_agente
-- ============================================================================
-- =====================================================================
-- Migration 020 — COM#4: renomeia ENUM agente_modalidade nas 4 tabelas
-- Data: 09/05/2026
-- PRD: PRD-0002 RF-02 (atualizada) + ADR-0007 (regra fallback Premium)
--
-- ENUM antigo: ('pct_venda','pct_comissao','tabela_preco')
-- ENUM novo:   ('pct_parceiro','pct_cliente_final','tabela_preco')
--
-- Tabelas afetadas:
--   tbl_Representante.agente_modalidade           (cadastro do agente)
--   tbl_Pedido.agente_modalidade_snap             (snapshot do pedido — 48 linhas)
--   tbl_Faturamento.agente_modalidade_snap        (snapshot propagado — 1 linha)
--   tbl_HistPedido.agente_modalidade_snap         (snapshot histórico — 0 linhas)
--
-- Ordem das operações (validada pela DBA Camila Rocha em 09/05/2026):
--   1) DROP triggers de propagação (ADR-0005, ADR-0006)
--   2) UPDATE dados existentes para os valores novos do ENUM
--   3) ALTER ENUM nas 4 tabelas
--   4) CREATE triggers (idênticas em comportamento)
--
-- Por que essa ordem:
--   - Triggers usam IFNULL+SELECT do tipo da coluna; após ALTER do tipo de origem
--     vs destino, melhor recriar pra garantir consistência interna do MySQL.
--   - UPDATE antes do ALTER porque o ALTER ENUM rejeita linhas com valor inválido
--     (em strict mode); migrar valores ANTES é o caminho seguro.
--   - SET SESSION sql_mode='' contorna NO_ZERO_DATE em registros legados de
--     tbl_Representante (data_cadastro = '0000-00-00' em algumas linhas — regra
--     dura registrada em memória `feedback_engine_tabelas_tefnet_erp_myisam_vs_innodb`
--     e em ADR-0005 nota de implementação).
-- =====================================================================

SET SESSION sql_mode = '';

-- ---------------------------------------------------------------------
-- 1) DROP triggers de propagação (recriadas no fim)
-- ---------------------------------------------------------------------
DROP TRIGGER IF EXISTS trg_agente_snapshot_faturamento_bi;
DROP TRIGGER IF EXISTS trg_agente_snapshot_histpedido_bi;

-- ---------------------------------------------------------------------
-- 2) UPDATE dados existentes para valores novos do ENUM
--    Decisões fechadas pelo dono (chat 09/05/2026):
--      - Agente 278 (MARCO POLO MONTEIRO VIANA) → pct_parceiro
--      - Agente 417 (CODGOX)                     → pct_cliente_final
--      - Snapshots no tbl_Pedido/tbl_Faturamento são todos do agente 417
--    `pct_comissao` formalmente removido — auditoria confirmou zero linhas.
-- ---------------------------------------------------------------------

-- Cadastro do agente em tbl_Representante (idNatureza=3)
UPDATE tbl_Representante
   SET agente_modalidade = 'pct_parceiro'
 WHERE id = 278
   AND agente_modalidade = 'pct_venda';

UPDATE tbl_Representante
   SET agente_modalidade = 'pct_cliente_final'
 WHERE id = 417
   AND agente_modalidade = 'pct_venda';

-- Snapshots em tbl_Pedido (todos do agente 417 em revendas Standart)
UPDATE tbl_Pedido
   SET agente_modalidade_snap = 'pct_cliente_final'
 WHERE agente_cod_snap = 417
   AND agente_modalidade_snap = 'pct_venda';

-- Snapshot em tbl_Faturamento (também do agente 417)
UPDATE tbl_Faturamento
   SET agente_modalidade_snap = 'pct_cliente_final'
 WHERE agente_cod_snap = 417
   AND agente_modalidade_snap = 'pct_venda';

-- tbl_HistPedido tem 0 linhas com snap — UPDATE no-op por segurança
UPDATE tbl_HistPedido
   SET agente_modalidade_snap = 'pct_cliente_final'
 WHERE agente_modalidade_snap = 'pct_venda';

-- ---------------------------------------------------------------------
-- 2.5) Validação pós-UPDATE — RESSALVA-IGOR-01 (Security review COM#4)
--      MyISAM não tem ROLLBACK; conferir que 100% dos dados migraram
--      ANTES do ALTER ENUM (que rejeitaria valores inválidos).
--      Se qualquer SELECT abaixo retornar > 0, o ALTER falhará e a
--      operação inteira fica em estado parcial. Verificação manual:
--          SELECT * FROM tbl_Representante
--           WHERE agente_modalidade IN ('pct_venda','pct_comissao');
--          SELECT * FROM tbl_Pedido
--           WHERE agente_modalidade_snap IN ('pct_venda','pct_comissao');
--          SELECT * FROM tbl_Faturamento
--           WHERE agente_modalidade_snap IN ('pct_venda','pct_comissao');
--          SELECT * FROM tbl_HistPedido
--           WHERE agente_modalidade_snap IN ('pct_venda','pct_comissao');
--      Todos devem retornar 0 linhas. Caso contrário, abortar.
-- ---------------------------------------------------------------------

-- ---------------------------------------------------------------------
-- 3) ALTER ENUM nas 4 tabelas
--    Engines: tbl_Representante/tbl_Pedido/tbl_HistPedido = MyISAM (rebuild
--    rápido); tbl_Faturamento = InnoDB com 81k+ linhas — usar INPLACE
--    quando suportado.
-- ---------------------------------------------------------------------

ALTER TABLE tbl_Representante
  MODIFY COLUMN agente_modalidade
    ENUM('pct_parceiro','pct_cliente_final','tabela_preco')
    NULL DEFAULT NULL
    COMMENT 'Aplicavel quando idNatureza=3 (Agente). COM#4: renomeado em 09/05/2026.';

ALTER TABLE tbl_Pedido
  MODIFY COLUMN agente_modalidade_snap
    ENUM('pct_parceiro','pct_cliente_final','tabela_preco')
    NULL DEFAULT NULL
    COMMENT 'Snapshot do agente no momento do INSERT do pedido. COM#4: renomeado em 09/05/2026.';

ALTER TABLE tbl_Faturamento
  MODIFY COLUMN agente_modalidade_snap
    ENUM('pct_parceiro','pct_cliente_final','tabela_preco')
    NULL DEFAULT NULL
    COMMENT 'Snapshot propagado de tbl_Pedido por trigger ADR-0005. COM#4: renomeado em 09/05/2026.';

ALTER TABLE tbl_HistPedido
  MODIFY COLUMN agente_modalidade_snap
    ENUM('pct_parceiro','pct_cliente_final','tabela_preco')
    NULL DEFAULT NULL
    COMMENT 'Snapshot histórico propagado de tbl_Pedido por trigger ADR-0006. COM#4: renomeado em 09/05/2026.';

-- ---------------------------------------------------------------------
-- 4) CREATE triggers de propagação (idênticas em comportamento — só
--    o tipo da coluna mudou, lógica continua um IFNULL+SELECT puro)
-- ---------------------------------------------------------------------

-- ATENÇÃO: o runner sql/migrate.php (PDO) NÃO suporta DELIMITER. Triggers
-- abaixo seguem em single-statement (sem BEGIN/END). Se o runner falhar
-- na execução, aplicar via mysql cli interativo + register-applied
-- (regra dura registrada em memória `feedback_pdo_runner_nao_suporta_delimiter`).

CREATE TRIGGER trg_agente_snapshot_faturamento_bi
  BEFORE INSERT ON tbl_Faturamento
  FOR EACH ROW SET
    NEW.agente_cod_snap = IFNULL(NEW.agente_cod_snap, (SELECT p.agente_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)),
    NEW.agente_pct_snap = IFNULL(NEW.agente_pct_snap, (SELECT p.agente_pct_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)),
    NEW.agente_modalidade_snap = IFNULL(NEW.agente_modalidade_snap, (SELECT p.agente_modalidade_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1));

CREATE TRIGGER trg_agente_snapshot_histpedido_bi
  BEFORE INSERT ON tbl_HistPedido
  FOR EACH ROW SET
    NEW.agente_cod_snap = IFNULL(NEW.agente_cod_snap, (SELECT p.agente_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)),
    NEW.agente_pct_snap = IFNULL(NEW.agente_pct_snap, (SELECT p.agente_pct_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)),
    NEW.agente_modalidade_snap = IFNULL(NEW.agente_modalidade_snap, (SELECT p.agente_modalidade_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1));

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260509_020_rename_enum_modalidade_agente', 'up', 'consolidado producao');


-- ============================================================================
-- 20260509_021_create_override_revenda_agente
-- ============================================================================
-- ============================================================
-- Migration 021 — Camada 2: Override de comissão revenda↔agente
-- ============================================================
--
-- AG#9 / PRD-0006-EXT / ADR-0008
--
-- Adiciona 2 colunas opcionais em tbl_Representante (revenda Premium/Standard com
-- agente vinculado) para permitir negociações específicas que substituem o padrão
-- do agente vinculado APENAS naquela revenda. Modalidade NÃO muda no override
-- (decisão D-EXT-06 / ADR-0008): só os valores dentro da modalidade vigente.
--
-- Cria tabela `agente_hist_override_revenda` para auditoria das mudanças nos
-- overrides (gravação PHP-side via pattern salvaLog do newportaltefnet).
--
-- Snapshot do pedido continua imutável (D-03 PRD-0006). Override é lido NO MOMENTO
-- do INSERT pelo helper agente_resolver_snapshot() e carimbado nas 3 (agora 4 com
-- Migration 022) colunas snap do pedido. Mudanças posteriores no override NÃO
-- afetam pedidos antigos.
-- ============================================================

SET SESSION sql_mode = '';

ALTER TABLE tbl_Representante
  ADD COLUMN agente_pct_override DECIMAL(8,4) NULL DEFAULT NULL
    COMMENT 'Camada 2 / AG#9: override do percentual do agente vinculado para esta revenda. NULL=usa agente_pct_padrao do agente. Aplicavel quando modalidade do agente vinculado eh pct_parceiro ou pct_cliente_final.',
  ADD COLUMN agente_tabela_preco_override_cod INT NULL DEFAULT NULL
    COMMENT 'Camada 2 / AG#9: override da tabela de preco para esta revenda. FK soft -> tbl_Representante.id de outro agente cuja agente_tabela_preco sera usada. NULL=usa tabela do proprio agente vinculado. Aplicavel quando modalidade do agente vinculado eh tabela_preco.',
  ADD INDEX idx_repr_agente_pct_override (agente_pct_override),
  ADD INDEX idx_repr_agente_tab_override (agente_tabela_preco_override_cod);

CREATE TABLE IF NOT EXISTS agente_hist_override_revenda (
  id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
  cod_Revenda INT NOT NULL COMMENT 'FK soft -> tbl_Representante.id (revenda Premium/Standard com idNatureza in (1,2))',
  campo VARCHAR(80) NOT NULL COMMENT 'Nome da coluna alterada: agente_pct_override | agente_tabela_preco_override_cod',
  valor_antigo TEXT NULL COMMENT 'Valor anterior (NULL se nao havia override antes). Texto para preservar formato exato.',
  valor_novo TEXT NULL COMMENT 'Valor novo (NULL se override foi removido).',
  alterado_at DATETIME NOT NULL COMMENT 'Timestamp da alteracao (NOW() do controller).',
  alterado_by INT NOT NULL COMMENT 'tbl_Usuario.idUsuario do operador que salvou (geralmente da $_SESSION).',
  origem VARCHAR(120) NOT NULL COMMENT 'Identificacao do contexto: updateRevenda.php | inserirRevenda.php | troca_agente_vinculado | etc.',
  INDEX idx_hist_ovr_rev (cod_Revenda, alterado_at),
  INDEX idx_hist_ovr_rev_campo (cod_Revenda, campo, alterado_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='Camada 2 / AG#9: auditoria das mudancas nos overrides agente_pct_override e agente_tabela_preco_override_cod em tbl_Representante. Gravacao PHP-side pelos controllers updateRevenda/inserirRevenda (pattern salvaLog).';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260509_021_create_override_revenda_agente', 'up', 'consolidado producao');


-- ============================================================================
-- 20260509_022_alter_snapshot_tabela_cod
-- ============================================================================
-- ============================================================
-- Migration 022 — 4ª coluna no snapshot do pedido (agente_tabela_cod_snap)
-- ============================================================
--
-- AG#9 / PRD-0006-EXT / ADR-0008
--
-- Adiciona coluna `agente_tabela_cod_snap` em tbl_Pedido + tbl_Faturamento +
-- tbl_HistPedido para carimbar QUAL agente tem a tabela_preco vigente no momento
-- do INSERT do pedido. Necessário para Camada 2: quando há override de
-- tabela_preco em tbl_Representante (revenda aponta tabela de outro agente),
-- a referência precisa ir junto com o snapshot do pedido (D-03 imutabilidade).
--
-- Semântica:
--   agente_cod_snap        = quem RECEBE a comissão (= agente vinculado)
--   agente_tabela_cod_snap = de QUAL agente vamos LER agente_tabela_preco (default
--                            = igual a agente_cod_snap; quando override = aponta
--                            pra outro agente)
--
-- Pedidos pré-Camada 2 ficam com NULL e a apuração faz fallback `?? agente_cod_snap`.
--
-- Recria os triggers `trg_agente_snapshot_faturamento_bi` e
-- `trg_agente_snapshot_histpedido_bi` para também propagar a 4ª coluna.
-- Single-statement SET ... IFNULL(...) compatível com runner PDO (sem DELIMITER).
-- ============================================================

SET SESSION sql_mode = '';

-- ============ ALTERS aditivos (3 tabelas) ============

ALTER TABLE tbl_Pedido
  ADD COLUMN agente_tabela_cod_snap INT NULL DEFAULT NULL
    COMMENT 'Camada 2 / AG#9: snapshot de QUAL agente tem a agente_tabela_preco vigente neste pedido. Default eh igual a agente_cod_snap; quando ha override de tabela_preco na revenda, aponta para o agente da tabela escolhida. NULL em pedidos pre-Camada 2 (apuracao faz fallback).',
  ADD INDEX idx_pedido_agente_tab_snap (agente_tabela_cod_snap);

ALTER TABLE tbl_Faturamento
  ADD COLUMN agente_tabela_cod_snap INT NULL DEFAULT NULL
    COMMENT 'Camada 2 / AG#9: propagado de tbl_Pedido.agente_tabela_cod_snap via trigger trg_agente_snapshot_faturamento_bi.',
  ADD INDEX idx_fat_agente_tab_snap (agente_tabela_cod_snap);

ALTER TABLE tbl_HistPedido
  ADD COLUMN agente_tabela_cod_snap INT NULL DEFAULT NULL
    COMMENT 'Camada 2 / AG#9: propagado de tbl_Pedido.agente_tabela_cod_snap via trigger trg_agente_snapshot_histpedido_bi.';

-- ============ Recriacao dos triggers de snapshot ============
-- DROP IF EXISTS antes do CREATE para idempotencia. NAO toca triggers de protecao
-- (trg_agente_proteger_faturamento_bu, trg_agente_proteger_faturamento_bd) que sao
-- separados e cobrem AP#10.1.

DROP TRIGGER IF EXISTS trg_agente_snapshot_faturamento_bi;

CREATE TRIGGER trg_agente_snapshot_faturamento_bi
BEFORE INSERT ON tbl_Faturamento
FOR EACH ROW
SET NEW.agente_cod_snap = IFNULL(NEW.agente_cod_snap, (SELECT p.agente_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)),
    NEW.agente_pct_snap = IFNULL(NEW.agente_pct_snap, (SELECT p.agente_pct_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)),
    NEW.agente_modalidade_snap = IFNULL(NEW.agente_modalidade_snap, (SELECT p.agente_modalidade_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1)),
    NEW.agente_tabela_cod_snap = IFNULL(NEW.agente_tabela_cod_snap, (SELECT p.agente_tabela_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.pedido_id LIMIT 1));

DROP TRIGGER IF EXISTS trg_agente_snapshot_histpedido_bi;

CREATE TRIGGER trg_agente_snapshot_histpedido_bi
BEFORE INSERT ON tbl_HistPedido
FOR EACH ROW
SET NEW.agente_cod_snap = IFNULL(NEW.agente_cod_snap, (SELECT p.agente_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)),
    NEW.agente_pct_snap = IFNULL(NEW.agente_pct_snap, (SELECT p.agente_pct_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)),
    NEW.agente_modalidade_snap = IFNULL(NEW.agente_modalidade_snap, (SELECT p.agente_modalidade_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1)),
    NEW.agente_tabela_cod_snap = IFNULL(NEW.agente_tabela_cod_snap, (SELECT p.agente_tabela_cod_snap FROM tbl_Pedido p WHERE p.cod_Pedido = NEW.cod_Pedido LIMIT 1));

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260509_022_alter_snapshot_tabela_cod', 'up', 'consolidado producao');


-- ============================================================================
-- 20260509_033_alter_modalidade_snap_enum_novo
-- ============================================================================
-- Migration 033 — DT-0021 — fix ENUM modalidade_snap em agente_apuracao_periodos.
--
-- Contexto: COM#4 (09/05/2026, Migration 020) renomeou ENUM agente_modalidade
-- de ('pct_venda','pct_comissao','tabela_preco') para ('pct_parceiro',
-- 'pct_cliente_final','tabela_preco') em tbl_Representante. Mas a coluna
-- agente_apuracao_periodos.modalidade_snap nao foi atualizada na mesma rodada.
-- Resultado: cron de apuracao falha com `Data truncated for column 'modalidade_snap'`
-- toda vez que tenta gravar o snapshot da modalidade vigente.
--
-- Padrao seguro de ALTER ENUM em strict mode (memoria
-- feedback_alter_enum_ordem_segura.md):
--   1. ALTER pra ENUM expandido (velhos + novos)
--   2. UPDATE pros nomes novos
--   3. ALTER pra ENUM final (so novos)
--
-- Status: cobre DT-0021. Detectado durante UI#23 (smoke do cron --meses=3).

SET SESSION sql_mode = '';

-- Passo 1 — expande ENUM aceitando velhos + novos (compat temporaria)
ALTER TABLE agente_apuracao_periodos
  MODIFY modalidade_snap
    ENUM('pct_venda','pct_comissao','pct_parceiro','pct_cliente_final','tabela_preco') NULL;

-- Passo 2 — UPDATE pros nomes novos.
-- (Hoje a tabela esta vazia pra agentes 278 e 417, mas a migration permanece
-- idempotente caso haja registros legados em ambientes diferentes.)
UPDATE agente_apuracao_periodos SET modalidade_snap='pct_parceiro'      WHERE modalidade_snap='pct_venda';
UPDATE agente_apuracao_periodos SET modalidade_snap='pct_cliente_final' WHERE modalidade_snap='pct_comissao';

-- Passo 3 — ENUM final (so nomes novos).
ALTER TABLE agente_apuracao_periodos
  MODIFY modalidade_snap
    ENUM('pct_parceiro','pct_cliente_final','tabela_preco') NULL;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260509_033_alter_modalidade_snap_enum_novo', 'up', 'consolidado producao');


-- ============================================================================
-- 20260510_034_create_agente_log_acao
-- ============================================================================
-- Migration 034 — AUDIT#1 — log estruturado de acoes do app web/agente.
--
-- Contexto: GAP de auditoria detectado em 10/05/2026 — Reapurar/Fechar/Resgatar
-- e demais transicoes de lote nao logam em BD. Aprovado pelo dono ("pode
-- providenciar, para ficar tudo rastreado").
--
-- Acoes capturadas:
--   apurar | fechar | reabrir | resgate_solicitar | lote_liquidar |
--   lote_estornar | rollback_executar | cron_manual
--
-- Insercao SEMPRE fora de transacao (depois de commit ou erro). Helper em
-- api/_log_helpers.php sob funcao log_acao().

CREATE TABLE IF NOT EXISTS agente_log_acao (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  usuario_id INT NOT NULL DEFAULT 0 COMMENT 'tbl_Usuario.id (0 quando DEV sem login)',
  usuario_nome VARCHAR(120) NULL COMMENT 'snapshot do nome no momento da acao',
  usuario_tpuser VARCHAR(20) NULL COMMENT 'Tef.Net | Revenda | Agente',
  cod_Representante INT NULL COMMENT 'agente alvo da acao',
  competencia CHAR(7) NULL COMMENT 'AAAA-MM',
  acao VARCHAR(40) NOT NULL COMMENT 'apurar | fechar | reabrir | resgate_solicitar | lote_liquidar | lote_estornar | rollback_executar | cron_manual',
  status_resultado ENUM('OK','ERRO') NOT NULL,
  mensagem VARCHAR(500) NULL,
  apuracao_id BIGINT UNSIGNED NULL,
  lote_id BIGINT UNSIGNED NULL,
  payload_resumo TEXT NULL COMMENT 'JSON pequeno com contexto (max 500 chars)',
  ip_address VARCHAR(45) NULL,
  user_agent VARCHAR(255) NULL,
  ambiente VARCHAR(20) DEFAULT 'PROD' COMMENT 'DEV | PROD (DEV quando ?dev=1)',
  PRIMARY KEY (id),
  KEY idx_log_data (created_at),
  KEY idx_log_acao_data (acao, created_at),
  KEY idx_log_cod_comp (cod_Representante, competencia),
  KEY idx_log_apuracao (apuracao_id),
  KEY idx_log_lote (lote_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='AUDIT#1 — log estruturado de acoes do app web/agente. Aprovado em 10/05/2026.';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260510_034_create_agente_log_acao', 'up', 'consolidado producao');


-- ============================================================================
-- 20260510_035_alter_agente_lote_status_pendente_reprovado
-- ============================================================================
-- Migration 035 — RES#2 / AP#11.
-- Expande ENUM status_lote em agente_lote_resgate adicionando os estados:
--   pendente_aprovacao  -- novo default; agente solicitou, aguarda Tef.Net
--   reprovado_tef_net   -- novo; lote rejeitado pela Tef.Net antes de pagar
--
-- Estados antigos permanecem válidos (aguardando_pagamento, pago, liquidado, estornado).
-- Lotes existentes ficam intactos. Apenas o DEFAULT do ENUM muda — INSERTs sem
-- coluna explícita agora caem em pendente_aprovacao.
--
-- Como só ADICIONAMOS estados (não removemos), NÃO é necessária a ordem segura de
-- 3 passos (feedback_alter_enum_ordem_segura.md). Um único ALTER basta.
--
-- ADR-0010 — Resgate como conta corrente.

SET SESSION sql_mode = '';

ALTER TABLE agente_lote_resgate
  MODIFY status_lote ENUM(
    'pendente_aprovacao',
    'aguardando_pagamento',
    'pago',
    'liquidado',
    'estornado',
    'reprovado_tef_net'
  ) NOT NULL DEFAULT 'pendente_aprovacao'
  COMMENT 'Estado do lote no fluxo conta corrente (ADR-0010). pendente_aprovacao = default novo.';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260510_035_alter_agente_lote_status_pendente_reprovado', 'up', 'consolidado producao');


-- ============================================================================
-- 20260510_036_alter_agente_lote_add_reprovacao
-- ============================================================================
-- Migration 036 — RES#2 / AP#11.
-- Adiciona campos de reprovação Tef.Net em agente_lote_resgate.
--
-- Quando Tef.Net reprova um lote em 'pendente_aprovacao' (Sprint B),
-- preenchemos as 3 colunas e desvinculamos os itens (DELETE em
-- agente_lote_item) — assim o disponível da competência volta a contar
-- aqueles boletos. ADR-0010.

SET SESSION sql_mode = '';

ALTER TABLE agente_lote_resgate
  ADD COLUMN reprovado_motivo VARCHAR(240) NULL AFTER estorno_motivo,
  ADD COLUMN reprovado_em     DATETIME     NULL AFTER reprovado_motivo,
  ADD COLUMN reprovado_by     INT          NULL AFTER reprovado_em,
  ADD INDEX  idx_lote_reprovado_em (reprovado_em);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260510_036_alter_agente_lote_add_reprovacao', 'up', 'consolidado producao');


-- ============================================================================
-- 20260510_037_create_agente_lote_anexo
-- ============================================================================
-- Migration 037 — RES#2 Sprint C (10/05/2026 madrugada virada 2).
--
-- Cria tabela agente_lote_anexo pra registrar arquivos (NF, boleto, comprovantes)
-- vinculados a cada agente_lote_resgate. Referência opaca via `storage_key` —
-- driver atual é StorageLocal (api/_storage_local.php) gravando em
-- /uploads/local/{section}/{YYYY-MM}/{hash}.{ext}; quando ARM#1 fechar, migra
-- pra R2/S3/MinIO sem mexer no schema (a key continua opaca).
--
-- Sprint C introduz fluxo:
--   1. Parceiro clica "Solicitar resgate" → modal abre
--   2. Modal coleta forma_pag (pix|boleto) + upload NF (obrigatório) +
--      upload Boleto (obrigatório se forma_pag='boleto')
--   3. POST api/resgate_anexar.php: faz upload via get_storage()->upload(),
--      cria lote em pendente_aprovacao, INSERT em agente_lote_anexo
--   4. Bandeja Tef.Net mostra links pra baixar anexos via api/arquivo_baixar.php
--
-- Tipos:
--   nf           — Nota Fiscal (PDF/JPG/PNG/XML)
--   boleto       — Boleto bancário (PDF)
--   comprovante  — Comprovante de pagamento (Tef.Net pode anexar futuramente)
--   outro        — Catch-all pra extensões
--
-- ON DELETE CASCADE — se o lote for soft-deletado fisicamente (raro), anexos vão junto.
-- Em situacao=0 (soft delete) o anexo permanece, só fica oculto.

SET SESSION sql_mode = '';

CREATE TABLE IF NOT EXISTS agente_lote_anexo (
  id INT PRIMARY KEY AUTO_INCREMENT,
  lote_id INT NOT NULL,
  tipo ENUM('nf','boleto','comprovante','outro') NOT NULL,
  storage_key VARCHAR(500) NOT NULL COMMENT 'Key opaca do driver (path em local, key em S3/R2)',
  nome_original VARCHAR(255) NOT NULL,
  mime_type VARCHAR(100) NOT NULL,
  tamanho_bytes INT NOT NULL,
  uploaded_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  uploaded_by INT NULL COMMENT 'user_id do uploader (NULL em DEV bypass)',
  situacao TINYINT(1) NOT NULL DEFAULT 1,
  INDEX idx_anexo_lote (lote_id),
  INDEX idx_anexo_tipo (tipo),
  CONSTRAINT fk_anexo_lote FOREIGN KEY (lote_id) REFERENCES agente_lote_resgate(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
COMMENT='RES#2 Sprint C — anexos (NF/Boleto/Comprovante) por lote de resgate. Driver opaco via api/_storage.php.';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260510_037_create_agente_lote_anexo', 'up', 'consolidado producao');


-- ============================================================================
-- 20260510_038_alter_agente_lote_add_competencia
-- ============================================================================
-- Migration 038 — RES#2 Sprint D (10/05/2026 madrugada virada 3).
--
-- B#13 — Denormaliza `competencia` (YYYY-MM) na propria tabela
-- `agente_lote_resgate`.
--
-- Motivo:
--   Antes desta migration a competencia era derivada via JOIN:
--     agente_lote_resgate
--       -> agente_lote_item
--          -> agente_apuracao_itens
--             -> agente_apuracao_periodos.competencia
--   Quando o lote eh REPROVADO (Sprint B), `resgate_reprovar.php` faz
--   DELETE em `agente_lote_item` pra devolver disponibilidade. O JOIN
--   passa a retornar NULL e o frontend agrupa o lote em "Sem-Competencia"
--   (B#13 visivel em #lotes). Lote precisa preservar a competencia mesmo
--   apos o DELETE — denormalizamos.
--
-- Schema novo:
--   agente_lote_resgate.competencia VARCHAR(7) NOT NULL DEFAULT ''
--     COMMENT 'YYYY-MM, denormalizado pra preservar agrupamento pos-reprovacao'
--   + INDEX idx_lote_competencia (competencia)
--
-- Backfill:
--   Lotes que AINDA tem itens vivos: derivam via JOIN GROUP BY (1 row por lote).
--   Lotes que perderam itens (reprovados pre-038): ficam com '' — serao mostrados
--   em grupo "Sem-Competencia" pelo frontend (legado). Como nao havia reprovados
--   anteriores em produção, essa fallback eh esperada pra rows sinteticas de
--   smoke.
--
-- Idempotente via IF NOT EXISTS-like (verificado pelo migrate.php).

SET SESSION sql_mode = '';

ALTER TABLE agente_lote_resgate
  ADD COLUMN competencia VARCHAR(7) NOT NULL DEFAULT '' COMMENT 'YYYY-MM, denormalizado pra preservar agrupamento mesmo apos resgate_reprovar deletar agente_lote_item (B#13)' AFTER cod_Representante,
  ADD INDEX idx_lote_competencia (competencia);

-- Backfill: lotes que AINDA tem itens derivam via JOIN.
-- Subquery agrega por (lote_id, competencia) pra evitar conflito UPDATE-from-target.
UPDATE agente_lote_resgate l
INNER JOIN (
  SELECT li.lote_id, MIN(ap.competencia) AS competencia
  FROM agente_lote_item li
  INNER JOIN agente_apuracao_itens ai ON ai.id = li.apuracao_item_id
  INNER JOIN agente_apuracao_periodos ap ON ap.id = ai.apuracao_id
  GROUP BY li.lote_id
) src ON src.lote_id = l.id
SET l.competencia = src.competencia
WHERE l.competencia = '';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260510_038_alter_agente_lote_add_competencia', 'up', 'consolidado producao');


-- ============================================================================
-- 20260510_039_alter_agente_lote_add_data_prev_pag
-- ============================================================================
-- Migration 039 — RES#2 Sprint D (10/05/2026 madrugada virada 3).
--
-- Adiciona `data_prev_pag` (data prevista de pagamento) em agente_lote_resgate.
--
-- Motivo:
--   Aba "Bandeja Tef.Net" (em #lotes, Sprint D) precisa de coluna pra Tef.Net
--   programar quando o lote sera pago. Pode ser preenchida no momento da
--   aprovacao (resgate_aprovar.php aceita campo opcional) ou via UI futura
--   de edicao de programacao de pagamento.
--
-- Schema novo:
--   agente_lote_resgate.data_prev_pag DATE NULL
--     COMMENT 'Data programada para pagamento; Tef.Net define ao aprovar ou depois'
--
-- Nao confundir com `data_pag` ja existente — essa coluna eh a data
-- DEFINITIVA do pagamento (preenchida pelo lote_liquidar.php). A nova
-- `data_prev_pag` eh a PROGRAMACAO (intencao).

SET SESSION sql_mode = '';

ALTER TABLE agente_lote_resgate
  ADD COLUMN data_prev_pag DATE NULL COMMENT 'Data programada para pagamento (Tef.Net interno define ao aprovar ou depois)' AFTER data_pag,
  ADD INDEX idx_lote_data_prev_pag (data_prev_pag);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260510_039_alter_agente_lote_add_data_prev_pag', 'up', 'consolidado producao');


-- ============================================================================
-- 20260511_040_alter_tbl_representante_add_resgate_config
-- ============================================================================
-- Migration 040 — RES#2 (11/05/2026).
--
-- Adiciona 2 colunas em tbl_Representante para a politica de resgate
-- configurada por agente:
--
--   agente_limite_resgates_auto       — limite de resgates automaticos
--                                       por competencia (1-5). Apos atingir
--                                       o limite, parceiro precisa de
--                                       liberacao manual Tef.Net.
--
--   agente_dia_min_resgate_corrente   — dia minimo do mes para o 1o
--                                       resgate da COMPETENCIA CORRENTE
--                                       (1-31). Competencias anteriores
--                                       ficam sempre liberadas a partir
--                                       do dia 1 do mes seguinte.
--
-- Nasce NULLABLE pra permitir backfill seguro dos agentes existentes
-- (Migration 041) antes do ALTER NOT NULL (Migration 042).
--
-- Card: RES#2 / PRD-0010 / DT-0023.
-- ADR-0011 (a criar) consolida a politica.
--
-- Padroes:
--   - PHP 7.4 / MySQL 5.7+ compat.
--   - SET SESSION sql_mode = '' (CLAUDE.md item 12) — runner aplica via PDO
--     sem DELIMITER; sql_mode permissivo evita NO_ZERO_DATE em tabelas legacy.
--   - Mantem comentarios em cada coluna pra documentacao no INFORMATION_SCHEMA.

SET SESSION sql_mode = '';

ALTER TABLE tbl_Representante
  ADD COLUMN agente_limite_resgates_auto TINYINT UNSIGNED NULL
    COMMENT 'RES#2: limite de resgates automaticos por competencia (1-5). NULL = nao configurado ainda' AFTER agente_cod_vinculado,
  ADD COLUMN agente_dia_min_resgate_corrente TINYINT UNSIGNED NULL
    COMMENT 'RES#2: dia minimo do mes para 1o resgate da competencia corrente (1-31). NULL = nao configurado ainda' AFTER agente_limite_resgates_auto;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260511_040_alter_tbl_representante_add_resgate_config', 'up', 'consolidado producao');


-- ============================================================================
-- 20260511_042_alter_tbl_representante_resgate_config_not_null
-- ============================================================================
-- Migration 042 — RES#2 (11/05/2026).
--
-- Promove as 2 colunas de politica de resgate a NOT NULL.
--
-- Precondicao:
--   - Migration 040 aplicada (colunas existem NULLABLE)
--   - Migration 041 aplicada (agentes existentes 278/417 backfillados)
--
-- Apos esta migration:
--   - INSERT/UPDATE em tbl_Representante com idNatureza=3 (agente) deve
--     trazer valor explicito nessas colunas. Cadastros novos sem essa
--     info sao bloqueados pelo controller (defesa em profundidade).
--   - Representantes nao-agente (revendas, parceiros) tambem precisam
--     de valor — controller seta default (3/20) pra eles automaticamente
--     pra nao quebrar fluxos existentes.
--
-- Card: RES#2.

SET SESSION sql_mode = '';

ALTER TABLE tbl_Representante
  MODIFY COLUMN agente_limite_resgates_auto TINYINT UNSIGNED NOT NULL DEFAULT 3
    COMMENT 'RES#2: limite de resgates automaticos por competencia (1-5). Obrigatorio no cadastro do agente.',
  MODIFY COLUMN agente_dia_min_resgate_corrente TINYINT UNSIGNED NOT NULL DEFAULT 20
    COMMENT 'RES#2: dia minimo do mes para 1o resgate da competencia corrente (1-31). Obrigatorio no cadastro do agente.';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260511_042_alter_tbl_representante_resgate_config_not_null', 'up', 'consolidado producao');


-- ============================================================================
-- 20260511_043_create_agente_liberacao_resgate_extra
-- ============================================================================
-- Migration 043 — RES#2 (11/05/2026).
--
-- Cria tabela agente_liberacao_resgate_extra para tickets de liberacao
-- manual da Tef.Net.
--
-- Cada linha = 1 ticket. Quando o parceiro atinge o limite automatico
-- (limite_configurado_no_agente) na competencia, novos resgates so
-- liberam se houver ticket disponivel.
--
-- Workflow:
--   1. Tef.Net cria ticket via UI Bandeja Tef.Net (POST
--      tef_net_liberacao_extra_conceder.php) — status='disponivel'.
--   2. Proximo POST de painel_resgate.php / resgate_anexar.php naquela
--      competencia consome o ticket — UPDATE status='consumido',
--      consumido_lote_id, consumido_em.
--   3. Tef.Net pode revogar antes de consumir — UPDATE status='revogado',
--      revogado_em, revogado_por_user_id.
--
-- Cada ticket vale 1 resgate. Nao "abre comportas" — premissa do dono.
--
-- Trilha AUDIT#1: cada transicao (conceder/consumir/revogar) dispara
-- log_acao() com payload incluindo motivo + agente + competencia.
--
-- Card: RES#2 / PRD-0010.

SET SESSION sql_mode = '';

CREATE TABLE IF NOT EXISTS agente_liberacao_resgate_extra (
  id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  agente_cod_snap INT UNSIGNED NOT NULL
    COMMENT 'cod_Representante do agente (snapshot ao conceder)',
  competencia VARCHAR(7) NOT NULL
    COMMENT 'AAAA-MM',
  liberado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
    COMMENT 'momento da concessao',
  liberado_por_user_id INT UNSIGNED NULL
    COMMENT 'user_id Tef.Net que liberou (NULL em CLI/CRON emergencial)',
  motivo TEXT NOT NULL
    COMMENT 'justificativa obrigatoria',
  consumido_lote_id BIGINT UNSIGNED NULL
    COMMENT 'lote_id que consumiu este ticket (preenche no INSERT do lote)',
  consumido_em DATETIME NULL
    COMMENT 'momento do consumo',
  revogado_em DATETIME NULL
    COMMENT 'momento da revogacao (Tef.Net cancelou antes de ser consumido)',
  revogado_por_user_id INT UNSIGNED NULL,
  revogacao_motivo TEXT NULL
    COMMENT 'motivo da revogacao',
  status ENUM('disponivel','consumido','revogado') NOT NULL DEFAULT 'disponivel',
  situacao TINYINT(1) NOT NULL DEFAULT 1
    COMMENT 'soft delete: 1=ativo, 0=apagado',
  PRIMARY KEY (id),
  KEY idx_libextra_agente_comp_status (agente_cod_snap, competencia, status),
  KEY idx_libextra_status (status),
  KEY idx_libextra_consumido_lote (consumido_lote_id),
  KEY idx_libextra_liberado_em (liberado_em)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='RES#2: tickets de liberacao manual Tef.Net pra resgates alem do limite';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260511_043_create_agente_liberacao_resgate_extra', 'up', 'consolidado producao');


-- ============================================================================
-- 20260511_044_create_cadastro_feriados
-- ============================================================================
-- Migration 044 — F10 (11/05/2026).
--
-- Cria tabela cadastro_feriados — cadastro centralizado de feriados
-- (nacionais, estaduais, municipais, facultativos) consumido pela
-- validacao de dias uteis do boleto (RES#2 F6.2).
--
-- Decisao do dono (11/05/2026):
--   - Feriados NACIONAIS vem seeded por mim (Migration 045)
--   - UI no newportaltefnet (menu Configuracoes) permite cadastrar
--     adicionais (estadual, municipal, facultativo)
--   - Toggle "ativo" liga/desliga (nao exclui — sindicato pode trocar
--     dia regional, voce desativa sem perder historico)
--   - 1 vez cadastrado, vale ate ser desativado
--
-- Card: F10 / RES#2.

SET SESSION sql_mode = '';

CREATE TABLE IF NOT EXISTS cadastro_feriados (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  data DATE NOT NULL
    COMMENT 'data do feriado',
  descricao VARCHAR(120) NOT NULL
    COMMENT 'nome do feriado (ex: Tiradentes, Padroeira de Natal)',
  tipo ENUM('nacional','estadual','municipal','facultativo') NOT NULL
    COMMENT 'abrangencia',
  uf VARCHAR(2) NULL
    COMMENT 'preenche em estadual/municipal (ex: RN, SP)',
  municipio VARCHAR(120) NULL
    COMMENT 'preenche so em municipal',
  ativo TINYINT(1) NOT NULL DEFAULT 1
    COMMENT '1=valido, 0=desativado (sindicato trocou, troca regional, etc)',
  criado_em DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  criado_por_user_id INT UNSIGNED NULL
    COMMENT 'user que cadastrou (NULL = seed do sistema)',
  atualizado_em DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
  atualizado_por_user_id INT UNSIGNED NULL,
  PRIMARY KEY (id),
  UNIQUE KEY uq_data_tipo_uf_mun (data, tipo, uf, municipio),
  KEY idx_data_ativo (data, ativo),
  KEY idx_tipo (tipo)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='F10: cadastro de feriados (nacional+estadual+municipal+facultativo)';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260511_044_create_cadastro_feriados', 'up', 'consolidado producao');


-- ============================================================================
-- 20260511_045_seed_feriados_nacionais_2024_2030
-- ============================================================================
-- Migration 045 — Seed feriados nacionais 2024-2030 (F10).
--
-- Inclui datas fixas anuais + moveis calculadas por Computus
-- (Pascoa → Carnaval, Sexta Santa, Corpus Christi).
--
-- Datas moveis (geradas manualmente — Computus do PHP):
--
-- 2024: Pascoa=31/03  Carnaval=12-13/02  SextaSanta=29/03  Corpus=30/05
-- 2025: Pascoa=20/04  Carnaval=03-04/03  SextaSanta=18/04  Corpus=19/06
-- 2026: Pascoa=05/04  Carnaval=16-17/02  SextaSanta=03/04  Corpus=04/06
-- 2027: Pascoa=28/03  Carnaval=08-09/02  SextaSanta=26/03  Corpus=27/05
-- 2028: Pascoa=16/04  Carnaval=28-29/02  SextaSanta=14/04  Corpus=15/06
-- 2029: Pascoa=01/04  Carnaval=12-13/02  SextaSanta=30/03  Corpus=31/05
-- 2030: Pascoa=21/04  Carnaval=04-05/03  SextaSanta=19/04  Corpus=20/06
--
-- Carnaval = segunda-feira anterior + terca-feira de Carnaval (Pascoa - 48 e -47)
-- Sexta-feira da Paixao = Pascoa - 2
-- Corpus Christi = Pascoa + 60 (5a feira)

SET SESSION sql_mode = '';

INSERT INTO cadastro_feriados (data, descricao, tipo, ativo) VALUES
  -- 2024
  ('2024-01-01','Confraternizacao Universal','nacional',1),
  ('2024-02-12','Carnaval (segunda)','nacional',1),
  ('2024-02-13','Carnaval (terca)','nacional',1),
  ('2024-03-29','Sexta-feira da Paixao','nacional',1),
  ('2024-04-21','Tiradentes','nacional',1),
  ('2024-05-01','Dia do Trabalho','nacional',1),
  ('2024-05-30','Corpus Christi','nacional',1),
  ('2024-09-07','Independencia do Brasil','nacional',1),
  ('2024-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2024-11-02','Finados','nacional',1),
  ('2024-11-15','Proclamacao da Republica','nacional',1),
  ('2024-11-20','Dia da Consciencia Negra','nacional',1),
  ('2024-12-25','Natal','nacional',1),

  -- 2025
  ('2025-01-01','Confraternizacao Universal','nacional',1),
  ('2025-03-03','Carnaval (segunda)','nacional',1),
  ('2025-03-04','Carnaval (terca)','nacional',1),
  ('2025-04-18','Sexta-feira da Paixao','nacional',1),
  ('2025-04-21','Tiradentes','nacional',1),
  ('2025-05-01','Dia do Trabalho','nacional',1),
  ('2025-06-19','Corpus Christi','nacional',1),
  ('2025-09-07','Independencia do Brasil','nacional',1),
  ('2025-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2025-11-02','Finados','nacional',1),
  ('2025-11-15','Proclamacao da Republica','nacional',1),
  ('2025-11-20','Dia da Consciencia Negra','nacional',1),
  ('2025-12-25','Natal','nacional',1),

  -- 2026
  ('2026-01-01','Confraternizacao Universal','nacional',1),
  ('2026-02-16','Carnaval (segunda)','nacional',1),
  ('2026-02-17','Carnaval (terca)','nacional',1),
  ('2026-04-03','Sexta-feira da Paixao','nacional',1),
  ('2026-04-21','Tiradentes','nacional',1),
  ('2026-05-01','Dia do Trabalho','nacional',1),
  ('2026-06-04','Corpus Christi','nacional',1),
  ('2026-09-07','Independencia do Brasil','nacional',1),
  ('2026-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2026-11-02','Finados','nacional',1),
  ('2026-11-15','Proclamacao da Republica','nacional',1),
  ('2026-11-20','Dia da Consciencia Negra','nacional',1),
  ('2026-12-25','Natal','nacional',1),

  -- 2027
  ('2027-01-01','Confraternizacao Universal','nacional',1),
  ('2027-02-08','Carnaval (segunda)','nacional',1),
  ('2027-02-09','Carnaval (terca)','nacional',1),
  ('2027-03-26','Sexta-feira da Paixao','nacional',1),
  ('2027-04-21','Tiradentes','nacional',1),
  ('2027-05-01','Dia do Trabalho','nacional',1),
  ('2027-05-27','Corpus Christi','nacional',1),
  ('2027-09-07','Independencia do Brasil','nacional',1),
  ('2027-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2027-11-02','Finados','nacional',1),
  ('2027-11-15','Proclamacao da Republica','nacional',1),
  ('2027-11-20','Dia da Consciencia Negra','nacional',1),
  ('2027-12-25','Natal','nacional',1),

  -- 2028
  ('2028-01-01','Confraternizacao Universal','nacional',1),
  ('2028-02-28','Carnaval (segunda)','nacional',1),
  ('2028-02-29','Carnaval (terca)','nacional',1),
  ('2028-04-14','Sexta-feira da Paixao','nacional',1),
  ('2028-04-21','Tiradentes','nacional',1),
  ('2028-05-01','Dia do Trabalho','nacional',1),
  ('2028-06-15','Corpus Christi','nacional',1),
  ('2028-09-07','Independencia do Brasil','nacional',1),
  ('2028-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2028-11-02','Finados','nacional',1),
  ('2028-11-15','Proclamacao da Republica','nacional',1),
  ('2028-11-20','Dia da Consciencia Negra','nacional',1),
  ('2028-12-25','Natal','nacional',1),

  -- 2029
  ('2029-01-01','Confraternizacao Universal','nacional',1),
  ('2029-02-12','Carnaval (segunda)','nacional',1),
  ('2029-02-13','Carnaval (terca)','nacional',1),
  ('2029-03-30','Sexta-feira da Paixao','nacional',1),
  ('2029-04-21','Tiradentes','nacional',1),
  ('2029-05-01','Dia do Trabalho','nacional',1),
  ('2029-05-31','Corpus Christi','nacional',1),
  ('2029-09-07','Independencia do Brasil','nacional',1),
  ('2029-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2029-11-02','Finados','nacional',1),
  ('2029-11-15','Proclamacao da Republica','nacional',1),
  ('2029-11-20','Dia da Consciencia Negra','nacional',1),
  ('2029-12-25','Natal','nacional',1),

  -- 2030
  ('2030-01-01','Confraternizacao Universal','nacional',1),
  ('2030-03-04','Carnaval (segunda)','nacional',1),
  ('2030-03-05','Carnaval (terca)','nacional',1),
  ('2030-04-19','Sexta-feira da Paixao','nacional',1),
  ('2030-04-21','Tiradentes','nacional',1),
  ('2030-05-01','Dia do Trabalho','nacional',1),
  ('2030-06-20','Corpus Christi','nacional',1),
  ('2030-09-07','Independencia do Brasil','nacional',1),
  ('2030-10-12','Nossa Senhora Aparecida','nacional',1),
  ('2030-11-02','Finados','nacional',1),
  ('2030-11-15','Proclamacao da Republica','nacional',1),
  ('2030-11-20','Dia da Consciencia Negra','nacional',1),
  ('2030-12-25','Natal','nacional',1);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260511_045_seed_feriados_nacionais_2024_2030', 'up', 'consolidado producao');


-- ============================================================================
-- 20260511_046_alter_agente_detalhe_add_pix_tipo_e_nome
-- ============================================================================
-- Migration 046 (11/05/2026) — RES#2 F6 / rodada 3.
-- Adiciona tipo de chave Pix + nome do titular em agente_detalhe.
--
-- Motivacao (dono em 11/05/2026): "manda escolher o tipo chave pix para vc
-- formar corretamente. telefone cnpj ou cpf, email chave aleatoria. coloque
-- o campo nome (nome que vai aparecer no pix)".
--
-- ENUM canonico Bacen: celular, email, cpf, cnpj, aleatoria.
-- nome_titular_pix: nome que aparece na confirmacao do Pix no Bacen
--                   (usado pelo parceiro pra conferir titularidade).
--
-- Stack: MySQL 5.7+ / engine herdada (InnoDB).
-- Sem strict mode: ALTER em 1 passo (so adicao, nao modificacao).

ALTER TABLE agente_detalhe
    ADD COLUMN tipo_chave_pix ENUM('celular','email','cpf','cnpj','aleatoria') NULL
        COMMENT 'RES#2 F6 (11/05/2026) — tipo da chave Pix conforme Bacen.'
        AFTER pix_chave,
    ADD COLUMN nome_titular_pix VARCHAR(160) NULL
        COMMENT 'RES#2 F6 (11/05/2026) — nome que aparece na confirmacao do Pix.'
        AFTER tipo_chave_pix;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260511_046_alter_agente_detalhe_add_pix_tipo_e_nome', 'up', 'consolidado producao');


-- NOTA: Migrations 047 (seed_feriados_estaduais_municipais) e 048
-- (refactor_feriados_sem_ano) ainda nao consolidadas neste release —
-- consultar arquivos .up.sql diretos quando preparar deploy. As migrations
-- 049-054 abaixo (AP#11 / PRD-0007-EXT) estao consolidadas.


-- ============================================================================
-- 20260513_049_create_agente_motivo_reprovacao
-- ============================================================================
-- Migration 049 — AP#11 / PRD-0007-EXT.
-- Cria cadastro Tef.Net de motivos de reprovacao/correcao de resgate.
-- Vide arquivo .up.sql original para comentarios completos.

SET SESSION sql_mode = '';

CREATE TABLE IF NOT EXISTS agente_motivo_reprovacao (
  id          INT AUTO_INCREMENT PRIMARY KEY,
  descricao   VARCHAR(120) NOT NULL COMMENT 'Texto exibido no dropdown (ate 120 chars)',
  ativo       TINYINT(1)   NOT NULL DEFAULT 1 COMMENT 'Soft delete: 1=visivel, 0=oculto mas preserva historico',
  criado_em   DATETIME     NOT NULL DEFAULT CURRENT_TIMESTAMP,
  criado_por  INT          NULL COMMENT 'tbl_Usuario.id_user do criador; NULL em DEV/seed',
  INDEX idx_ativo (ativo)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='AP#11 (PRD-0007-EXT) — Catalogo Tef.Net de motivos de reprovacao/correcao de resgate.';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_049_create_agente_motivo_reprovacao', 'up', 'consolidado producao');


-- ============================================================================
-- 20260513_050_alter_status_lote_add_aprovado_parcial
-- ============================================================================
-- Migration 050 — AP#11 / PRD-0007-EXT.
-- Adiciona valor `aprovado_parcial` ao ENUM status_lote.
-- 1 passo (so adicao) — paridade Migration 035.

SET SESSION sql_mode = '';

ALTER TABLE agente_lote_resgate
  MODIFY status_lote ENUM(
    'pendente_aprovacao',
    'aguardando_pagamento',
    'pago',
    'liquidado',
    'estornado',
    'reprovado_tef_net',
    'aprovado_parcial'
  ) NOT NULL DEFAULT 'pendente_aprovacao'
  COMMENT 'Estado do lote no fluxo conta corrente (ADR-0010). aprovado_parcial: AP#11/PRD-0007-EXT — pagamento travado ate parceiro reanexar correcao (1 chance, vide correcao_tentativas).';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_050_alter_status_lote_add_aprovado_parcial', 'up', 'consolidado producao');


-- ============================================================================
-- 20260513_051_alter_agente_lote_resgate_add_correcao
-- ============================================================================
-- Migration 051 — AP#11 / PRD-0007-EXT.
-- Reprovacao categorizada (FK agente_motivo_reprovacao) + ciclo de correcao
-- (1 chance de aprovado_parcial — contador correcao_tentativas).

SET SESSION sql_mode = '';

ALTER TABLE agente_lote_resgate
  ADD COLUMN reprovado_motivo_categoria_id INT NULL
    COMMENT 'AP#11 — FK agente_motivo_reprovacao.id; substitui reprovado_motivo (texto livre) como fonte canonica.'
    AFTER reprovado_motivo,
  ADD COLUMN reprovado_observacao TEXT NULL
    COMMENT 'AP#11 — Observacao detalhada (5-1000 chars) obrigatoria pelo endpoint resgate_reprovar.php.'
    AFTER reprovado_motivo_categoria_id,
  ADD COLUMN correcao_tentativas TINYINT NOT NULL DEFAULT 0
    COMMENT 'AP#11 — Contador de correcoes ja aceitas. >=1 bloqueia novo aprovado_parcial (regra dura: 1 chance).'
    AFTER reprovado_observacao,
  ADD COLUMN correcao_aberta_em DATETIME NULL
    COMMENT 'AP#11 — Quando Tef.Net abriu a pendencia (transicao -> aprovado_parcial).'
    AFTER correcao_tentativas,
  ADD COLUMN correcao_aberta_motivo_categoria_id INT NULL
    COMMENT 'AP#11 — FK agente_motivo_reprovacao.id (motivo da pendencia de correcao).'
    AFTER correcao_aberta_em,
  ADD COLUMN correcao_aberta_observacao TEXT NULL
    COMMENT 'AP#11 — O que precisa ser corrigido (obrigatorio quando decisao=parcial).'
    AFTER correcao_aberta_motivo_categoria_id;

ALTER TABLE agente_lote_resgate
  ADD CONSTRAINT fk_alr_rep_motivo_cat
    FOREIGN KEY (reprovado_motivo_categoria_id)
    REFERENCES agente_motivo_reprovacao(id)
    ON DELETE SET NULL,
  ADD CONSTRAINT fk_alr_cor_motivo_cat
    FOREIGN KEY (correcao_aberta_motivo_categoria_id)
    REFERENCES agente_motivo_reprovacao(id)
    ON DELETE SET NULL;

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_051_alter_agente_lote_resgate_add_correcao', 'up', 'consolidado producao');


-- ============================================================================
-- 20260513_052_create_agente_lote_anexo_check
-- ============================================================================
-- Migration 052 — AP#11 / PRD-0007-EXT.
-- Persiste os 3 checks do operador Tef.Net (NF / Boleto-ou-Pix / Valor) no
-- modal de validacao. UNIQUE (lote_id, tipo_check) garante idempotencia.

SET SESSION sql_mode = '';

CREATE TABLE IF NOT EXISTS agente_lote_anexo_check (
  id          INT AUTO_INCREMENT PRIMARY KEY,
  lote_id     INT NOT NULL,
  tipo_check  ENUM('nf','boleto_pix','valor') NOT NULL
              COMMENT 'AP#11 — Qual dos 3 cards de validacao foi marcado.',
  checado_em  DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
  checado_by  INT NULL COMMENT 'tbl_Usuario.id_user do operador; NULL em DEV',
  UNIQUE KEY uq_lote_check (lote_id, tipo_check),
  CONSTRAINT fk_alac_lote
    FOREIGN KEY (lote_id) REFERENCES agente_lote_resgate(id)
    ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
  COMMENT='AP#11 (PRD-0007-EXT) — Checks individuais (NF/Pix-Boleto/Valor) do operador Tef.Net por lote.';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_052_create_agente_lote_anexo_check', 'up', 'consolidado producao');


-- ============================================================================
-- 20260513_053_seed_motivos_reprovacao_iniciais
-- ============================================================================
-- Migration 053 — AP#11 / PRD-0007-EXT.
-- Seed idempotente dos 5 motivos comuns.

SET SESSION sql_mode = '';

INSERT INTO agente_motivo_reprovacao (descricao, ativo, criado_por)
SELECT 'Nota Fiscal invalida', 1, NULL
WHERE NOT EXISTS (
  SELECT 1 FROM agente_motivo_reprovacao WHERE descricao = 'Nota Fiscal invalida'
);

INSERT INTO agente_motivo_reprovacao (descricao, ativo, criado_por)
SELECT 'Chave Pix invalida', 1, NULL
WHERE NOT EXISTS (
  SELECT 1 FROM agente_motivo_reprovacao WHERE descricao = 'Chave Pix invalida'
);

INSERT INTO agente_motivo_reprovacao (descricao, ativo, criado_por)
SELECT 'Boleto vencido', 1, NULL
WHERE NOT EXISTS (
  SELECT 1 FROM agente_motivo_reprovacao WHERE descricao = 'Boleto vencido'
);

INSERT INTO agente_motivo_reprovacao (descricao, ativo, criado_por)
SELECT 'Valor divergente', 1, NULL
WHERE NOT EXISTS (
  SELECT 1 FROM agente_motivo_reprovacao WHERE descricao = 'Valor divergente'
);

INSERT INTO agente_motivo_reprovacao (descricao, ativo, criado_por)
SELECT 'Documentacao incompleta', 1, NULL
WHERE NOT EXISTS (
  SELECT 1 FROM agente_motivo_reprovacao WHERE descricao = 'Documentacao incompleta'
);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_053_seed_motivos_reprovacao_iniciais', 'up', 'consolidado producao');


-- ============================================================================
-- 20260513_054_alter_tbl_permissao_motivo_reprovacao_editar
-- ============================================================================
-- Migration 054 — AP#11 / PRD-0007-EXT.
-- Adiciona flag agente_motivo_reprovacao_editar em tbl_Permissao (legacy
-- MyISAM, newportaltefnet). Padrao ADR-0004 / Migration 009.
--
-- 6 PONTOS SINCRONIZADOS no PHP do newportaltefnet (CLAUDE.md item 24):
--   tblPermission.php (view), inserirPerfil, updatePerfil, updateUsuario,
--   selectUserEdit, selectUserEditPerm. Sincronia PHP fica no AUTH#X
--   correlato — esta migration apenas cria a coluna.

ALTER TABLE tbl_Permissao
  ADD COLUMN agente_motivo_reprovacao_editar CHAR(1) NOT NULL DEFAULT 'N'
    COMMENT '[satelite:agente] AP#11 — Cadastrar/editar motivos de reprovacao de resgate (CRUD em agente_motivo_reprovacao).';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_054_alter_tbl_permissao_motivo_reprovacao_editar', 'up', 'consolidado producao');


-- ============================================================================
-- 20260513_055_alter_agente_motivo_reprovacao_unique_descricao
-- ============================================================================
-- Migration 055 — DT race motivo_reprovacao_salvar (13/05/2026).
--
-- Igor-Security RESSALVA-6: SELECT WHERE descricao = :desc → INSERT sem transação
-- nem UNIQUE permitia 2 cliques paralelos passarem pelo SELECT e inserirem ambos
-- (cosmético — dropdown duplicado, mas é débito limpo).
--
-- Fix: UNIQUE em descricao. INSERT cego dispara SQLSTATE 23000 quando duplica
-- e o endpoint captura + retorna 409 DESCRICAO_DUPLICADA.

SET SESSION sql_mode = '';

ALTER TABLE agente_motivo_reprovacao
    ADD UNIQUE KEY uq_descricao (descricao);

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260513_055_alter_agente_motivo_reprovacao_unique_descricao', 'up', 'consolidado producao');


-- ============================================================================
-- 20260514_056_consolidar_status_lote_pago
-- ============================================================================
-- Migration 056 — AP#13 (14/05/2026).
-- Consolida ENUM status_lote / status_item: remove 'liquidado' (migra histórico → 'pago').
-- Padrão ALTER ENUM 3 passos (CLAUDE.md item 11) por causa de strict_trans_tables.
--
-- ESCOPO:
--   Tabela A: agente_lote_resgate.status_lote — remove 'liquidado'.
--   Tabela B: agente_apuracao_itens.status_item — remove 'liquidado', adiciona 'pago'.
--
-- DESTRUTIVO: o UPDATE perde a distinção entre lotes/itens originalmente
-- 'liquidado' vs 'pago' (ambos viram 'pago').

SET SESSION sql_mode = '';

-- ---- Tabela A: agente_lote_resgate.status_lote ----
ALTER TABLE agente_lote_resgate
  MODIFY status_lote ENUM(
    'pendente_aprovacao','aguardando_pagamento','pago','liquidado',
    'estornado','reprovado_tef_net','aprovado_parcial'
  ) NOT NULL DEFAULT 'pendente_aprovacao'
  COMMENT 'Migration 056 (passo 1/3): ENUM expandido pra UPDATE seguro.';

UPDATE agente_lote_resgate SET status_lote = 'pago' WHERE status_lote = 'liquidado';

ALTER TABLE agente_lote_resgate
  MODIFY status_lote ENUM(
    'pendente_aprovacao','aguardando_pagamento','pago',
    'estornado','reprovado_tef_net','aprovado_parcial'
  ) NOT NULL DEFAULT 'pendente_aprovacao'
  COMMENT 'AP#13/Migration 056: removido valor liquidado (consolidado em pago).';

-- ---- Tabela B: agente_apuracao_itens.status_item ----
ALTER TABLE agente_apuracao_itens
  MODIFY status_item ENUM(
    'disponivel','em_lote','liquidado','pago','estornado'
  ) NOT NULL DEFAULT 'disponivel'
  COMMENT 'Migration 056 (passo 1/3): ENUM expandido com pago, mantendo liquidado pro UPDATE.';

UPDATE agente_apuracao_itens SET status_item = 'pago' WHERE status_item = 'liquidado';

ALTER TABLE agente_apuracao_itens
  MODIFY status_item ENUM(
    'disponivel','em_lote','pago','estornado'
  ) NOT NULL DEFAULT 'disponivel'
  COMMENT 'AP#13/Migration 056: removido valor liquidado (consolidado em pago).';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260514_056_consolidar_status_lote_pago', 'up', 'consolidado producao');


-- ============================================================================
-- 20260515_057_rename_log_acao_lote_marcar_pago
-- ============================================================================
-- Migration 057 — AP#13 limpeza retroativa (15/05/2026).
-- Renomeia ação no log forense `lote_liquidar` → `lote_marcar_pago` pra alinhar
-- com o vocabulário UI introduzido pelo AP#13.
--
-- Em pré-produção, "preservar compatibilidade" cria pontos ocultos sem benefício
-- (memória `feedback_pre_producao_rename_livre_pos_producao_preserva`).

UPDATE agente_log_acao
   SET acao = 'lote_marcar_pago'
 WHERE acao = 'lote_liquidar';

INSERT IGNORE INTO agente_migrations (version, direction, notes) VALUES ('20260515_057_rename_log_acao_lote_marcar_pago', 'up', 'consolidado producao');


-- ============================================================================
-- FIM DA APLICAÇÃO — verificação rápida
-- ============================================================================
-- SELECT COUNT(*) AS migrations_aplicadas FROM agente_migrations WHERE direction='up';
-- Esperado: ≥ 47 (apos 049-057 aplicadas; release atual ignora 047/048)
--
-- SHOW TABLES LIKE 'agente_%';
-- Esperado (18 tabelas apos AP#11/AP#13):
--   agente_apuracao, agente_apuracao_item, agente_detalhe, agente_hist_*,
--   agente_liberacao_resgate_extra, agente_log_acao, agente_lote_resgate,
--   agente_lote_item, agente_lote_anexo, agente_lote_anexo_check (NOVO 052),
--   agente_migrations, agente_motivo_reprovacao (NOVO 049, UNIQUE 055),
--   agente_tabela_preco, agente_usuario_vinculo, agente_hist_override_revenda
--
-- SHOW COLUMNS FROM agente_lote_resgate LIKE 'status_lote';
-- Esperado (apos 056): ENUM sem 'liquidado' — pendente_aprovacao,
--   aguardando_pagamento, pago, estornado, reprovado_tef_net, aprovado_parcial.
--
-- SELECT acao, COUNT(*) FROM agente_log_acao GROUP BY acao;
-- Esperado (apos 057): nenhuma linha com acao='lote_liquidar' (renomeada).
--
-- SELECT COUNT(*) AS feriados FROM cadastro_feriados WHERE ativo=1;
-- Esperado: 91 (13 feriados nacionais × 7 anos)
