name: Publish @fiscal-rs/node to npm

# Runs on every push to master (same trigger as release-plz).
# Compares the version in Cargo.toml with the latest npm version.
# If they differ, builds all platforms and publishes to npm.
on:
  push:
    branches:
      - master
    paths:
      - 'crates/fiscal-napi/**'
      - 'crates/fiscal-core/**'
      - 'crates/fiscal-crypto/**'
      - 'crates/fiscal-sefaz/**'

permissions:
  contents: read

env:
  MACOSX_DEPLOYMENT_TARGET: '10.13'

jobs:
  check-version:
    name: Check if npm publish needed
    runs-on: ubuntu-latest
    outputs:
      should_publish: ${{ steps.check.outputs.should_publish }}
      version: ${{ steps.check.outputs.version }}
    steps:
      - uses: actions/checkout@v6

      - name: Determine version from dependency crates
        id: check
        run: |
          # npm version follows the highest version among fiscal-rs crates
          CORE=$(grep '^version' crates/fiscal-core/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          SEFAZ=$(grep '^version' crates/fiscal-sefaz/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          CRYPTO=$(grep '^version' crates/fiscal-crypto/Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')
          FACADE=$(grep '^version' Cargo.toml | head -1 | sed 's/.*"\(.*\)".*/\1/')

          echo "fiscal-core: $CORE"
          echo "fiscal-sefaz: $SEFAZ"
          echo "fiscal-crypto: $CRYPTO"
          echo "fiscal (facade): $FACADE"

          # Pick the highest version (sort -V = version sort)
          VERSION=$(printf '%s\n' "$CORE" "$SEFAZ" "$CRYPTO" "$FACADE" | sort -V | tail -1)
          echo "Resolved npm version: $VERSION"

          # Check npm registry for latest published version
          NPM_VERSION=$(npm view @fiscal-rs/node version 2>/dev/null || echo "0.0.0")
          echo "Current npm version: $NPM_VERSION"

          if [ "$VERSION" != "$NPM_VERSION" ]; then
            echo "Version changed: $NPM_VERSION -> $VERSION"
            echo "should_publish=true" >> $GITHUB_OUTPUT
          else
            echo "Version unchanged, skipping publish"
            echo "should_publish=false" >> $GITHUB_OUTPUT
          fi
          echo "version=$VERSION" >> $GITHUB_OUTPUT

  build:
    name: Build ${{ matrix.target }}
    needs: check-version
    if: needs.check-version.outputs.should_publish == 'true'
    runs-on: ${{ matrix.os }}
    defaults:
      run:
        working-directory: crates/fiscal-napi
    strategy:
      fail-fast: false
      matrix:
        include:
          - target: x86_64-unknown-linux-gnu
            os: ubuntu-latest
          - target: aarch64-unknown-linux-gnu
            os: ubuntu-latest
          - target: x86_64-unknown-linux-musl
            os: ubuntu-latest
          - target: aarch64-unknown-linux-musl
            os: ubuntu-latest
          - target: x86_64-apple-darwin
            os: macos-13
          - target: aarch64-apple-darwin
            os: macos-14
          - target: x86_64-pc-windows-msvc
            os: windows-latest
          - target: aarch64-pc-windows-msvc
            os: windows-latest

    steps:
      - uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22

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

      - name: Install dependencies
        run: npm ci

      - name: Install cross-compilation tools
        if: contains(matrix.target, 'aarch64-unknown-linux') || matrix.target == 'x86_64-unknown-linux-musl'
        uses: napi-rs/setup-cross-toolchain-action@v1
        with:
          target: ${{ matrix.target }}

      - name: Install OpenSSL (Linux x86_64 gnu)
        if: matrix.target == 'x86_64-unknown-linux-gnu'
        run: sudo apt-get update && sudo apt-get install -y libssl-dev pkg-config

      - name: Build native addon
        run: npx napi build --release --platform --target ${{ matrix.target }}

      - name: Upload artifact
        uses: actions/upload-artifact@v4
        with:
          name: bindings-${{ matrix.target }}
          path: crates/fiscal-napi/fiscal.*.node
          if-no-files-found: error

  publish:
    name: Publish to npm
    runs-on: ubuntu-latest
    needs: [check-version, build]
    steps:
      - uses: actions/checkout@v6

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 22
          registry-url: https://registry.npmjs.org

      - name: Install dependencies
        working-directory: crates/fiscal-napi
        run: npm ci

      - name: Sync version to package.json
        working-directory: crates/fiscal-napi
        run: npx napi version --no-git ${{ needs.check-version.outputs.version }}

      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: crates/fiscal-napi/artifacts

      - name: Move artifacts to npm dirs
        working-directory: crates/fiscal-napi
        run: npx napi artifacts --dir artifacts

      - name: List packages
        working-directory: crates/fiscal-napi
        run: |
          echo "Version: ${{ needs.check-version.outputs.version }}"
          for d in npm/*/; do
            echo "$d: $(ls "$d"fiscal.*.node 2>/dev/null | wc -l) binary"
          done

      - name: Publish platform packages
        working-directory: crates/fiscal-napi
        run: npx napi prepublish --skip-gh-release -t npm
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

      - name: Publish main package
        working-directory: crates/fiscal-napi
        run: npm publish --access public
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
