name: CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

env:
  CARGO_TERM_COLOR: always
  RUST_BACKTRACE: 1

jobs:
  test:
    name: Test
    runs-on: ubuntu-latest
    strategy:
      matrix:
        rust:
          - stable
          - beta
          - nightly
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: ${{ matrix.rust }}

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Run tests
        run: cargo test --verbose

      - name: Run tests with all features
        run: cargo test --verbose --all-features

      - name: Check documentation
        run: cargo doc --no-deps --document-private-items

  cross-platform:
    name: Cross-platform
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
          - os: macos-latest
            target: x86_64-apple-darwin
          - os: windows-latest
            target: x86_64-pc-windows-msvc
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
          - os: ubuntu-latest
            target: arm-unknown-linux-gnueabihf
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          targets: ${{ matrix.target }}

      - name: Install cross-compilation tools
        if: matrix.target != 'x86_64-unknown-linux-gnu' && matrix.target != 'x86_64-apple-darwin' && matrix.target != 'x86_64-pc-windows-msvc'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu gcc-arm-linux-gnueabihf

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Build for target
        run: cargo build --target ${{ matrix.target }} --release

      - name: Test for native targets
        if: matrix.target == 'x86_64-unknown-linux-gnu' || matrix.target == 'x86_64-apple-darwin' || matrix.target == 'x86_64-pc-windows-msvc'
        run: cargo test --target ${{ matrix.target }}

  no-alloc:
    name: No-alloc verification
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Build without alloc (core functionality only)
        run: cargo build --no-default-features

      - name: Test no-alloc compatibility
        run: |
          # Create a minimal no-alloc test
          cat > no_alloc_test.rs << 'EOF'
          #![no_std]

          use clock_bigint::{U256, BigIntCore, Gas, G_BASE, MAX_LIMBS};

          fn test_no_alloc_basic() {
              let mut a = U256::from_u64(1);
              let b = U256::from_u64(2);

              // Test basic fixed-size operations work without alloc
              assert_eq!(a.limb_count(), 4);
              assert_eq!(b.limb_count(), 4);
              assert_eq!(a.limbs()[0], 1);
              assert_eq!(b.limbs()[0], 2);

              // Test gas constants are available
              let _gas: Gas = G_BASE;
              assert_eq!(MAX_LIMBS, 512);
          }
          EOF

          # Compile the test
          rustc --edition=2024 --crate-type lib --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 no_alloc_test.rs --extern clock_bigint=target/debug/libclock_bigint-*.rlib --out-dir target/debug/deps

          # Clean up
          rm no_alloc_test.rs

  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          components: rustfmt, clippy

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Check formatting
        run: cargo fmt --all -- --check

      - name: Run clippy
        run: cargo clippy --all-targets --all-features -- -W warnings -A clippy::similar-names -A clippy::many-single-char-names -A clippy::unreadable-literal

      - name: Check for security vulnerabilities
        run: |
          cargo install cargo-audit --version 0.18.0 || true
          cargo audit || echo "cargo-audit not available or no vulnerabilities found"

  msrv:
    name: Minimum Supported Rust Version
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: "1.70.0"  # Update this based on your MSRV

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Build with MSRV
        run: cargo build

      - name: Test with MSRV
        run: cargo test

  coverage:
    name: Code Coverage
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install Rust
        uses: dtolnay/rust-toolchain@master
        with:
          toolchain: stable
          components: llvm-tools-preview

      - name: Install cargo-llvm-cov
        run: cargo install cargo-llvm-cov --version 0.6.0

      - name: Cache dependencies
        uses: Swatinem/rust-cache@v2

      - name: Generate coverage report
        run: cargo llvm-cov --all-features --workspace --lcov --output-path lcov.info

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v3
        with:
          file: lcov.info
          fail_ci_if_error: false