# SMGW PKI · Monorepo runner.
# Run `just` (no args) to list recipes.

set shell := ["bash", "-euo", "pipefail", "-c"]

repo := justfile_directory()
deploy := repo / "deploy"
backend := repo / "backend"
frontend := repo / "frontend"

# Default target — print recipe list.
default:
    @just --list --unsorted

# ─── Compose lifecycle ───────────────────────────────────────────────────────

# Bring stack up (attached). Builds on first run.
up *ARGS:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml up {{ARGS}}

# Bring stack up detached.
up-d *ARGS:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml up -d {{ARGS}}

# Stop and remove containers + network. Volumes preserved.
down:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml down

# Rebuild images. `just rebuild backend` rebuilds one service.
build *ARGS:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml build {{ARGS}}

rebuild *ARGS:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml build --no-cache {{ARGS}}

# Tail logs (default: both services). Pass a service to filter.
logs *ARGS:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml logs -f {{ARGS}}

# Reload nginx config without restarting the container.
nginx-reload:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml exec frontend nginx -s reload

# Compose status table.
ps:
    docker compose --project-directory {{deploy}} -f {{deploy}}/compose.yaml ps

# ─── Local dev (without Docker) ──────────────────────────────────────────────

# Run the Rust backend locally with dev-auth + CORS for Vite.
dev-backend:
    cd {{backend}} && DEV_AUTH=1 CORS_ALLOW_ORIGIN=http://localhost:5173 cargo run

# Run the Vite dev server (expects backend on :8443).
dev-frontend:
    cd {{frontend}} && bun run dev

# ─── OpenAPI contract ────────────────────────────────────────────────────────

# Regenerate openapi.json from the backend and the TS client from it.
gen-api:
    cd {{backend}} && cargo run --quiet -- --emit-openapi > {{frontend}}/openapi.json
    cd {{frontend}} && bun run gen:api

# Fail if the committed openapi.json drifts from the current Rust source.
openapi-diff:
    cd {{backend}} && cargo run --quiet -- --emit-openapi > /tmp/smgw-fresh-openapi.json
    diff {{frontend}}/openapi.json /tmp/smgw-fresh-openapi.json \
        && echo "openapi.json in sync" \
        || ( echo "drift — run \`just gen-api\`" >&2 ; exit 1 )

# ─── Checks ──────────────────────────────────────────────────────────────────

# Run both side checks (cargo check + bun typecheck).
check:
    cd {{backend}} && cargo check
    cd {{frontend}} && bun run typecheck

# Run both test suites.
test:
    cd {{backend}} && cargo test
    cd {{frontend}} && bun run typecheck  # placeholder — frontend tests TBD

# Format + lint (best-effort).
fmt:
    cd {{backend}} && cargo fmt
    cd {{frontend}} && bun x prettier --write 'src/**/*.{ts,tsx,css}' 2>/dev/null || true
