-- ---------------------------------------------------------------------------
-- O cupom de sorteio repetido: o segundo cupom com o MESMO NUMERO da mesma venda
-- no mesmo sorteio sai, e o indice unico (sorteio, venda, numero) entra em
-- `sorteios_vendas` (D370; e o D561, o numero do cupom).
--
--   mysql franquiabv < scripts/migracao-sorteios-vendas-unicos.sql
--
-- RODA NO PASSO 3 DA JANELA, E NAO NO PASSO 0 (a resposta 124 (a) do dono, de
-- 12/10/2026, "Sim, na janela do corte", e a 192 (a): o passo 3 e a etapa 2). Ela
-- APAGA LINHA -- o cupom a mais de cada par --, e o laco do passo 0 so leva o que
-- acrescenta; a etapa 1 copia aquele laco.
--
-- PRECISA DA COLUNA `numero`, que o laco do passo 0 acrescenta
-- (`scripts/migracao-sorteios-regra-do-cupom.sql`). Sem ela, o primeiro comando que
-- a cita para com "Unknown column", antes de apagar qualquer coisa.
--
-- DECIDIDO PELO DONO EM 12/10/2026 (pergunta 124 da pagina do lote, a opcao (a)):
-- "O passo conta os pares na producao, tira o segundo cupom de cada venda e cria a
-- regra nos dois bancos; dai em diante o banco recusa o segundo cupom da mesma
-- venda." E A REGRA MUDOU EM 21/10/2026, pelo dono ("trocar a regra do banco", o
-- D561): a venda pode ter varios cupons no mesmo sorteio -- um a cada R$ X do
-- valor, ou um por servico --, numerados 1, 2, 3...; o banco recusa o MESMO NUMERO
-- duas vezes, e nao mais o segundo cupom. Os 4 pares de hoje sao do mesmo numero
-- (o 1, que o passo 0 da a todo cupom de antes) e saem igual. O PostgreSQL nasce
-- com a chave pelo gerador (`$unicidades` de `scripts/gerar-ddl-postgres.php`), e
-- nao pelo `mysql.sql` que o passo 1 refaz da producao, que nao a tem antes da
-- janela.
--
-- A COPIA LOCAL A RECEBEU EM 21/10/2026, nos dois bancos (a resposta 218 (a),
-- 15/10/2026: "Tambem nas duas copias locais, ja"): primeiro com a chave
-- (sorteio, venda), e no mesmo dia trocada pela (sorteio, venda, numero) -- por isso
-- o passo 2b tira a de antes, se ela existir; na producao ela nunca existiu, e o
-- passo nao faz nada. Medido antes, nas duas copias: 4 pares, 4 cupons a mais --
-- um no sorteio #1, um no #3 e dois no #4 --, de 5 s a 1.419 s um do outro, e
-- nenhum dos quatro segundos e o ganhador. A base do teste do BVIP fica como esta
-- ate a proxima copia exportada daqui: o codigo funciona com e sem o indice.
--
-- QUAL CUPOM FICA: o PRIMEIRO do par (o menor id), que e o que o sorteio marca
-- como ganhador (o D72, `SorteioVendaRepository::selecionarVenda`) -- A MENOS QUE o
-- sorteio aponte outro cupom do par como ganhador (`sorteios.ganhador`): entao fica
-- esse, e a chave estrangeira nao recusa o `DELETE`. O que fica leva a marca de
-- ganhador se algum do par a tinha. NENHUM RESULTADO MUDA: o sorteio interno e a
-- planilha ja contam cada cupom (venda e numero) uma vez (desde 21/10/2026, as
-- fatias SORTEIOS-SORTEAR e SORTEIOS-CADASTRO; o DS-2), e o par so dava chance
-- dupla na planilha de antes.
--
-- O CUPOM SEM VENDA OU SEM SORTEIO (as colunas aceitam nulo) NAO E PAR: o indice
-- unico aceita varios nulos, e eles ficam como estao.
--
-- IDEMPOTENTE: sem pares, o UPDATE e o DELETE mudam zero linhas; sem a chave de
-- antes, o passo 2b diz que nao ha o que tirar; com a chave nova, o ALTER diz que
-- ela ja existe. Rodar de novo nao muda nada.
--
-- NAO COPIA A TABELA: indice secundario o InnoDB cria e tira INPLACE, com
-- LOCK=NONE (7.212 cupons na copia). Se o servidor recusar o INPLACE, o ALTER falha
-- e nao muda nada -- e a transacao de antes ja foi: rodar de novo nao a refaz (nada
-- mais a tirar), e tenta o ALTER outra vez.
--
-- E O CODIGO ANTIGO NUMA VOLTA: com o indice, a finalizacao repetida do PDV
-- antigo, que gravava o segundo cupom calada (com o numero 1 do padrao), passa a
-- dar erro ao finalizar. O codigo novo nao repete o cupom
-- (`SorteioService::darCupom` da so os numeros que faltam, sob a trava do sorteio,
-- e a venda nao se finaliza duas vezes desde a fatia 5c).
-- ---------------------------------------------------------------------------

SELECT '=== ANTES: pares (sorteio, venda, numero) repetidos e cupons a mais ===' AS '';
SELECT COUNT(*), COALESCE(SUM(n) - COUNT(*), 0)
  FROM (SELECT COUNT(*) AS n FROM sorteios_vendas
         WHERE sorteio IS NOT NULL AND venda IS NOT NULL
         GROUP BY sorteio, venda, numero HAVING COUNT(*) > 1) p;

-- 1. A LISTA DOS PARES: o sorteio, a venda, o numero, o cupom que fica e os que
--    saem, e os segundos entre o primeiro e o ultimo cupom do par. Vazia quando nao
--    ha par.
SELECT '=== OS PARES: sorteio, venda, numero, o cupom que fica, os que saem, segundos entre eles ===' AS '';
SELECT d.sorteio, d.venda, d.numero, d.fica,
       (SELECT GROUP_CONCAT(s.id ORDER BY s.id) FROM sorteios_vendas s
         WHERE s.sorteio = d.sorteio AND s.venda = d.venda AND s.numero = d.numero AND s.id <> d.fica),
       d.segundos
  FROM (
    SELECT sv.sorteio, sv.venda, sv.numero,
           COALESCE(MIN(CASE WHEN g.id IS NOT NULL THEN sv.id END), MIN(sv.id)) AS fica,
           TIMESTAMPDIFF(SECOND, MIN(sv.data), MAX(sv.data)) AS segundos
      FROM sorteios_vendas sv
      LEFT JOIN sorteios g ON g.ganhador = sv.id
     WHERE sv.sorteio IS NOT NULL AND sv.venda IS NOT NULL
     GROUP BY sv.sorteio, sv.venda, sv.numero
    HAVING COUNT(*) > 1
  ) d
 ORDER BY d.sorteio, d.venda, d.numero;

-- 2. OS PARES, numa transacao: o que fica leva a marca de ganhador do par, e os
--    outros saem.
START TRANSACTION;

UPDATE sorteios_vendas sv
  JOIN (
    SELECT x.sorteio, x.venda, x.numero,
           COALESCE(MIN(CASE WHEN g.id IS NOT NULL THEN x.id END), MIN(x.id)) AS fica,
           MAX(x.ganhador) AS ganhador
      FROM sorteios_vendas x
      LEFT JOIN sorteios g ON g.ganhador = x.id
     WHERE x.sorteio IS NOT NULL AND x.venda IS NOT NULL
     GROUP BY x.sorteio, x.venda, x.numero
    HAVING COUNT(*) > 1
  ) d ON d.fica = sv.id
   SET sv.ganhador = d.ganhador;

DELETE sv FROM sorteios_vendas sv
  JOIN (
    SELECT x.sorteio, x.venda, x.numero,
           COALESCE(MIN(CASE WHEN g.id IS NOT NULL THEN x.id END), MIN(x.id)) AS fica
      FROM sorteios_vendas x
      LEFT JOIN sorteios g ON g.ganhador = x.id
     WHERE x.sorteio IS NOT NULL AND x.venda IS NOT NULL
     GROUP BY x.sorteio, x.venda, x.numero
    HAVING COUNT(*) > 1
  ) d ON d.sorteio = sv.sorteio AND d.venda = sv.venda AND d.numero = sv.numero
 WHERE sv.id <> d.fica;

COMMIT;

-- 2b. A CHAVE DE ANTES (sorteio, venda), que so as copias locais tiveram, por
--     algumas horas de 21/10/2026: com ela, a venda nao teria o cupom 2.
SELECT '=== A CHAVE DE ANTES: o aviso, se ela nao existe ===' AS '';

SET @existe = (
    SELECT COUNT(*) FROM information_schema.statistics
     WHERE table_schema = DATABASE()
       AND table_name = 'sorteios_vendas'
       AND index_name = 'uq_sorteios_vendas_sorteio_venda'
);

SET @sql = IF(@existe = 0,
    'SELECT ''a chave de antes nao existe, nada a tirar'' AS aviso',
    'ALTER TABLE sorteios_vendas
       DROP INDEX uq_sorteios_vendas_sorteio_venda,
       ALGORITHM=INPLACE, LOCK=NONE'
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

-- 3. A CHAVE, com os pares ja tirados. Na segunda vez, o aviso de que ela ja existe.
SELECT '=== A CHAVE: o aviso, se ela ja existe ===' AS '';

SET @existe = (
    SELECT COUNT(*) FROM information_schema.statistics
     WHERE table_schema = DATABASE()
       AND table_name = 'sorteios_vendas'
       AND index_name = 'uq_sorteios_vendas_sorteio_venda_numero'
);

SET @sql = IF(@existe = 0,
    'ALTER TABLE sorteios_vendas
       ADD UNIQUE KEY uq_sorteios_vendas_sorteio_venda_numero (sorteio, venda, numero),
       ALGORITHM=INPLACE, LOCK=NONE',
    'SELECT ''o indice dos cupons ja existe, nada a fazer'' AS aviso'
);

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SELECT '=== DEPOIS: pares (sorteio, venda, numero) repetidos (tem que ser zero) ===' AS '';
SELECT COUNT(*)
  FROM (SELECT 1 FROM sorteios_vendas
         WHERE sorteio IS NOT NULL AND venda IS NOT NULL
         GROUP BY sorteio, venda, numero HAVING COUNT(*) > 1) p;

SELECT '=== INDICE: o nome, as colunas e se e unico (0) ===' AS '';
SELECT index_name, GROUP_CONCAT(column_name ORDER BY seq_in_index), MAX(non_unique)
  FROM information_schema.statistics
 WHERE table_schema = DATABASE()
   AND table_name = 'sorteios_vendas'
   AND index_name IN ('uq_sorteios_vendas_sorteio_venda', 'uq_sorteios_vendas_sorteio_venda_numero')
 GROUP BY index_name;
