name: Release

on:
  release:
    types: [created]

env:
  CARGO_TERM_COLOR: always
  # All features EXCEPT napi (requires Node.js N-API at link time) and wasm (requires wasm target)
  SDK_FEATURES: "full,json-schema,test-utils,keypair-serialization,websocket"

jobs:
  validate:
    name: Validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          components: clippy, rustfmt
      - uses: Swatinem/rust-cache@v2
      - run: cargo fmt --check
      - run: cargo clippy --features $SDK_FEATURES -- -D warnings
        env:
          RUSTFLAGS: "-Dwarnings"
      - run: cargo test --features $SDK_FEATURES
        env:
          RUSTFLAGS: "-Dwarnings"
      - run: cargo doc --no-deps --features $SDK_FEATURES
        env:
          RUSTDOCFLAGS: -D warnings

  publish-crates:
    name: Publish to crates.io
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
      - uses: Swatinem/rust-cache@v2
      - run: cargo publish --token ${{ secrets.CARGO_REGISTRY_TOKEN }} --allow-dirty

  # Build native .node addon for each platform
  build-native:
    name: Build native (${{ matrix.platform }})
    needs: validate
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        include:
          - os: macos-latest
            target: aarch64-apple-darwin
            platform: lastid-sdk-darwin-arm64
            lib: liblastid_sdk.dylib
          - os: macos-latest
            target: x86_64-apple-darwin
            platform: lastid-sdk-darwin-x64
            lib: liblastid_sdk.dylib
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            platform: lastid-sdk-linux-x64-gnu
            lib: liblastid_sdk.so
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            platform: lastid-sdk-linux-arm64-gnu
            lib: liblastid_sdk.so
            cross: true
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            platform: lastid-sdk-win32-x64-msvc
            lib: lastid_sdk.dll
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: ${{ matrix.target }}
      - uses: Swatinem/rust-cache@v2
        with:
          key: ${{ matrix.target }}

      # Cross-compilation toolchain for linux-arm64
      - name: Install cross-compilation tools
        if: matrix.cross
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
          # Add linker to existing section using sed (avoid duplicate TOML table headers)
          sed -i '/^\[target\.aarch64-unknown-linux-gnu\]/a linker = "aarch64-linux-gnu-gcc"' .cargo/config.toml

      - name: Ensure target is installed
        run: rustup target add ${{ matrix.target }}

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

      # Copy the shared lib as a .node file (this IS the napi addon)
      - name: Package platform addon (Unix)
        if: runner.os != 'Windows'
        run: |
          mkdir -p npm/platforms/${{ matrix.platform }}
          cp target/${{ matrix.target }}/release/${{ matrix.lib }} npm/platforms/${{ matrix.platform }}/lastid_sdk.node
          # Generate platform package.json
          node -e "
            const pkg = {
              name: '@lastid/${{ matrix.platform }}',
              version: '${{ github.event.release.tag_name }}'.replace(/^v/, ''),
              description: 'LastID SDK native binding for ${{ matrix.platform }}',
              license: 'MIT OR Apache-2.0',
              repository: { type: 'git', url: 'https://github.com/GetTrustedApp/lastid-rust-sdk' },
              os: ['${{ matrix.platform }}'.split('-')[2] === 'darwin' ? 'darwin' : '${{ matrix.platform }}'.split('-')[2] === 'win32' ? 'win32' : 'linux'],
              cpu: ['${{ matrix.platform }}'.split('-')[3]],
              main: 'lastid_sdk.node',
              files: ['lastid_sdk.node']
            };
            // Fix os/cpu from the platform name
            const parts = '${{ matrix.platform }}'.replace('lastid-sdk-', '').split('-');
            if (parts[0] === 'darwin') { pkg.os = ['darwin']; pkg.cpu = [parts[1]]; }
            else if (parts[0] === 'linux') { pkg.os = ['linux']; pkg.cpu = [parts[1]]; }
            else if (parts[0] === 'win32') { pkg.os = ['win32']; pkg.cpu = [parts[1]]; }
            require('fs').writeFileSync('npm/platforms/${{ matrix.platform }}/package.json', JSON.stringify(pkg, null, 2) + '\n');
          "

      - name: Package platform addon (Windows)
        if: runner.os == 'Windows'
        shell: bash
        run: |
          mkdir -p npm/platforms/${{ matrix.platform }}
          cp target/${{ matrix.target }}/release/${{ matrix.lib }} npm/platforms/${{ matrix.platform }}/lastid_sdk.node
          node -e "
            const pkg = {
              name: '@lastid/${{ matrix.platform }}',
              version: '${{ github.event.release.tag_name }}'.replace(/^v/, ''),
              description: 'LastID SDK native binding for ${{ matrix.platform }}',
              license: 'MIT OR Apache-2.0',
              repository: { type: 'git', url: 'https://github.com/GetTrustedApp/lastid-rust-sdk' },
              os: ['win32'],
              cpu: ['x64'],
              main: 'lastid_sdk.node',
              files: ['lastid_sdk.node']
            };
            require('fs').writeFileSync('npm/platforms/${{ matrix.platform }}/package.json', JSON.stringify(pkg, null, 2) + '\n');
          "

      - name: Upload platform artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.platform }}
          path: npm/platforms/${{ matrix.platform }}/

  # Build WASM for browser target
  build-wasm:
    name: Build WASM
    needs: validate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: dtolnay/rust-toolchain@stable
        with:
          targets: wasm32-unknown-unknown
      - uses: Swatinem/rust-cache@v2
      - uses: taiki-e/install-action@wasm-pack

      - name: Build WASM (web)
        run: wasm-pack build --release --scope lastid --target web --no-default-features --features wasm

      - name: Upload WASM artifact
        uses: actions/upload-artifact@v4
        with:
          name: wasm-web
          path: |
            pkg/lastid_sdk_bg.wasm
            pkg/lastid_sdk.js
            pkg/lastid_sdk.d.ts

  # Publish all npm packages
  publish-npm:
    name: Publish to npm
    needs: [build-native, build-wasm]
    runs-on: ubuntu-latest
    permissions:
      id-token: write
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          registry-url: https://registry.npmjs.org

      # Download all platform artifacts
      - uses: actions/download-artifact@v4
        with:
          name: lastid-sdk-darwin-arm64
          path: npm/platforms/lastid-sdk-darwin-arm64/
      - uses: actions/download-artifact@v4
        with:
          name: lastid-sdk-darwin-x64
          path: npm/platforms/lastid-sdk-darwin-x64/
      - uses: actions/download-artifact@v4
        with:
          name: lastid-sdk-linux-x64-gnu
          path: npm/platforms/lastid-sdk-linux-x64-gnu/
      - uses: actions/download-artifact@v4
        with:
          name: lastid-sdk-linux-arm64-gnu
          path: npm/platforms/lastid-sdk-linux-arm64-gnu/
      - uses: actions/download-artifact@v4
        with:
          name: lastid-sdk-win32-x64-msvc
          path: npm/platforms/lastid-sdk-win32-x64-msvc/

      # Download WASM
      - uses: actions/download-artifact@v4
        with:
          name: wasm-web
          path: npm/wasm/

      # Set version from release tag
      - name: Set version
        run: |
          VERSION="${{ github.event.release.tag_name }}"
          VERSION="${VERSION#v}"
          echo "VERSION=$VERSION" >> $GITHUB_ENV
          # Update main package version
          cd npm
          node -e "const p=require('./package.json'); p.version='$VERSION'; Object.keys(p.optionalDependencies||{}).forEach(k => p.optionalDependencies[k]='$VERSION'); require('fs').writeFileSync('package.json', JSON.stringify(p,null,2)+'\n')"

      # Publish each platform package first
      - name: Publish platform packages
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: |
          for dir in npm/platforms/lastid-sdk-*/; do
            pkg=$(basename "$dir")
            echo "Publishing @lastid/$pkg@$VERSION..."
            cd "$dir"
            # Update version in platform package.json
            node -e "const p=require('./package.json'); p.version='${{ env.VERSION }}'; require('fs').writeFileSync('package.json', JSON.stringify(p,null,2)+'\n')"
            npm publish --access public --provenance || echo "  (already published or failed — continuing)"
            cd -
          done

      # Publish main package last (depends on platform packages)
      - name: Publish main package
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: |
          cd npm
          echo "Publishing @lastid/lastid-sdk@$VERSION..."
          npm publish --access public --provenance

      # Verify installation works
      - name: Verify install
        run: |
          mkdir /tmp/verify && cd /tmp/verify
          npm init -y
          npm install @lastid/lastid-sdk@${{ env.VERSION }}
          node -e "const sdk = require('@lastid/lastid-sdk'); console.log('SDK version:', sdk.NapiClient.version())"

  # Upload release assets (binaries for direct download)
  upload-release-assets:
    name: Upload Release Assets
    needs: [build-native, build-wasm]
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/download-artifact@v4
        with:
          path: artifacts

      - name: Package artifacts
        run: |
          cd artifacts
          for dir in lastid-sdk-*/; do
            name=$(basename "$dir")
            tar -czvf "${name}.tar.gz" -C "$dir" .
            sha256sum "${name}.tar.gz" > "${name}.tar.gz.sha256"
          done
          if [ -d "wasm-web" ]; then
            tar -czvf "lastid-sdk-wasm-web.tar.gz" -C wasm-web .
            sha256sum "lastid-sdk-wasm-web.tar.gz" > "lastid-sdk-wasm-web.tar.gz.sha256"
          fi

      - name: Upload to release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            artifacts/*.tar.gz
            artifacts/*.sha256
