-- =============================================================================
-- MIGRACAO ADITIVA v2 - "Jornada e regras de ponto" individuais (ATM-VPS-UP2410)
-- NAO APLICADA. Para revisao e aprovacao. Fazer BACKUP antes de executar.
--
-- Garantias (todas cobertas por testes em MariaDB descartavel - tests/migracao.test.js):
--   * IDEMPOTENTE: pode ser executada varias vezes; so cria o que falta e so preenche o que e NULL.
--   * ADITIVA: so adiciona 8 colunas opcionais em Funcionario. Nada existente e alterado ou apagado.
--   * RegistroPonto, operacoes, auditoria e configuracoes NAO sao alteradas (configuracoes so e LIDA).
--   * Configuracao individual ja preenchida NUNCA e sobrescrita (UPDATE so onde a coluna e NULL).
--   * CONFLITO: se a configuracao global antiga tiver mais de um valor valido diferente, NADA e
--     preenchido ate o revisor definir @tol_override (0 a 5). Ate la o sistema usa a politica padrao
--     de 5 minutos com aviso no relatorio (nenhum dado e perdido).
--   * Valores invalidos (negativo, maior que 5, decimal, texto, vazio, NULL) sao ignorados.
--
-- ORDEM DE IMPLANTACAO: execute ESTE SQL ANTES de subir o codigo novo (o model novo seleciona as
-- colunas novas). O codigo ANTIGO continua funcionando depois da migracao (colunas extras sao ignoradas).
--
-- Convencao de nomes (Sequelize underscored + freezeTableName): tabela Funcionario, coluna jorn_trabalho.
-- CONFIRME no banco real antes (secao 0) e ajuste se os nomes forem diferentes.
-- Nao use ponto e virgula dentro de comentarios: o arquivo e executado por clientes que dividem por ponto e virgula.
-- =============================================================================

-- --- 0. PRE-CHECAGEM (somente leitura) ---------------------------------------
--     SHOW TABLES LIKE 'Funcionario'
--     SHOW COLUMNS FROM Funcionario LIKE 'jorn_trabalho'
--     SHOW COLUMNS FROM configuracoes

-- --- 1. ESTRUTURA (aditiva e idempotente) ------------------------------------
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'tolerancia_ponto_min') = 0,
  'ALTER TABLE Funcionario ADD COLUMN tolerancia_ponto_min TINYINT UNSIGNED NULL COMMENT ''Tolerancia por marcacao em minutos 0 a 5 - CLT art 58 par 1 - NULL usa politica padrao de 5'' AFTER jorn_trabalho', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_batidas') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_batidas TINYINT UNSIGNED NULL COMMENT ''Batidas previstas por jornada 2 ou 4'' AFTER tolerancia_ponto_min', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_perfil') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_perfil VARCHAR(20) NULL COMMENT ''padrao reduzida personalizada - informativo'' AFTER ponto_batidas', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_hora_entrada') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_hora_entrada TIME NULL COMMENT ''Horario previsto de entrada'' AFTER ponto_perfil', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_hora_almoco') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_hora_almoco TIME NULL COMMENT ''Horario previsto de saida para intervalo'' AFTER ponto_hora_entrada', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_hora_retorno') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_hora_retorno TIME NULL COMMENT ''Horario previsto de retorno do intervalo'' AFTER ponto_hora_almoco', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_hora_saida') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_hora_saida TIME NULL COMMENT ''Horario previsto de saida'' AFTER ponto_hora_retorno', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;
SET @s = IF((SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND LOWER(table_name) = 'funcionario' AND column_name = 'ponto_regras_desde') = 0,
  'ALTER TABLE Funcionario ADD COLUMN ponto_regras_desde DATE NULL COMMENT ''Vigencia da configuracao individual de ponto'' AFTER ponto_hora_saida', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;

-- --- 2. VALOR INICIAL DA TOLERANCIA (somente leitura de configuracoes) -------
-- Revisor: para forcar um valor (ou resolver conflito) defina @tol_override com um inteiro de 0 a 5 e reexecute.
SET @tol_override = COALESCE(@tol_override, NULL);
SET @tol_override_ok = IF(@tol_override IS NOT NULL AND @tol_override BETWEEN 0 AND 5 AND @tol_override = FLOOR(@tol_override), @tol_override, NULL);

DROP TEMPORARY TABLE IF EXISTS tmp_tol_fontes;
CREATE TEMPORARY TABLE tmp_tol_fontes (fonte VARCHAR(10), config_id INT, v TINYINT UNSIGNED);
-- (a) linhas por chave - o que RelatorioController.getConfiguracoes() lia
INSERT INTO tmp_tol_fontes
  SELECT 'chave', id, CAST(TRIM(valor) AS UNSIGNED) FROM configuracoes
   WHERE chave IN ('tolerancia_minutos', 'toleranciaMinutos') AND TRIM(valor) REGEXP '^0?[0-5]$';
-- (b) coluna tolerancia_minutos - o que a tela do gerenciador gravava (so se a coluna existir)
SET @tem_col = (SELECT COUNT(*) FROM information_schema.columns WHERE table_schema = DATABASE() AND table_name = 'configuracoes' AND column_name = 'tolerancia_minutos');
SET @s = IF(@tem_col > 0,
  'INSERT INTO tmp_tol_fontes SELECT ''coluna'', id, tolerancia_minutos FROM configuracoes WHERE tolerancia_minutos BETWEEN 0 AND 5', 'DO 0');
PREPARE st FROM @s; EXECUTE st; DEALLOCATE PREPARE st;

SET @n_distintos = (SELECT COUNT(DISTINCT v) FROM tmp_tol_fontes);
-- 0 fontes validas: politica padrao 5 / 1 valor: usa o valor / 2 ou mais valores diferentes: CONFLITO (NULL)
SET @tol_inicial = IF(@tol_override IS NOT NULL, @tol_override_ok,
                      IF(@n_distintos = 0, 5, IF(@n_distintos = 1, (SELECT MIN(v) FROM tmp_tol_fontes), NULL)));

-- 2.1 PREVISUALIZACAO (somente leitura) - conferir antes de seguir
SELECT @n_distintos AS valores_validos_distintos, @tol_override AS override_informado,
       @tol_inicial AS tolerancia_que_sera_gravada,
       CASE WHEN @tol_override IS NOT NULL AND @tol_override_ok IS NULL THEN 'ERRO: @tol_override invalido (use inteiro de 0 a 5) - nada sera gravado'
            WHEN @tol_inicial IS NULL THEN 'CONFLITO: ha mais de um valor valido diferente em configuracoes - defina @tol_override - nada sera gravado'
            ELSE 'OK' END AS situacao;
SELECT fonte, config_id, v FROM tmp_tol_fontes ORDER BY fonte, config_id;
SELECT id, chave, valor FROM configuracoes WHERE chave IN ('tolerancia_minutos', 'toleranciaMinutos');
-- funcionarios sem jornada cadastrada ou legivel: o RH precisa preencher (o sistema NAO assume 08:48)
SELECT id, nome, status, jorn_trabalho FROM Funcionario
 WHERE jorn_trabalho IS NULL OR TRIM(jorn_trabalho) = '' OR NOT (jorn_trabalho REGEXP '^[0-9]{1,2}:[0-9]{2}$');

-- --- 3. CARGA INICIAL (unico UPDATE: coluna nova, apenas onde e NULL) --------
START TRANSACTION;
UPDATE Funcionario SET tolerancia_ponto_min = @tol_inicial WHERE tolerancia_ponto_min IS NULL AND @tol_inicial IS NOT NULL;
SET @linhas_atualizadas = ROW_COUNT();
COMMIT;
DROP TEMPORARY TABLE IF EXISTS tmp_tol_fontes;

-- --- 4. VERIFICACAO (somente leitura) ----------------------------------------
SELECT @linhas_atualizadas AS linhas_atualizadas, COUNT(*) AS funcionarios, SUM(tolerancia_ponto_min IS NULL) AS sem_tolerancia_individual,
       MIN(tolerancia_ponto_min) AS min_tol, MAX(tolerancia_ponto_min) AS max_tol FROM Funcionario;
