#!/usr/bin/env bash
#
# O PORTAO DO RELOGIO NOS TESTES, POSTO A PROVA -- D440, desde 07/11/2026 (a
# verificacao da fatia 102, CI-VERDE-NO-RUNNER).
#
#     bash scripts/ensaiar-portao-do-relogio.sh
#
# POR QUE ISTO EXISTE. O `conferir-relogio-nos-testes.php` falha nos dois
# sentidos -- leitura nova acusa, excecao sem uso tambem --, e por isso arrancar
# a regra do `new` INTEIRA ja o deixa vermelho (as excecoes declaradas deixam de
# ser achadas). As variacoes finas nao: o `new` sem parentese, o `null`, o texto
# julgado como data absoluta, o nome com a barra (`\microtime(`, que o PHP 8
# entrega como um token so). Mudar uma delas deixava o portao verde, porque hoje
# nenhum teste de verdade usa a forma -- a verificacao da 102 os mutou so numa
# copia. Cada forma e um arquivo aqui, com o que o portao tem de dizer dele.
#
# COMO. Os casos sao arquivos PHP num diretorio temporario, um por forma, e o
# portao roda sobre esse diretorio (o primeiro argumento dele). Ele sai 1 ali de
# qualquer jeito -- as excecoes da `PERMITIDAS` nao estao no diretorio --, entao
# o ensaio le as LINHAS: cada arquivo plantado com uma leitura tem de aparecer
# com a chave e a conta certas; cada arquivo sem leitura nao pode aparecer.
#
# Saida: 0 com todos os casos na saida esperada; 1 com algum fora dela; 2 quando
# nao consegue montar os casos ou o portao nao chega a ler o diretorio.
#
# PARA VER O ENSAIO PEGAR UM DEFEITO, aponte-o para outra versao do portao:
#
#     PORTAO_A_ENSAIAR=/caminho/da/versao.php bash scripts/ensaiar-portao-do-relogio.sh

set -u
cd "$(dirname "$0")/.."
RAIZ=$(pwd)
PORTAO="${PORTAO_A_ENSAIAR:-$RAIZ/scripts/conferir-relogio-nos-testes.php}"

T=$(mktemp -d) || { echo "Nao consegui criar o diretorio temporario." >&2; exit 2; }
trap 'rm -rf "$T"' EXIT

# Um arquivo de caso: o nome e o corpo de um metodo.
planta() {
    printf '<?php\n\nclass %s\n{\n    public function caso(): void\n    {\n        %s\n    }\n}\n' "${1%.php}" "$2" > "$T/$1" ||
        { echo "NAO CONSEGUI MONTAR O CASO: $1" >&2; exit 2; }
}

# --- o que o portao TEM de acusar: arquivo, chave e quantas vezes ---------------
# O `'2026'` sozinho parece um ano e e uma HORA (20:26 de hoje, para o PHP): le o relogio.
LE=(
    "NewSemParentese.php|\$a = new \\DateTime;|new DateTime|1"
    "NewVazio.php|\$a = new \\DateTimeImmutable();|new DateTimeImmutable|1"
    "NewNull.php|\$a = new DateTime(null);|new DateTime|1"
    "NewRelativo.php|\$a = new \\DateTime('+1 day');|new DateTime|1"
    "NewTodayComFuso.php|\$a = new \\DateTimeImmutable('today', new \\DateTimeZone('America/Sao_Paulo'));|new DateTimeImmutable|1"
    "NewHoraSo.php|\$a = new \\DateTimeImmutable('15:00');|new DateTimeImmutable|1"
    "NewAnoSo.php|\$a = new \\DateTime('2026');|new DateTime|1"
    "DateCreate.php|\$a = date_create('+1 day');|date_create|1"
    "DateCreateComBarra.php|\$a = \\date_create_immutable();|date_create_immutable|1"
    "Gmdate.php|\$a = gmdate('Y');|gmdate|1"
    "Idate.php|\$a = idate('Y');|idate|1"
    "Hrtime.php|\$a = hrtime(true);|hrtime|1"
    "MicrotimeComBarra.php|\$a = \\microtime(true);|microtime|1"
    "DateComBarra.php|\$a = \\date('Y-m-d');|date|1"
    "DuasLeituras.php|\$a = new \\DateTime('now'); \$b = new \\DateTime('now');|new DateTime|2"
)

# --- o que o portao NAO pode acusar ----------------------------------------------
NAO_LE=(
    "DataAbsoluta.php|\$a = new \\DateTime('2026-03-15 00:00:01'); \$b = date_create('2026-01-01');"
    "Segundos.php|\$a = new \\DateTimeImmutable('@1700000000');"
    "AgoraDaSuite.php|\$a = new \\DateTimeImmutable(\$this->agora());"
    "SoComentario.php|// new \\DateTime('now'); microtime(true); \\date('Y')"
    "NamespaceAlheio.php|\$a = \\Outro\\Lugar\\microtime(1);"
    "ClasseAlheia.php|\$a = new \\DateTimeZone('UTC');"
)

for c in "${LE[@]}"; do
    IFS='|' read -r arq corpo _ _ <<< "$c"
    planta "$arq" "$corpo"
done
for c in "${NAO_LE[@]}"; do
    IFS='|' read -r arq corpo <<< "$c"
    planta "$arq" "$corpo"
done

SAIDA=$(php "$PORTAO" "$T" 2>&1)
CODIGO=$?

if [ "$CODIGO" -eq 2 ] || ! printf '%s\n' "$SAIDA" | grep -q "arquivos lidos: *$(( ${#LE[@]} + ${#NAO_LE[@]} ))\$"; then
    echo "O portao nao leu o diretorio dos casos (saida $CODIGO):" >&2
    printf '%s\n' "$SAIDA" | head -20 >&2
    exit 2
fi

n=0
falhas=0

for c in "${LE[@]}"; do
    IFS='|' read -r arq _ chave vezes <<< "$c"
    n=$((n + 1))
    esperada="$arq::$chave le o relogio $vezes vez(es)"
    if printf '%s\n' "$SAIDA" | grep -qF "$esperada"; then
        echo "  ok    $esperada"
    else
        echo "  FORA  esperava \"$esperada\" -- veio: $(printf '%s\n' "$SAIDA" | grep -F "$arq" | head -1)"
        falhas=$((falhas + 1))
    fi
done

for c in "${NAO_LE[@]}"; do
    IFS='|' read -r arq _ <<< "$c"
    n=$((n + 1))
    if printf '%s\n' "$SAIDA" | grep -qF "$arq"; then
        echo "  FORA  $arq nao le o relogio, e o portao o acusou: $(printf '%s\n' "$SAIDA" | grep -F "$arq" | head -1)"
        falhas=$((falhas + 1))
    else
        echo "  ok    $arq nao acusado"
    fi
done

echo ''
echo "  $n casos, $falhas fora da saida esperada."
echo ''
[ "$falhas" -eq 0 ] || exit 1
exit 0
