#!/usr/bin/env bash
#
# Confere se o inventario de acoes commitado ainda bate com o codigo.
#
#     sh scripts/conferir-inventario-atual.sh
#
# Sai com 1 se `docs/inventario-acoes.md` ou `.csv` estiverem defasados em
# relacao ao que `scripts/inventariar-acoes.php` produz hoje.
#
# POR QUE ISTO EXISTE. O inventario e ARQUIVO GERADO, e nada obrigava a
# regera-lo. Ele ja ficou velho pelo menos duas vezes:
#
#   - `Convenios::atualizarVencimento` mudou de modulo durante o D50 e o
#     arquivo seguiu apontando o modulo antigo;
#   - `yungasNpsAtualizar` foi removida em 31/08 (D43) e so nao ficou
#     sobrando porque lembrei de rodar o gerador na mesma tarde.
#
# Inventario velho nao da erro: ele responde com confianca um numero que nao
# vale mais. E o roadmap decide escopo de fase por esses numeros -- foi um
# deles que rotulou 29 rotinas de cron como "contrato do aplicativo" (D70).
#
# ELE NAO ALTERA NADA. O gerador escreve em caminho fixo, entao este roteiro
# guarda os dois arquivos, roda, compara e DEVOLVE os originais -- aconteca o
# que acontecer. Quem decide regerar e voce, com o comando que ele imprime.

set -eu

RAIZ="$(cd "$(dirname "$0")/.." && pwd)"
MD="$RAIZ/docs/inventario-acoes.md"
CSV="$RAIZ/docs/inventario-acoes.csv"

for f in "$MD" "$CSV"; do
    if [ ! -f "$f" ]; then
        echo "nao achei $f -- rode a partir da raiz do projeto." >&2
        exit 2
    fi
done

GUARDA="$(mktemp -d)"
cp "$MD" "$GUARDA/md.antes"
cp "$CSV" "$GUARDA/csv.antes"

# O restore roda mesmo se o gerador morrer no meio: deixar o inventario
# meio-escrito seria pior do que nao conferir.
restaurar() {
    cp "$GUARDA/md.antes" "$MD"
    cp "$GUARDA/csv.antes" "$CSV"
    rm -r -f "$GUARDA"
}
trap restaurar EXIT INT TERM

if ! php "$RAIZ/scripts/inventariar-acoes.php" > "$GUARDA/saida-do-gerador.txt" 2>&1; then
    echo "O GERADOR FALHOU. A saida dele:"
    echo
    cat "$GUARDA/saida-do-gerador.txt"
    exit 2
fi

cp "$MD" "$GUARDA/md.agora"
cp "$CSV" "$GUARDA/csv.agora"

# Verde sobre nada nao e verde. Se o gerador escrever um arquivo curto, a
# comparacao passaria por dois arquivos igualmente vazios.
LINHAS_MD=$(wc -l < "$GUARDA/md.agora")
LINHAS_CSV=$(wc -l < "$GUARDA/csv.agora")

if [ "$LINHAS_MD" -lt 300 ] || [ "$LINHAS_CSV" -lt 200 ]; then
    echo "O gerador produziu arquivos curtos demais para acreditar:"
    echo "  inventario-acoes.md   $LINHAS_MD linhas (esperava mais de 300)"
    echo "  inventario-acoes.csv  $LINHAS_CSV linhas (esperava mais de 200)"
    echo
    echo "Isso e falha do gerador, nao inventario defasado. Nao confie no verde."
    exit 2
fi

# ---------------------------------------------------------------------------
# Segunda opiniao sobre a COMPLETUDE, por um mecanismo diferente.
#
# Comparar gerado-contra-commitado tem um ponto cego: os dois vem do mesmo
# gerador. Se ele parar de ENXERGAR uma acao, os dois concordam e o portao
# fica verde -- que e o "verde sobre nada" de sempre, uma camada acima.
#
# O QUE ELE PEGA, E O QUE NAO PEGA -- e isso mudou em 31/08/2026.
#
# Quando este contador nasceu, o gerador achava as acoes SO por expressao
# regular no texto, e a independencia era total. Ele acusou na primeira
# execucao: 360 contra 361, e a sobra era um metodo inteiramente comentado
# que a regex contava como acao (D70).
#
# A correcao daquilo fez o gerador passar a cruzar a regex COM o tokenizador.
# Os dois ficaram menos independentes, e isso precisa ser dito:
#
#   PEGA      regex do gerador que quebre ou passe a ver de menos -- o
#             gerador produziria menos linhas do que este contador acha
#   PEGA      acao que apareca em comentario ou string
#   NAO PEGA  erro de logica que os dois compartilhem, porque os dois
#             passaram a usar `token_get_all` para decidir o que e nome real
#
# O que sobra de independente: este exige visibilidade PUBLICA e o gerador
# nao. Nao e muito. Se um dia a completude do inventario voltar a importar
# de verdade, o contador honesto e outro -- contar rotas declaradas no
# `module.config.php` e cruzar com as acoes, que e evidencia de outra fonte.
# ---------------------------------------------------------------------------

ACOES_CODIGO=$(php <<'PHPFIM'
<?php
$raiz = getcwd();
$total = 0;

foreach (glob($raiz . '/module/*/src/Controller/*.php') as $arquivo) {
    $tk = token_get_all(file_get_contents($arquivo));
    $n = count($tk);

    for ($i = 0; $i < $n; $i++) {
        if (!is_array($tk[$i]) || $tk[$i][0] !== T_FUNCTION) {
            continue;
        }

        // O nome vem depois do T_FUNCTION.
        $nome = null;
        for ($j = $i + 1; $j < $n; $j++) {
            if (is_array($tk[$j]) && $tk[$j][0] === T_WHITESPACE) {
                continue;
            }
            if (is_array($tk[$j]) && $tk[$j][0] === T_STRING) {
                $nome = $tk[$j][1];
            }
            break;
        }

        if ($nome === null || substr($nome, -6) !== 'Action') {
            continue;
        }

        // Visibilidade: olha para tras ate achar public/private/protected.
        $publico = true;
        for ($k = $i - 1; $k >= 0 && $k > $i - 6; $k--) {
            if (!is_array($tk[$k])) {
                continue;
            }
            if ($tk[$k][0] === T_PRIVATE || $tk[$k][0] === T_PROTECTED) {
                $publico = false;
                break;
            }
            if ($tk[$k][0] === T_PUBLIC) {
                break;
            }
        }

        if ($publico) {
            $total++;
        }
    }
}

echo $total;
PHPFIM
)

ACOES_CSV=$(( LINHAS_CSV - 1 ))

if [ "$ACOES_CODIGO" -ne "$ACOES_CSV" ]; then
    echo "O GERADOR E O CODIGO DISCORDAM SOBRE QUANTAS ACOES EXISTEM."
    echo
    echo "  metodos *Action publicos no codigo:  $ACOES_CODIGO"
    echo "  linhas no inventario gerado:         $ACOES_CSV"
    echo
    echo "  Os dois contam a mesma coisa por mecanismos diferentes -- o gerador"
    echo "  por expressao regular no texto, este por token_get_all. Se eles"
    echo "  divergem, o inventario esta INCOMPLETO ou INFLADO, e comparar"
    echo "  gerado-contra-commitado nao pegaria isso: os dois viriam do mesmo"
    echo "  gerador cego."
    echo
    echo "  Leia scripts/inventariar-acoes.php linha 118 antes de qualquer outra"
    echo "  coisa: e la que ele decide o que e uma acao."
    exit 1
fi

echo "=============================================================================="
echo "INVENTARIO DE ACOES -- O COMMITADO AINDA BATE COM O CODIGO?"
echo "=============================================================================="
echo
echo "  acoes no CSV commitado:   $(( $(wc -l < "$GUARDA/csv.antes") - 1 ))"
echo "  acoes no CSV gerado hoje: $(( LINHAS_CSV - 1 ))"
echo

DIFERENTES=0

if ! cmp -s "$GUARDA/md.antes" "$GUARDA/md.agora"; then
    DIFERENTES=1
    echo "  docs/inventario-acoes.md   DEFASADO"
fi

if ! cmp -s "$GUARDA/csv.antes" "$GUARDA/csv.agora"; then
    DIFERENTES=1
    echo "  docs/inventario-acoes.csv  DEFASADO"
fi

if [ "$DIFERENTES" -eq 0 ]; then
    echo "  Os dois batem com o codigo."
    exit 0
fi

echo
echo "  O que mudou no CSV (as 20 primeiras linhas do diff):"
echo
diff "$GUARDA/csv.antes" "$GUARDA/csv.agora" | head -20 | sed 's/^/      /' || true

echo
echo "  Os arquivos do repositorio NAO foram alterados por este roteiro."
echo "  Para atualiza-los:"
echo
echo "      php scripts/inventariar-acoes.php"
echo
echo "  Confira o diff antes de commitar: uma acao que some do inventario pode"
echo "  ser remocao intencional ou rota que parou de ser reconhecida (D70)."

exit 1
