# packages/sdk/python — Python SDK tasks.
#
# The underlying tooling is `uv` + `maturin`. Callers should go through these
# recipes so the commands are discoverable and consistent.

import "../../../justfiles/common.just"

# `source_directory()` (not `justfile_directory()`) because this file is
# imported as a `mod` from `packages/sdk/justfile` via `justfile` (root).
# `justfile_directory()` always resolves to the *root* justfile's directory
# regardless of module depth, which would point `_pkg` / `_spec` / `_generated`
# at the repo root instead of `packages/sdk/python/`.
_pkg := source_directory()
_spec := source_directory() / ".." / ".." / "api-spec" / "openapi.json"
_generated := source_directory() / "python" / "openapp_sdk" / "models" / "_generated.py"

_:
    @just --list

# Install/refresh the dev virtualenv at `.venv` using `uv`.
_venv:
    cd {{ _pkg }} && uv sync --all-extras

# Fast iteration: `maturin develop` builds the bridge in-place (debug mode).
build-develop: _venv
    cd {{ _pkg }} && uv run maturin develop --features pyo3/extension-module

# Release wheel for the local platform (CI uses `maturin-action` to cross-build).
wheel: _venv
    cd {{ _pkg }} && uv run maturin build --release --strip

# sdist for PyPI (includes the Rust source so manual builds are possible).
sdist: _venv
    cd {{ _pkg }} && uv run maturin sdist

# Run the full test suite (unit + integration; integration tests auto-skip without
# `OPENAPP_SDK_TEST_API_KEY`).
test: _venv
    cd {{ _pkg }} && uv run pytest -v

# Run just the unit suite — fast, no backend needed.
test-unit: _venv
    cd {{ _pkg }} && uv run pytest -v tests/unit

# Consumer contract tests (Pact; no live backend).
test-contract: _venv
    cd {{ _pkg }} && uv run pytest -v tests/contract

# Shared Gherkin scenarios under `packages/sdk/features` (skip `@wip` placeholders).
behave: _venv
    cd {{ _pkg }} && uv run behave ../features --tags=-wip

# Behave with JUnit + Allure raw results (same layout as CI `gherkin-behave`).
behave-reports: _venv
    #!/usr/bin/env bash
    set -euo pipefail
    rep="{{ _pkg }}/.tmp/sdk-reports"
    mkdir -p "$rep/behave-junit" "$rep/allure-behave-results"
    cd "{{ _pkg }}"
    uv run behave ../features --tags=-wip --no-color \
      -f allure_behave.formatter:AllureFormatter -o "$rep/allure-behave-results" \
      -f plain --junit --junit-directory="$rep/behave-junit"

# Unit tests with JUnit XML + Allure raw results under `.tmp/sdk-reports/` (gitignored).
test-reports: _venv
    #!/usr/bin/env bash
    set -euo pipefail
    rep="{{ _pkg }}/.tmp/sdk-reports"
    mkdir -p "$rep"
    cd "{{ _pkg }}"
    uv run pytest -v tests/unit \
      --junitxml="$rep/pytest-junit.xml" \
      --alluredir="$rep/allure-results"

# Generate HTML and open Allure (requires `allure` on PATH; see packages/sdk/docs/REPORTING.md).
report-allure-open: test-reports
    #!/usr/bin/env bash
    set -euo pipefail
    rep="{{ _pkg }}/.tmp/sdk-reports"
    if ! command -v allure >/dev/null 2>&1; then
      echo "allure: command not found. Install Allure commandline:" >&2
      echo "  https://docs.qameta.io/allure/#_installing_a_commandline" >&2
      exit 1
    fi
    allure generate "$rep/allure-results" -o "$rep/allure-report" --clean
    allure open "$rep/allure-report"

# Ruff + mypy.
lint: _venv
    cd {{ _pkg }} && uv run ruff check .
    cd {{ _pkg }} && uv run ruff format --check .
    cd {{ _pkg }} && uv run python -m mypy

lint-fix: _venv
    cd {{ _pkg }} && uv run ruff format .
    cd {{ _pkg }} && uv run ruff check --fix .

# Regenerate the committed Pydantic models from the OpenAPI spec.
openapi-gen: _venv
    #!/usr/bin/env bash
    set -euo pipefail
    cd "{{ _pkg }}"
    tmp="$(mktemp)"
    trap 'rm -f "$tmp"' EXIT
    uv run python -m datamodel_code_generator \
        --input "{{ _spec }}" \
        --input-file-type openapi \
        --output "$tmp" \
        --output-model-type pydantic_v2.BaseModel \
        --target-python-version 3.10 \
        --use-standard-collections \
        --use-union-operator \
        --use-annotated \
        --disable-timestamp \
        --collapse-root-models \
        --field-constraints \
        --enum-field-as-literal one \
        --use-schema-description \
        --formatters ruff-format ruff-check
    # Drop the generator's own `# generated by datamodel-codegen: ... filename: ...`
    # banner (first line) because it embeds the host-specific absolute path of
    # the spec file and makes the check non-reproducible across machines.
    {
        printf '# @generated by `just sdk::python::openapi-gen` — DO NOT EDIT.\n'
        printf '# Source: packages/api-spec/openapi.json\n\n'
        tail -n +2 "$tmp"
    } > "{{ _generated }}"

# README "Prebuilt wheels" bullets must match openapp-sdk-release.yml (CI guard).
readme-wheel-check: _venv
    cd {{ _pkg }} && uv run python scripts/check_wheel_readme_drift.py

# Drift check for the committed Pydantic models.
openapi-check: _venv
    #!/usr/bin/env bash
    set -euo pipefail
    cd "{{ _pkg }}"
    tmp="$(mktemp)"
    trap 'rm -f "$tmp"' EXIT
    uv run python -m datamodel_code_generator \
        --input "{{ _spec }}" \
        --input-file-type openapi \
        --output "$tmp" \
        --output-model-type pydantic_v2.BaseModel \
        --target-python-version 3.10 \
        --use-standard-collections \
        --use-union-operator \
        --use-annotated \
        --disable-timestamp \
        --collapse-root-models \
        --field-constraints \
        --enum-field-as-literal one \
        --use-schema-description \
        --formatters ruff-format ruff-check
    expected="$(mktemp)"
    trap 'rm -f "$tmp" "$expected"' EXIT
    {
        printf '# @generated by `just sdk::python::openapi-gen` — DO NOT EDIT.\n'
        printf '# Source: packages/api-spec/openapi.json\n\n'
        tail -n +2 "$tmp"
    } > "$expected"
    if ! diff -u "{{ _generated }}" "$expected" >/dev/null; then
        echo "openapp_sdk/models/_generated.py is stale vs packages/api-spec/openapi.json." >&2
        echo "Run: just sdk::python::openapi-gen" >&2
        exit 1
    fi
    echo "openapp_sdk/models/_generated.py is up to date."

# Composite recipe used by `scripts/pre-commit-subproject-wrapper.sh packages/sdk/python`.
pre-commit: lint openapi-check readme-wheel-check test-unit
