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

backend := "backend"
db_url := "postgresql+asyncpg://fintracker:fintracker@localhost:54329/fintracker"

default:
    @just --list

# --- python ---

# install backend deps (uv)
sync:
    cd {{backend}} && uv sync

# run API with reload against the local dev DB
api:
    cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker serve --reload

# API + Flutter web build from one origin (run `just build-web` first)
web:
    cd {{backend}} && DATABASE_URL={{db_url}} WEB_DIR=../app/build/web uv run fintracker serve --port 8000

# --- flutter ---

build-web: app-web-assets
    cd app && flutter pub get && flutter build web --release

# fetch sqlite3.wasm + compile drift_worker.js into app/web/ (offline cache, drift/wasm+OPFS —
# see docs/ai/offline-cache.md). Re-run whenever the drift/sqlite3 package versions change;
# both files are committed, so this is not needed on every build.
app-web-assets:
    cd app && flutter pub get
    v=$(cd app && flutter pub deps --json | jq -r '.packages[] | select(.name=="sqlite3") | .version') && \
        curl -fL -o app/web/sqlite3.wasm "https://github.com/simolus3/sqlite3.dart/releases/download/sqlite3-$v/sqlite3.wasm"
    d=$(jq -r '.packages[] | select(.name=="drift") | .rootUri' app/.dart_tool/package_config.json | sed 's#^file://##') && \
        cd app && dart compile js -O2 --packages=.dart_tool/package_config.json -o web/drift_worker.js "$d/web/drift_worker.dart" && \
        rm -f web/drift_worker.js.deps web/drift_worker.js.map

app-check:
    cd app && flutter pub get && flutter analyze && flutter test

# one-off source sync against the local dev DB (zenmoney | cbr)
pull SOURCE:
    cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker sync {{SOURCE}}

# run the sync worker against the local dev DB
worker:
    cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker worker

lint:
    cd {{backend}} && uv run ruff check . && uv run ruff format --check .

fmt:
    cd {{backend}} && uv run ruff format . && uv run ruff check --fix .

typecheck:
    cd {{backend}} && uv run pyright

test *ARGS:
    cd {{backend}} && uv run pytest {{ARGS}}

check: lint typecheck test openapi-check app-check

# --- database (local dev cluster in ./.pgdata, port 54329) ---

db-init:
    test -d .pgdata || initdb -D .pgdata -U postgres --auth=trust --no-locale --encoding=UTF8 >/dev/null
    grep -q "unix_socket_directories = '$PWD/.pgdata'" .pgdata/postgresql.conf || \
        printf "\nport = 54329\nunix_socket_directories = '%s/.pgdata'\nlisten_addresses = 'localhost'\n" "$PWD" >> .pgdata/postgresql.conf

db-start: db-init
    pg_ctl -D .pgdata status >/dev/null 2>&1 || pg_ctl -D .pgdata -l .pgdata/log start -w
    psql -h localhost -p 54329 -U postgres -tc "SELECT 1 FROM pg_roles WHERE rolname='fintracker'" | grep -q 1 || \
        psql -h localhost -p 54329 -U postgres -c "CREATE ROLE fintracker LOGIN PASSWORD 'fintracker' CREATEDB"
    psql -h localhost -p 54329 -U postgres -tc "SELECT 1 FROM pg_database WHERE datname='fintracker'" | grep -q 1 || \
        psql -h localhost -p 54329 -U postgres -c "CREATE DATABASE fintracker OWNER fintracker"

db-stop:
    pg_ctl -D .pgdata status >/dev/null 2>&1 && pg_ctl -D .pgdata stop -m fast || true

db-psql:
    psql -h localhost -p 54329 -U fintracker fintracker

migrate *ARGS="upgrade head":
    cd {{backend}} && DATABASE_URL={{db_url}} uv run alembic {{ARGS}}

# create a new migration from model changes
revision MSG:
    cd {{backend}} && DATABASE_URL={{db_url}} uv run alembic revision --autogenerate -m "{{MSG}}"

create-user EMAIL:
    cd {{backend}} && DATABASE_URL={{db_url}} uv run fintracker create-user {{EMAIL}}

# --- openapi / dart client ---

# export openapi/openapi.json from the FastAPI app
openapi:
    cd {{backend}} && uv run fintracker openapi ../openapi/openapi.json

# fail if the committed spec drifted from the code
openapi-check:
    cd {{backend}} && uv run fintracker openapi /tmp/fin-tracker-openapi.json
    diff -q openapi/openapi.json /tmp/fin-tracker-openapi.json

# regenerate app/packages/api_client from openapi/openapi.json
gen-client: openapi
    rm -rf app/packages/api_client/lib app/packages/api_client/doc
    openapi-generator-cli generate -g dart-dio -i openapi/openapi.json -o app/packages/api_client \
        -c app/packages/api_client/openapi-config.yaml
    # the generator pins an old language version; null-aware elements need >= 3.8
    sed -i "s/sdk: '>=3.5.0 <4.0.0'/sdk: '>=3.8.0 <4.0.0'/" app/packages/api_client/pubspec.yaml
    cd app/packages/api_client && dart pub get && dart run build_runner build --delete-conflicting-outputs

# --- deploy (VPS) ---

# build without the host proxy vars: podman/buildah bakes HTTP_PROXY into the image otherwise
up:
    env -u http_proxy -u https_proxy -u HTTP_PROXY -u HTTPS_PROXY -u ALL_PROXY -u all_proxy \
        docker compose up -d --build

logs *ARGS:
    docker compose logs -f {{ARGS}}
