name: Release

on:
  push:
    tags:
      - 'v*'

permissions:
  packages: write
  contents: write

jobs:
  build-and-release:
    name: Build and Release
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            target: x86_64-unknown-linux-gnu
            artifact_name: PROJECT_NAME-linux-x86_64
            binary_extension: ""
          - os: ubuntu-latest
            target: aarch64-unknown-linux-gnu
            artifact_name: PROJECT_NAME-linux-aarch64
            binary_extension: ""
          - os: macos-latest
            target: x86_64-apple-darwin
            artifact_name: PROJECT_NAME-macos-x86_64
            binary_extension: ""
          - os: macos-latest
            target: aarch64-apple-darwin
            artifact_name: PROJECT_NAME-macos-aarch64
            binary_extension: ""
          - os: windows-latest
            target: x86_64-pc-windows-msvc
            artifact_name: PROJECT_NAME-windows-x86_64
            binary_extension: ".exe"

    steps:
      - name: Checkout
        uses: actions/checkout@v4

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

      - name: Install cross-compilation tools (Linux ARM64)
        if: matrix.target == 'aarch64-unknown-linux-gnu'
        run: |
          sudo apt-get update
          sudo apt-get install -y gcc-aarch64-linux-gnu

      - name: Build
        shell: bash
        run: |
          if [ "${{ matrix.target }}" == "aarch64-unknown-linux-gnu" ]; then
            export CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
          fi
          
          cargo build --release --target ${{ matrix.target }}
          
          BIN_DIR="target/${{ matrix.target }}/release"
          cp "$BIN_DIR/PROJECT_NAME${{ matrix.binary_extension }}" "${{ matrix.artifact_name }}${{ matrix.binary_extension }}"

      - name: Upload Artifact
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.artifact_name }}
          path: ${{ matrix.artifact_name }}${{ matrix.binary_extension }}

  publish-cargo:
    name: Publish to Cargo
    needs: build-and-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Install Rust
        uses: dtolnay/rust-toolchain@stable
      - name: Publish
        env:
          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
        run: cargo publish --token $CARGO_REGISTRY_TOKEN --no-verify --allow-dirty || echo "Already published"

  publish-npm:
    name: Publish to NPM
    needs: build-and-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'
      - name: Publish
        env:
          NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npm publish --access public || echo "Already published"

  publish-docker:
    name: Publish to Docker Hub
    needs: build-and-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Log in to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Build and Push Docker Image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          push: true
          tags: |
            ${{ secrets.DOCKER_USERNAME }}/PROJECT_NAME-cli:${{ github.ref_name }}
            ${{ secrets.DOCKER_USERNAME }}/PROJECT_NAME-cli:latest

  publish-gpr:
    name: Publish to GitHub Packages (NPM)
    needs: build-and-release
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Setup Node
        uses: actions/setup-node@v4
        with:
          node-version: "20"
          registry-url: "https://npm.pkg.github.com"
          scope: "@ibidathoillah"
      - name: Publish to GPR
        env:
          NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          sed -i 's|https://registry.npmjs.org|https://npm.pkg.github.com|g' package.json || true
          npm publish || echo "Already published to GPR"

  publish-ghcr:
    name: Publish to GHCR
    needs: build-and-release
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and Push to GHCR
        uses: docker/build-push-action@v5
        with:
          context: .
          file: ./Dockerfile
          push: true
          tags: |
            ghcr.io/${{ github.repository }}:${{ github.ref_name }}
            ghcr.io/${{ github.repository }}:latest

  github-release:
    name: GitHub Release
    needs: build-and-release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Download Artifacts
        uses: actions/download-artifact@v4
        with:
          merge-multiple: true

      - name: Create Release
        uses: softprops/action-gh-release@v2
        with:
          files: |
            PROJECT_NAME-linux-x86_64
            PROJECT_NAME-linux-aarch64
            PROJECT_NAME-macos-x86_64
            PROJECT_NAME-macos-aarch64
            PROJECT_NAME-windows-x86_64.exe
          body_path: RELEASE_NOTES.md
          fail_on_unmatched_files: false
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
