#!/usr/bin/env bash
# check-phpstan-gate-freshness.sh — R8BE-104 gate-staleness guard
#
# Verifies that gate-phpstan.log is NEWER than the newest PHP source file in
# app/, so a stale log can never pass the phpstan-green bar without a re-run.
#
# This is a LOCAL-only check (gate-phpstan.log is gitignored). Run it:
#   - Before accepting gate-phpstan.log as evidence of a green bar
#   - As part of the wave bar verification sequence
#
# NOTE: mtime comparison can report STALE after a git checkout/branch switch
# because git rewrites tracked source mtimes to 'now'. This is conservative
# (fails safe toward re-running) — use --fix to self-heal.
#
# Usage:
#   bash scripts/check-phpstan-gate-freshness.sh [--fix]
#
#   --fix   Re-run phpstan and update gate-phpstan.log if stale. Writes to a
#           temp file atomically; will NOT clobber the existing log on tool
#           failure. Exits 0 on green, non-zero if phpstan reports errors or
#           is missing.
#
# Exit codes:
#   0  gate-phpstan.log exists, is newer than all app/ PHP files, and contains
#      "[OK] No errors"
#   1  gate-phpstan.log is stale (app/ has newer PHP files) — re-run required
#   2  gate-phpstan.log is missing — must run phpstan first
#   3  gate-phpstan.log present and fresh but contains errors / phpstan errors
#      on --fix run (phpstan ran but reported failures)
#   4  phpstan binary missing or non-executable (only in --fix mode)

set -euo pipefail

# Anchor to repo root via SCRIPT_DIR so this works from any subdirectory.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || echo "$SCRIPT_DIR/..")"
GATE_LOG="$REPO_ROOT/gate-phpstan.log"
PHPSTAN="$REPO_ROOT/vendor/bin/phpstan"
FIX_MODE=0

for arg in "$@"; do
    case "$arg" in
        --fix) FIX_MODE=1 ;;
    esac
done

# ── Step 1: existence check ───────────────────────────────────────────────────
if [ ! -f "$GATE_LOG" ]; then
    echo "ERROR: gate-phpstan.log not found at $GATE_LOG" >&2
    echo "Run: \"$PHPSTAN\" analyse --memory-limit=1G --no-progress > \"$GATE_LOG\"" >&2
    exit 2
fi

# ── Step 2: staleness check ───────────────────────────────────────────────────
# Use -print -quit to stop find after the first match (find exits 0, no SIGPIPE).
# This avoids the `find … | head -1` SIGPIPE/set-e abort that kills the script
# with exit 141 when many files are newer than the log.
STALE_SIGNAL=0
if [ -d "$REPO_ROOT/app" ]; then
    FIRST_NEWER=$(find "$REPO_ROOT/app" -name "*.php" -newer "$GATE_LOG" -print -quit 2>/dev/null || true)
    [ -n "$FIRST_NEWER" ] && STALE_SIGNAL=1
fi

if [ "$STALE_SIGNAL" = "1" ]; then
    echo "STALE: gate-phpstan.log is older than at least one app/ source file:" >&2
    # Secondary diagnostic loop — safe: iterated via process substitution, no head pipe.
    while IFS= read -r f; do
        echo "  newer: $f" >&2
    done < <(find "$REPO_ROOT/app" -name "*.php" -newer "$GATE_LOG" 2>/dev/null || true)

    if [ "$FIX_MODE" = "1" ]; then
        if [ ! -x "$PHPSTAN" ]; then
            echo "ERROR: phpstan not found or not executable at $PHPSTAN" >&2
            exit 4
        fi
        echo "Fixing: re-running phpstan..." >&2
        # Write to a temp file first; only replace the real log on success.
        # This prevents clobbering a previously-green log if phpstan itself fails.
        TMP_LOG=$(mktemp)
        RC=0
        "$PHPSTAN" analyse --memory-limit=1G --no-progress > "$TMP_LOG" 2>&1 || RC=$?
        if [ "$RC" -ne 0 ]; then
            echo "ERROR: phpstan exited $RC — errors below, gate-phpstan.log NOT updated:" >&2
            cat "$TMP_LOG" >&2
            rm -f "$TMP_LOG"
            exit 3
        fi
        mv "$TMP_LOG" "$GATE_LOG"
        echo "Fixed: gate-phpstan.log refreshed" >&2
    else
        echo "Re-run: \"$PHPSTAN\" analyse --memory-limit=1G --no-progress > \"$GATE_LOG\"" >&2
        echo "  or:  bash scripts/check-phpstan-gate-freshness.sh --fix" >&2
        exit 1
    fi
fi

# ── Step 3: content check ─────────────────────────────────────────────────────
if ! grep -q '\[OK\] No errors' "$GATE_LOG"; then
    echo "FAIL: gate-phpstan.log does not contain '[OK] No errors'" >&2
    echo "Content:" >&2
    cat "$GATE_LOG" >&2
    exit 3
fi

echo "PASS: gate-phpstan.log is fresh and green"
exit 0
