name: Linux Distro Builds 🐧

on:
  push:
    branches: ["main"]
  pull_request:
    paths:
      - "src/cpp/**"
      - "CMakeLists.txt"
      - "**/CMakeLists.txt"
      - "CMakePresets.json"
      - "cmake/**"
      - "setup.sh"
      - "test/server_cli2.py"
      - "test/server_endpoints.py"
      - "test/requirements.txt"
      - "test/utils/**"
      - ".github/workflows/linux_distro_builds.yml"
      - ".github/actions/**"
      - "!**/*.md"
  workflow_dispatch:

permissions:
  contents: read

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'pull_request' && 'pr' || github.run_id }}
  cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
  build-linux:
    name: Build on ${{ matrix.distro }}
    runs-on: ubuntu-latest
    container:
      image: ${{ matrix.image }}
    env:
      HF_TOKEN: ${{ secrets.HUGGINGFACE_ACCESS_TOKEN }}
      CMAKE_C_COMPILER_LAUNCHER: ccache
      CMAKE_CXX_COMPILER_LAUNCHER: ccache
      CCACHE_DIR: ${{ github.workspace }}/.ccache

    strategy:
      fail-fast: false
      matrix:
        include:
          - distro: Arch
            image: archlinux:latest
            python: python
          - distro: openSUSE
            image: opensuse/tumbleweed:latest
            python: python3

    steps:
      - name: Checkout code
        uses: actions/checkout@v5
        with:
          clean: true
          fetch-depth: 0

      - name: Cache package downloads and ccache
        uses: actions/cache@v5
        with:
          path: |
            .package-cache
            .ccache
          key: cache-linux-distro-${{ matrix.distro }}-${{ hashFiles('CMakeLists.txt') }}-${{ github.run_id }}-${{ github.run_attempt }}
          restore-keys: |
            cache-linux-distro-${{ matrix.distro }}-${{ hashFiles('CMakeLists.txt') }}-
            cache-linux-distro-${{ matrix.distro }}-

      - name: Setup package cache directories
        run: |
          mkdir -p .package-cache/pacman .package-cache/zypp .package-cache/apt .package-cache/dnf
          if command -v pacman >/dev/null 2>&1; then
            mkdir -p /var/cache/pacman
            rm -rf /var/cache/pacman/pkg
            ln -s "$GITHUB_WORKSPACE/.package-cache/pacman" /var/cache/pacman/pkg
          elif command -v zypper >/dev/null 2>&1; then
            mkdir -p /var/cache
            rm -rf /var/cache/zypp
            ln -s "$GITHUB_WORKSPACE/.package-cache/zypp" /var/cache/zypp
          elif command -v apt-get >/dev/null 2>&1; then
            mkdir -p /var/cache/apt
            rm -rf /var/cache/apt/archives
            ln -s "$GITHUB_WORKSPACE/.package-cache/apt" /var/cache/apt/archives
          elif command -v dnf >/dev/null 2>&1; then
            mkdir -p /var/cache
            rm -rf /var/cache/dnf
            ln -s "$GITHUB_WORKSPACE/.package-cache/dnf" /var/cache/dnf
          fi

      - name: Install ccache
        run: |
          if command -v pacman >/dev/null 2>&1; then
            pacman -Syu --needed --noconfirm ccache
          elif command -v zypper >/dev/null 2>&1; then
            zypper install -y ccache
          elif command -v apt-get >/dev/null 2>&1; then
            apt-get update && apt-get install -y ccache
          elif command -v dnf >/dev/null 2>&1; then
            dnf install -y ccache
          fi
          ccache -z

      - name: Run setup.sh to configure environment
        run: |
          set -e

          echo "Running setup.sh for ${{ matrix.distro }}..."
          bash setup.sh

          echo "Verifying process management tools..."
          command -v pgrep && command -v pkill && command -v ps

          echo "Verifying SSL certificates..."
          ls -la /etc/ssl/certs/ | head -10

          echo "Testing HTTPS connectivity..."
          curl -sI https://huggingface.co | head -5 || echo "Warning: HTTPS test failed"

          echo "Setup completed successfully!"

      - name: Build C++ Server with CMake
        run: |
          set -e

          echo "Building lemond and lemonade on ${{ matrix.distro }}..."

          # Build
          echo "Building binaries..."
          cmake --build --preset default

          # Verify binaries exist
          if [ ! -f "build/lemond" ]; then
              echo "ERROR: lemond not found!"
              echo "Build directory contents:"
              ls -lh build/
              exit 1
          fi

          if [ ! -f "build/lemonade" ]; then
              echo "ERROR: lemonade not found!"
              echo "Build directory contents:"
              ls -lh build/
              exit 1
          fi

          echo "Binaries found successfully"
          ls -lh build/lemond build/lemonade

          echo "Verifying binary executability..."
          ./build/lemond --version
          ./build/lemonade --version

          echo "=== ccache statistics ==="
          ccache -s

          echo "${{ matrix.distro }} build successful!"

      - name: Verify system library linking
        run: |
          echo "Checking library dependencies..."
          cd build

          echo "=== lemond dependencies ==="
          ldd lemond

          echo ""
          echo "=== lemonade dependencies ==="
          ldd lemonade

          echo ""
          echo "All dependencies resolved successfully on ${{ matrix.distro }}!"

      - name: Setup Python virtual environment
        run: |
          echo "Creating Python virtual environment..."
          if [ "${{ matrix.distro }}" = "Debian" ]; then
              apt install -y python3-venv
          fi

          ${{ matrix.python }} -m venv .venv

          echo "Activating virtual environment and installing dependencies..."
          . .venv/bin/activate
          pip install --upgrade pip
          pip install -r test/requirements.txt

          echo "Python environment setup complete!"

      - name: Start server
        env:
          LEMONADE_CI_MODE: "True"
        run: |
          echo "Starting lemond in background..."
          mkdir -p "$RUNNER_TEMP/xdg-runtime"
          chmod 700 "$RUNNER_TEMP/xdg-runtime"
          echo "XDG_RUNTIME_DIR=$RUNNER_TEMP/xdg-runtime" >> "$GITHUB_ENV"
          export XDG_RUNTIME_DIR="$RUNNER_TEMP/xdg-runtime"
          ./build/lemond --port 13305 > "$RUNNER_TEMP/lemonade-server.log" 2>&1 &

          echo "Waiting for server to be ready..."
          for i in $(seq 1 30); do
            if curl -sf http://localhost:13305/live > /dev/null 2>&1; then
              echo "Server is running and healthy"
              exit 0
            fi
            sleep 2
          done
          echo "ERROR: Server did not start"
          cat "$RUNNER_TEMP/lemonade-server.log" 2>/dev/null || true
          exit 1

      - name: Run CLI tests
        env:
          LEMONADE_CI_MODE: "True"
          PYTHONIOENCODING: utf-8
        run: |
          set -e

          . .venv/bin/activate
          CLI_BINARY="$(pwd)/build/lemonade"

          echo "Running CLI tests..."
          python test/server_cli2.py --cli-binary "$CLI_BINARY"

          echo "CLI tests PASSED!"

      - name: Run endpoint tests
        env:
          LEMONADE_CI_MODE: "True"
          PYTHONIOENCODING: utf-8
        run: |
          set -e

          . .venv/bin/activate
          CLI_BINARY="$(pwd)/build/lemonade"

          echo "Running endpoint tests..."
          python test/server_endpoints.py --cli-binary "$CLI_BINARY"

          echo "Endpoint tests PASSED!"

      - name: Capture and upload server logs
        if: always()
        uses: ./.github/actions/capture-server-logs
        with:
          artifact-name: server-logs-distro-${{ matrix.distro }}
