name: CI Rust

on:
  workflow_call:

permissions:
  contents: read

jobs:
  audit:
    name: Dependency audit (cargo + pip)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install cargo-audit and run cargo audit
        run: |
          cargo install cargo-audit
          cargo audit

      - name: Install cargo-deny and run cargo deny check
        run: |
          cargo install cargo-deny --locked
          cargo deny check

      - name: Set up Python 3.12
        uses: actions/setup-python@v6
        with:
          python-version: "3.12"

      - name: Install uv
        run: pip install uv

      - name: Install pip-audit via uv and run pip-audit
        run: uv run --with pip-audit pip-audit --skip-editable

      - name: Verify uv.lock is up-to-date
        run: uv lock --check

  rust:
    name: Rust (fmt + clippy)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@v1
        with:
          toolchain: stable
          components: rustfmt, clippy
      - run: cargo fmt --all -- --check
      - run: cargo clippy --release -- -D warnings
      - name: Verify benchmarks compile (ferro_ta_core)
        run: cargo bench -p ferro_ta_core --no-run

  rust-core:
    name: Rust core library (ferro_ta_core)
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@v1
        with:
          toolchain: stable
      - name: Build core crate
        run: cargo build -p ferro_ta_core
      - name: Test core crate
        run: cargo test -p ferro_ta_core

  rust-coverage:
    name: Rust coverage (tarpaulin, optional)
    runs-on: ubuntu-latest
    continue-on-error: true
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@v1
        with:
          toolchain: stable
      - name: Install cargo-tarpaulin
        run: cargo install cargo-tarpaulin --locked
      - name: Collect Rust coverage (ferro_ta_core)
        run: cargo tarpaulin -p ferro_ta_core --out Xml --output-dir coverage/
      - name: Upload Rust coverage artifact
        uses: actions/upload-artifact@v7
        with:
          name: rust-coverage
          path: coverage/
          if-no-files-found: ignore

  fuzz:
    name: Fuzz targets (short CI run, optional)
    runs-on: ubuntu-latest
    continue-on-error: true
    steps:
      - uses: actions/checkout@v6
      - uses: dtolnay/rust-toolchain@v1
        with:
          toolchain: nightly
      - name: Install cargo-fuzz
        run: cargo install cargo-fuzz --locked
      - name: Run fuzz_sma (10000 iterations)
        working-directory: fuzz
        run: cargo fuzz run fuzz_sma -- -runs=10000 -max_len=512
      - name: Run fuzz_rsi (10000 iterations)
        working-directory: fuzz
        run: cargo fuzz run fuzz_rsi -- -runs=10000 -max_len=512
      - name: Upload fuzz artifacts on crash
        uses: actions/upload-artifact@v7
        if: always()
        with:
          name: fuzz-artifacts
          path: fuzz/artifacts/
          if-no-files-found: ignore
