name: CI

on:
  push:
    branches: [main]
    tags: ['v*']
  pull_request:

env:
  CARGO_TERM_COLOR: always
  RUSTFLAGS: "-D warnings"

jobs:
  lint:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: cargo fmt
        run: cargo +nightly fmt --all --check

      - name: cargo clippy
        run: cargo +nightly clippy --all-targets --all-features --message-format=short

      - name: cargo doc (no deps)
        run: cargo +nightly doc --no-deps --document-private-items
        env:
          RUSTDOCFLAGS: "-D warnings"

      - name: cargo audit
        run: cargo audit

  test:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: cargo test (core + CAPI, including ignored)
        run: cargo test -p libsoliton -p libsoliton_capi -- --include-ignored

  test-python:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: Set up Python venv
        run: |
          python3 -m venv .venv
          . .venv/bin/activate
          pip install maturin pytest

      - name: Build and install soliton-python
        working-directory: soliton_py
        run: |
          . ../.venv/bin/activate
          maturin develop

      - name: Run pytest
        working-directory: soliton_py
        run: |
          . ../.venv/bin/activate
          pytest tests/ -v

  test-zig:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: Build libsoliton_capi (release)
        run: cargo build --release -p libsoliton_capi

      - name: Run Zig tests
        working-directory: soliton_zig
        run: zig build test
        env:
          LD_LIBRARY_PATH: ${{ github.workspace }}/target/release

  test-wasm:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: Build WASM package
        working-directory: soliton_wasm
        run: wasm-pack build --target bundler

      - name: Install dependencies
        working-directory: soliton_wasm
        run: bun install

      - name: Run Node tests
        working-directory: soliton_wasm
        run: bunx vitest run

      - name: Install Playwright
        working-directory: soliton_wasm
        run: bunx playwright install chromium

      - name: Run browser tests
        working-directory: soliton_wasm
        run: bunx vitest run --config vitest.browser.config.js

  miri:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: MIRI test suite
        run: |
          MIRIFLAGS="-Zmiri-disable-isolation" cargo +nightly miri nextest run \
            -p libsoliton -p libsoliton_capi --profile miri -j$(nproc)
        env:
          RUSTFLAGS: ""

  fuzz-regression:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2
        with:
          lfs: true

      - name: Generate seed corpus
        run: cd soliton/fuzz && cargo +nightly run --bin gen_corpus --quiet

      - name: Corpus regression (all targets)
        run: ./ci_regression.sh

  build:
    runs-on: lo-runner
    steps:
      - uses: actions/checkout@v6.0.2

      - name: cargo build --release
        run: cargo build --release -p libsoliton -p libsoliton_capi

  publish:
    needs: [lint, test, test-python, test-zig, test-wasm, miri, fuzz-regression, build]
    runs-on: lo-runner
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
      - uses: actions/checkout@v6.0.2

      - name: Publish libsoliton
        run: cargo publish -p libsoliton
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}

      - name: Wait for crates.io indexing
        run: sleep 30

      - name: Publish libsoliton_capi
        run: cargo publish -p libsoliton_capi
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CRATES_IO_TOKEN }}

  publish-python:
    needs: [lint, test, test-python, test-wasm, miri, fuzz-regression, build]
    runs-on: lo-runner
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
      - uses: actions/checkout@v6.0.2

      - name: Set up Python venv
        run: |
          python3 -m venv .venv
          . .venv/bin/activate
          pip install maturin

      - name: Build wheel
        working-directory: soliton_py
        run: |
          . ../.venv/bin/activate
          maturin build --release

      - name: Publish to PyPI
        working-directory: soliton_py
        run: |
          . ../.venv/bin/activate
          maturin publish
        env:
          MATURIN_PYPI_TOKEN: ${{ secrets.PYPI_TOKEN }}

  publish-wasm:
    needs: [lint, test, test-wasm, miri, fuzz-regression, build]
    runs-on: lo-runner
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
      - uses: actions/checkout@v6.0.2

      - name: Build WASM package
        working-directory: soliton_wasm
        run: wasm-pack build --target bundler

      - name: Publish to Forgejo npm registry
        working-directory: soliton_wasm/pkg
        run: |
          echo '//git.lo.sh/api/packages/lo/npm/:_authToken=${{ secrets.BUN_TOKEN }}' > .npmrc
          bun publish --access public --registry ${{ github.server_url }}/api/packages/lo/npm/
