name: Build All Packages

on:
  push:
    tags:
      - '*'
  workflow_dispatch:
    inputs:
      version:
        description: 'Version to build (leave empty for auto)'
        required: false
        type: string

jobs:
  prepare:
    runs-on: ubuntu-latest
    outputs:
      version: ${{ steps.version.outputs.version }}
      is_release: ${{ steps.version.outputs.is_release }}
    steps:
      - uses: actions/checkout@v4
      - name: Determine version
        id: version
        run: |
          if [[ "${{ github.ref }}" =~ ^refs/tags/ ]]; then
            G4F_VERSION="${{ github.ref_name }}"
            IS_RELEASE="true"
          elif [[ -n "${{ inputs.version }}" ]]; then
            G4F_VERSION="${{ inputs.version }}"
            IS_RELEASE="false"
          else
            G4F_VERSION="0.0.0-dev"
            IS_RELEASE="false"
          fi
          echo "version=${G4F_VERSION}" >> $GITHUB_OUTPUT
          echo "is_release=${IS_RELEASE}" >> $GITHUB_OUTPUT
          echo "Building version: ${G4F_VERSION}"

  # PyPI Package
  build-pypi:
    runs-on: ubuntu-latest
    needs: prepare
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.x"
      - name: Install build tools
        run: |
          python -m pip install --upgrade pip
          python -m pip install build twine
      - name: Build package
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
        run: python -m build
      - name: Verify package
        run: |
          python -m twine check dist/*
          ls -la dist/
      - name: Upload PyPI artifacts
        uses: actions/upload-artifact@v4
        with:
          name: pypi-package
          path: dist/

  # Windows Executables
  build-windows-exe:
    runs-on: windows-latest
    needs: prepare
    strategy:
      matrix:
        include:
          - architecture: x64
            runner-arch: x86_64
          # Note: ARM64 cross-compilation on Windows requires additional setup
          # Keeping architecture in matrix for future expansion
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install nuitka
          pip install -e .
      - name: Write g4f_cli.py
        shell: pwsh
        run: |
          @"
          #!/usr/bin/env python3
          """
          Entry point for g4f CLI executable builds
          """

          import g4f.debug
          g4f.debug.version_check = False
          g4f.debug.version = "${{ needs.prepare.outputs.version }}"

          if __name__ == "__main__":
              from g4f.cli import main
              main()
          "@ | Set-Content -Path g4f_cli.py -Encoding utf8
      - name: Build Windows executable with Nuitka
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
          PLATFORM: windows
          ARCHITECTURE: ${{ matrix.runner-arch }}
        shell: bash
        run: |
          chmod +x scripts/build-nuitka.sh
          ./scripts/build-nuitka.sh
      - name: Zip Windows executable folder
        shell: pwsh
        run: |
          $architecture = "${{ matrix.architecture }}"
          $version = "${{ needs.prepare.outputs.version }}"
          $exeName = "g4f-windows-${version}-${architecture}.exe"
          if (Test-Path "dist\${exeName}") {
            Compress-Archive "dist\${exeName}" "dist\g4f-windows-${version}-${architecture}.zip"
          }
      - name: Upload Windows zip archive
        uses: actions/upload-artifact@v4
        with:
          name: windows-exe-${{ matrix.architecture }}
          path: dist/g4f-windows-*.zip

  # Linux Executables
  build-linux-exe:
    runs-on: ${{ matrix.runner }}
    needs: prepare
    strategy:
      matrix:
        include:
          - architecture: x64
            runner: ubuntu-latest
            runner-arch: x86_64
          - architecture: arm64
            runner: ubuntu-24.04-arm
            runner-arch: aarch64
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install nuitka
          pip install -e .
      - name: Write g4f_cli.py
        run: |
          cat > g4f_cli.py << EOF
          #!/usr/bin/env python3
          """
          Entry point for g4f CLI executable builds
          """

          import g4f.debug
          g4f.debug.version_check = False
          g4f.debug.version = "${{ needs.prepare.outputs.version }}"

          if __name__ == "__main__":
              from g4f.cli import main
              main()
          EOF
      - name: Build Linux executable with Nuitka
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
          PLATFORM: linux
          ARCHITECTURE: ${{ matrix.runner-arch }}
        run: |
          chmod +x scripts/build-nuitka.sh
          ./scripts/build-nuitka.sh
      - name: Upload Linux executable
        uses: actions/upload-artifact@v4
        with:
          name: linux-exe-${{ matrix.architecture }}
          path: dist/g4f-linux-*

  # macOS Executables  
  build-macos-exe:
    runs-on: macos-latest
    needs: prepare
    strategy:
      matrix:
        include:
          - architecture: x64
            runner-arch: x86_64
          - architecture: arm64
            runner-arch: arm64
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt
          pip install nuitka
          pip install -e .
      - name: Write g4f_cli.py
        run: |
          cat > g4f_cli.py << EOF
          #!/usr/bin/env python3
          """
          Entry point for g4f CLI executable builds
          """

          import g4f.debug
          g4f.debug.version_check = False
          g4f.debug.version = "${{ needs.prepare.outputs.version }}"

          if __name__ == "__main__":
              from g4f.cli import main
              main()
          EOF
      - name: Build macOS executable with Nuitka
        env:
          G4F_VERSION: ${{ needs.prepare.outputs.version }}
          PLATFORM: darwin
          ARCHITECTURE: ${{ matrix.runner-arch }}
        run: |
          chmod +x scripts/build-nuitka.sh
          ./scripts/build-nuitka.sh
      - name: Upload macOS executable
        uses: actions/upload-artifact@v4
        with:
          name: macos-exe-${{ matrix.architecture }}
          path: dist/g4f-macos-*

  # Docker Images
  build-docker:
    runs-on: ubuntu-latest
    needs: prepare
    if: needs.prepare.outputs.is_release == 'true'
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      - name: Get metadata for Docker
        id: metadata
        uses: docker/metadata-action@v5
        with:
          images: |
            hlohaus789/g4f
      - name: Log in to Docker Hub
        uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      - name: Build and push armv7 image
        uses: docker/build-push-action@v5
        with:
            context: .
            file: docker/Dockerfile-armv7
            platforms: linux/arm/v7
            push: true
            tags: |
              hlohaus789/g4f:latest-armv7
              hlohaus789/g4f:${{ needs.prepare.outputs.version }}-armv7
            labels: ${{ steps.metadata.outputs.labels }}
            build-args: |
              G4F_VERSION=${{ needs.prepare.outputs.version }}
      - name: Build and push slim images
        uses: docker/build-push-action@v5
        with:
          context: .
          file: docker/Dockerfile-slim
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            hlohaus789/g4f:latest-slim
            hlohaus789/g4f:${{ needs.prepare.outputs.version }}-slim
          labels: ${{ steps.metadata.outputs.labels }}
          build-args: |
            G4F_VERSION=${{ needs.prepare.outputs.version }}
      - name: Build and push image
        uses: docker/build-push-action@v5
        with:
          context: .
          file: docker/Dockerfile
          platforms: linux/amd64
          push: true
          tags: ${{ steps.metadata.outputs.tags }}
          labels: ${{ steps.metadata.outputs.labels }}
          build-args: |
            G4F_VERSION=${{ needs.prepare.outputs.version }}

  # Debian Packages
  # build-debian:
  #   runs-on: ubuntu-latest
  #   needs: prepare
  #   strategy:
  #     matrix:
  #       architecture: [amd64, arm64, armhf]
  #   steps:
  #     - uses: actions/checkout@v4
  #     - name: Set up Python
  #       uses: actions/setup-python@v5
  #       with:
  #         python-version: "3.x"
  #     - name: Install build dependencies
  #       run: |
  #         sudo apt-get update
  #         sudo apt-get install -y dpkg-dev build-essential python3-setuptools
  #         python3 -m pip install --upgrade pip
  #         pip3 install -r requirements-min.txt
  #         pip3 install -e .
  #     - name: Build Debian package
  #       env:
  #         G4F_VERSION: ${{ needs.prepare.outputs.version }}
  #         ARCH: ${{ matrix.architecture }}
  #       run: |
  #         chmod +x scripts/build-deb.sh
  #         ./scripts/build-deb.sh
  #     - name: Upload Debian package
  #       uses: actions/upload-artifact@v4
  #       with:
  #         name: debian-${{ matrix.architecture }}
  #         path: g4f-*-${{ matrix.architecture }}.deb

  # WinGet Package Manifest
  create-winget-manifest:
    runs-on: ubuntu-latest
    needs: [prepare, build-windows-exe]
    if: needs.prepare.outputs.is_release == 'true'
    steps:
      - uses: actions/checkout@v4
      - name: Download Windows executable zip (x64)
        uses: actions/download-artifact@v4
        with:
          name: windows-exe-x64
          path: ./artifacts/x64
      - name: Calculate hash and size of ZIP
        id: hash
        run: |
          HASH_X64=$(sha256sum ./artifacts/x64/g4f-windows-*-x64.zip | cut -d' ' -f1)
          echo "hash_x64=${HASH_X64}" >> $GITHUB_OUTPUT
          SIZE_X64=$(stat -c%s ./artifacts/x64/g4f-windows-*-x64.zip)
          echo "size_x64=${SIZE_X64}" >> $GITHUB_OUTPUT
      - name: Create WinGet manifest
        run: |
          mkdir -p winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}

          # Version manifest
          cat > winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}/g4f.yaml << EOF
          PackageIdentifier: g4f
          PackageVersion: ${{ needs.prepare.outputs.version }}
          DefaultLocale: en-US
          ManifestType: version
          ManifestVersion: 1.4.0
          EOF

          # Installer manifest
          cat > winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}/g4f.installer.yaml << EOF
          PackageIdentifier: g4f
          PackageVersion: ${{ needs.prepare.outputs.version }}
          Installers:
          - Architecture: x64
            InstallerType: zip
            NestedInstallerType: portable
            NestedInstallerFiles:
            - RelativeFilePath: g4f-windows-${{ needs.prepare.outputs.version }}-x64.exe
              PortableCommandAlias: g4f
            InstallerUrl: https://github.com/xtekky/gpt4free/releases/download/${{ needs.prepare.outputs.version }}/g4f-windows-${{ needs.prepare.outputs.version }}-x64.zip
            InstallerSha256: ${{ steps.hash.outputs.hash_x64 }}
          ManifestType: installer
          ManifestVersion: 1.4.0
          EOF

          # Locale manifest
          cat > winget/manifests/g/g4f/${{ needs.prepare.outputs.version }}/g4f.locale.en-US.yaml << EOF
          PackageIdentifier: g4f
          PackageVersion: ${{ needs.prepare.outputs.version }}
          PackageLocale: en-US
          Publisher: GPT4Free
          PublisherUrl: https://github.com/xtekky/gpt4free
          PackageName: g4f
          PackageUrl: https://github.com/xtekky/gpt4free
          License: GPL-3.0
          LicenseUrl: https://github.com/xtekky/gpt4free/blob/main/LICENSE
          ShortDescription: The official gpt4free repository
          Description: Various collection of powerful language models
          Tags:
          - ai
          - gpt
          - chatgpt
          - openai
          - free
          - client
          ManifestType: defaultLocale
          ManifestVersion: 1.4.0
          EOF
      - name: Upload WinGet manifest
        uses: actions/upload-artifact@v4
        with:
          name: winget-manifest
          path: winget/

  # Release Creation
  create-release:
    runs-on: ubuntu-latest
    needs: [prepare, build-pypi, build-windows-exe, build-linux-exe, build-macos-exe, create-winget-manifest]
    if: needs.prepare.outputs.is_release == 'true'
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          path: ./artifacts
      - name: Display artifact structure
        run: |
          echo "Downloaded artifacts:"
          find ./artifacts -type f -name "*" | sort
      - name: Create Release with Assets
        uses: softprops/action-gh-release@v2
        with:
          tag_name: ${{ needs.prepare.outputs.version }}
          name: Release ${{ needs.prepare.outputs.version }}
          append_body: true
          body: |
            ## g4f ${{ needs.prepare.outputs.version }}

            ### Download Options

            **Python Package:**
            - PyPI: `pip install g4f==${{ needs.prepare.outputs.version }}`

            **Executables:**
            - Windows x64: `g4f-windows-${{ needs.prepare.outputs.version }}-x64.zip`
            - Linux x64: `g4f-linux-${{ needs.prepare.outputs.version }}-x64`
            - Linux ARM64: `g4f-linux-${{ needs.prepare.outputs.version }}-arm64`
            - macOS x64: `g4f-macos-${{ needs.prepare.outputs.version }}-x64`
            - macOS ARM64: `g4f-macos-${{ needs.prepare.outputs.version }}-arm64`

            **System Packages:**
            - WinGet: `winget install gpt4free`

            **Docker:**
            - `docker pull hlohaus789/g4f:${{ needs.prepare.outputs.version }}`
            - `docker pull hlohaus789/g4f:${{ needs.prepare.outputs.version }}-slim`

            💻 **Having trouble with the .exe from this release?**  
            👉 Check out the Windows launcher for GPT4Free instead:  
            🔗 [https://github.com/gpt4free/g4f.exe](https://github.com/gpt4free/g4f.exe) 🚀  
          draft: false
          prerelease: false
          files: |
            ./artifacts/pypi-package/*
            ./artifacts/windows-exe-x64/*
            ./artifacts/linux-exe-x64/*
            ./artifacts/linux-exe-arm64/*
            ./artifacts/macos-exe-x64/*
            ./artifacts/macos-exe-arm64/*
            ./artifacts/debian-amd64/*
            ./artifacts/debian-arm64/*
            ./artifacts/debian-armhf/*
          token: ${{ secrets.GITHUB_TOKEN }}

  # Publish to PyPI (only for releases)
  # publish-pypi:
  #   runs-on: ubuntu-latest
  #   needs: [prepare, build-pypi, create-release]
  #   if: needs.prepare.outputs.is_release == 'true'
  #   environment:
  #     name: pypi
  #     url: https://pypi.org/p/g4f
  #   permissions:
  #     id-token: write
  #   steps:
  #     - name: Download PyPI artifacts
  #       uses: actions/download-artifact@v4
  #       with:
  #         name: pypi-package
  #         path: dist/
  #     - name: Publish to PyPI
  #       uses: pypa/gh-action-pypi-publish@release/v1