# Justfile — canonical entry point for build / gen / test / bench / conformance.
#
# `just` is required (https://github.com/casey/just). On macOS:  brew install just
# On Linux:                                                       cargo install just
#
# Quick map of common targets:
#   just                          show available recipes
#   just build                    build both plugins
#   just gen                      regenerate examples/expected/{full,runtime}/*
#   just test                     run the luatest suite
#   just bench                    alloc + throughput per op
#   just conformance              run Google's conformance suite in Docker
#   just examples                 per-example runners (see examples/Justfile)
#
# Sub-recipes live in examples/Justfile (one target per runnable example).

set shell := ["bash", "-cu"]

# ---------------------------------------------------------------------------
# Paths and constants
# ---------------------------------------------------------------------------

plugin            := "protoc-gen-tarantool"
doc_plugin        := "protoc-gen-tarantool-doc"
gen_dir           := "examples/expected"
docs_dir          := "examples/docs"
proto_dir         := "examples/proto"
conformance_proto := "test/conformance/proto"
luatest           := ".rocks/bin/luatest"
image             := "tarantool-protobuf-conformance:latest"

# Semicolon-joined LUA_PATH for the luatest suite. Trailing `;;` defers to the
# standard package.path for everything not explicitly listed.
lua_path := "./runtime/?/init.lua;./runtime/?.lua;./" + gen_dir + "/?.lua;./" + gen_dir + "/?/init.lua;./?.lua;./?/init.lua;./test/?.lua;;"

# ---------------------------------------------------------------------------
# Default
# ---------------------------------------------------------------------------

# Show available recipes.
default:
    @just --list

# Build everything from scratch and run the test suite.
all: build gen test

# ---------------------------------------------------------------------------
# Build
# ---------------------------------------------------------------------------

# Build the Lua codegen plugin (./protoc-gen-tarantool).
build:
    go build -o {{plugin}} ./cmd/protoc-gen-tarantool

# Build the Markdown doc plugin (./protoc-gen-tarantool-doc).
build-doc:
    go build -o {{doc_plugin}} ./cmd/protoc-gen-tarantool-doc

# ---------------------------------------------------------------------------
# Codegen
# ---------------------------------------------------------------------------

# Regenerate examples/expected/{full,runtime}/* + conformance protos.
gen: gen-full gen-runtime gen-conformance

# Generate full-mode Lua (inline encode/decode bodies).
gen-full: build
    mkdir -p {{gen_dir}}
    protoc \
        --plugin=./{{plugin}} \
        --tarantool_out={{gen_dir}} \
        --tarantool_opt=mode=full,prefix=full \
        -I {{proto_dir}} -I options \
        {{proto_dir}}/*.proto

# Generate runtime-mode Lua (delegates to pb.encode / pb.decode).
gen-runtime: build
    mkdir -p {{gen_dir}}
    protoc \
        --plugin=./{{plugin}} \
        --tarantool_out={{gen_dir}} \
        --tarantool_opt=mode=runtime,prefix=runtime \
        -I {{proto_dir}} -I options \
        {{proto_dir}}/*.proto

# Generate the Google conformance protos (TestAllTypesProto3) in both modes.
gen-conformance: build
    mkdir -p {{gen_dir}}
    protoc \
        --plugin=./{{plugin}} \
        --tarantool_out={{gen_dir}} \
        --tarantool_opt=mode=full,prefix=full \
        -I {{conformance_proto}} -I options \
        {{conformance_proto}}/*.proto
    protoc \
        --plugin=./{{plugin}} \
        --tarantool_out={{gen_dir}} \
        --tarantool_opt=mode=runtime,prefix=runtime \
        -I {{conformance_proto}} -I options \
        {{conformance_proto}}/*.proto

# Regenerate Markdown reference docs (examples/docs/*.md) — committed output.
gen-docs: build-doc
    mkdir -p {{docs_dir}}
    protoc \
        --plugin=./{{doc_plugin}} \
        --tarantool-doc_out={{docs_dir}} \
        -I {{proto_dir}} -I options \
        {{proto_dir}}/*.proto

# Regenerate test/interop/fixtures/*.bin via mainline `protoc --encode`.
goldens:
    @for f in test/interop/fixtures/*.txtpb; do \
        type=$(awk '/^# type:/ {print $3; exit}' "$f"); \
        out="${f%.txtpb}.bin"; \
        echo "  protoc --encode=$type < $f > $out"; \
        protoc --encode="$type" -I {{proto_dir}} -I options {{proto_dir}}/hello.proto < "$f" > "$out" || exit $?; \
    done

# ---------------------------------------------------------------------------
# Test
# ---------------------------------------------------------------------------

# Run the luatest suite (639 tests, parametrized over both codegen modes).
test: gen
    LUA_PATH="{{lua_path}}" {{luatest}} -v test/

# Run a single luatest group or test. Example:
#   just test-one protobuf_test.lua::hello.full.test_packed_repeated_int32
test-one filter: gen
    LUA_PATH="{{lua_path}}" {{luatest}} -v test/{{filter}}

# ---------------------------------------------------------------------------
# Bench
# ---------------------------------------------------------------------------

# Microbench: alloc + throughput per op across 5 payload sizes, both modes.
bench: gen
    tarantool bench/bench.lua --print

# Overwrite bench/baseline.json with current alloc-per-op numbers.
bench-baseline: gen
    tarantool bench/bench.lua --baseline

# Fail with exit 1 if any alloc-per-op regressed >5% vs the baseline.
bench-compare: gen
    tarantool bench/bench.lua --compare

# Per-helper microbench for runtime/pb/wire.lua (every primitive).
bench-wire: gen
    tarantool bench/wire_bench.lua

# Shape-variety microbench (scalar-heavy, packed, nested, maps, oneof, WKT).
bench-shapes: gen
    tarantool bench/shapes_bench.lua

# Trace-stability gate: assert hot paths JIT-compile without fatal aborts.
jit-trace: gen
    tarantool bench/jit_trace.lua

# ---------------------------------------------------------------------------
# Conformance (Google's protobuf conformance suite, in Docker)
# ---------------------------------------------------------------------------

# Build the conformance Docker image (idempotent).
conformance-build:
    docker build -t {{image}} -f docker/conformance.Dockerfile docker/

# Run the conformance suite with --enforce_recommended (strictest mode).
conformance: conformance-build gen
    docker run --rm -v "$(pwd):/work" -w /work {{image}}

# Quick pass without --enforce_recommended.
conformance-quick: conformance-build gen
    docker run --rm -v "$(pwd):/work" -w /work --entrypoint conformance_test_runner {{image}} \
        --failure_list test/conformance/known_failures.txt \
        --text_format_failure_list test/conformance/known_failures_text.txt \
        /usr/bin/tarantool cmd/conformance-runner.lua

# Dump failing_tests.txt under test/conformance for triage.
conformance-refresh-failures: conformance-build gen
    docker run --rm -v "$(pwd):/work" -w /work --entrypoint conformance_test_runner {{image}} \
        --enforce_recommended \
        --output_dir /work/test/conformance \
        /usr/bin/tarantool cmd/conformance-runner.lua || true
    @echo "Inspect test/conformance/*failing_tests.txt and update known_failures.txt as needed."

# Open an interactive shell in the conformance image.
conformance-shell: conformance-build
    docker run --rm -it -v "$(pwd):/work" -w /work --entrypoint bash {{image}}

# ---------------------------------------------------------------------------
# Examples — see examples/Justfile for per-example runners
# ---------------------------------------------------------------------------

# Run an example. `just examples` lists per-example recipes.
examples *ARGS:
    just -f examples/Justfile {{ARGS}}

# ---------------------------------------------------------------------------
# Clean
# ---------------------------------------------------------------------------

# Remove built plugin binaries and regenerated outputs.
clean:
    rm -f {{plugin}} {{doc_plugin}}
    rm -rf {{gen_dir}}

# Remove Tarantool instance state that leaked from running examples.
clean-state:
    rm -f *.snap *.xlog *.vylog *.run *.pid 512.lock
    rm -rf /tmp/tarantool-protobuf-*
