# 引数にスペースが含まれても分解されないよう位置パラメータを有効化する
# (pass-through するレシピの body では {{args}} ではなく "$@" を使う)
set positional-arguments

# デフォルトレシピ: レシピ一覧を表示
default:
    @just --list

# --- Rust (axum) ---

# 開発サーバー起動 (http://0.0.0.0:8000)
app: _target-gc-guard
    cargo run

# ビルド
build:
    cargo build --release

# テスト実行 (引数は cargo test にパススルー)
test *args: _target-gc-guard
    cargo test "$@"

# フォーマッター実行
fmt:
    cargo fmt --all

# フォーマットチェック (CI 用)
fmt-check:
    cargo fmt --all --check

# リンター実行
lint: _target-gc-guard
    cargo clippy --all-targets -- -D warnings

# 状態は target/ 内に置く (cargo clean で消えても次回 baseline を取り直すだけ)
# target/ を作り直し、フルビルド直後のサイズを baseline として記録する
target-gc:
    #!/usr/bin/env bash
    set -uo pipefail
    state="target/.target-gc"
    now=$(date +%s)
    base=$(sed -n 's/^baseline_kb=//p' "$state" 2>/dev/null | tail -1)
    echo "[target-gc] cargo clean → フルビルドで baseline を取り直します (数分かかります)"
    cargo clean
    if cargo build --all-targets; then
        kb=$(du -sk target | cut -f1)
        printf 'baseline_kb=%s\nlast_gc=%s\nlast_check=%s\n' "$kb" "$now" "$now" > "$state"
        echo "[target-gc] baseline = $((kb / 1024)) MiB を記録しました"
    else
        # 編集途中の壊れたツリーで発火した場合に、失敗ビルドの途中サイズを
        # baseline として過小記録しない (gc 時刻だけ更新して次回に回す)
        mkdir -p target
        printf 'baseline_kb=%s\nlast_gc=%s\nlast_check=%s\n' "${base:-0}" "$now" "$now" > "$state"
        echo "[target-gc] ビルド失敗のため baseline は更新していません" >&2
        exit 1
    fi

# cargo を呼ぶレシピの前段ガード。TARGET_GC=never で無効化、TARGET_GC_RATIO で倍率変更。
# CI (GitHub Actions は CI=true) では発火させない
_target-gc-guard:
    #!/usr/bin/env bash
    set -uo pipefail
    [ "${TARGET_GC:-}" = "never" ] && exit 0
    [ -n "${CI:-}" ] && exit 0
    state="target/.target-gc"
    now=$(date +%s)
    if [ ! -f "$state" ]; then
        echo "[target-gc] baseline 未確立のため target-gc を実行します"
        exec just target-gc
    fi
    baseline_kb=$(sed -n 's/^baseline_kb=//p' "$state" | tail -1)
    last_gc=$(sed -n 's/^last_gc=//p' "$state" | tail -1)
    last_check=$(sed -n 's/^last_check=//p' "$state" | tail -1)
    if [ $(( now - ${last_gc:-0} )) -gt $(( 30 * 86400 )) ]; then
        echo "[target-gc] 前回 gc から 30 日超のため target-gc を実行します"
        exec just target-gc
    fi
    # du -s target は数秒かかるので 1 日 1 回に間引く
    [ $(( now - ${last_check:-0} )) -lt 86400 ] && exit 0
    kb=$(du -sk target 2>/dev/null | cut -f1)
    sed -i "s/^last_check=.*/last_check=$now/" "$state"
    ratio=${TARGET_GC_RATIO:-5}
    if [ "${baseline_kb:-0}" -gt 0 ] && [ "${kb:-0}" -gt $(( baseline_kb * ratio )) ]; then
        echo "[target-gc] target/ が baseline の ${ratio} 倍を超えました ($((kb / 1024)) MiB)"
        exec just target-gc
    fi

# --- DB スキーマ ---
# 信頼の源は schema.sql。DSQL 方言の SQL を migrations/ に置き、schema-apply で
# 1 文ずつ適用する (適用済みは schema_migrations に記録され再実行で飛ばされる)。
# 接続先は通常のアプリと同じ env で解決する (DATABASE_URL > PG_HOST 系 > DSQL_HOST)。

# migrations/*.sql を接続先へ適用する
schema-apply *args:
    cargo run -q --bin schema-apply "$@"

# --- SeaORM entity 生成 (生成元は DSQL ではなくローカル PostgreSQL) ---

entity_dir := "src/entity"
lab_url := "postgres://postgres@127.0.0.1:5432/_dsql_lab?sslmode=disable"
# 作業台の作り方: ローカル PG に _dsql_lab を作り、schema.sql を流し込む

# 作業台 (_dsql_lab) から entity を生成し差分表示
entity-gen:
    sea-orm-cli generate entity \
        --database-url "{{lab_url}}" \
        --output-dir /tmp/entity-gen \
        --with-serde both --date-time-crate chrono --lib
    diff -ru {{entity_dir}} /tmp/entity-gen || true

# 生成した entity を反映
entity-apply:
    cp /tmp/entity-gen/*.rs {{entity_dir}}/

# --- フロントエンド (SvelteKit) ---

# フロントエンド開発サーバー (port 3000、/api は 8000 へ proxy)
front:
    cd frontend && bun run dev -- --host 0.0.0.0 --port 3000

# フロントエンドをビルド (pocket は再ビルドしないので deploy 前に必須)
front-build:
    cd frontend && bun install --frozen-lockfile && bun run build

# フロントエンドのチェック (雛形に test script が無いため svelte-check を実行)
front-check *args:
    cd frontend && bun install --frozen-lockfile && bun run check

# --- デプロイ (sandbox のみ) ---
# SPA を持つため front-build を必ず先行させる (pocket は frontend/build を再ビルドしない)。
# pocket.toml の domain は公開 repo では placeholder なので、deploy 前に実ドメインへ
# 書き戻し、終わったら placeholder に戻すこと。
#
# 例:
#   just deploy                          … sandbox へ
#   just deploy sandbox --skip-frontend  … その他 pocket フラグもそのまま渡せる
deploy stage="sandbox" *args: front-build
    #!/usr/bin/env bash
    set -euo pipefail
    shift   # $1 = stage を落として、残り (*args) だけを pocket へ渡す
    pocket deploy --stage={{stage}} -y "$@"
