name: CI

on:
  push:
    branches:
      - master
  pull_request:
    branches:
      - master
  workflow_dispatch:

jobs:
  format-check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Install clang-format
        run: |
          sudo apt update -y
          sudo apt install -y lsb-release wget software-properties-common gnupg
          wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo gpg --dearmor -o /usr/share/keyrings/llvm-snapshot.gpg
          echo "deb [signed-by=/usr/share/keyrings/llvm-snapshot.gpg] http://apt.llvm.org/$(lsb_release -cs)/ llvm-toolchain-$(lsb_release -cs)-21 main" | sudo tee /etc/apt/sources.list.d/llvm.list
          sudo apt update -y
          sudo apt remove -y clang-format 2>/dev/null || true
          sudo apt install -y clang-format-21
          sudo ln -sf /usr/bin/clang-format-21 /usr/bin/clang-format

      - name: Check code formatting
        run: |
          ./clang-format.sh
          if ! git diff --quiet; then
            git diff
            echo ""
            echo "Please run './clang-format.sh' and commit the changes."
            exit 1
          fi

  build-linux:
    needs: [format-check]
    runs-on: ubuntu-24.04
    timeout-minutes: 30
    strategy:
      matrix:
        compiler: [gcc, clang]
        build_type: [Debug, Release]
      fail-fast: false

    steps:
      - uses: actions/checkout@v6

      - name: Update system
        run: sudo apt update

      - name: Install Dependencies
        run: |
          sudo apt install -y \
            cmake \
            liburing-dev \
            libsystemd-dev \
            python3-docutils \
            libzstd-dev \
            liblz4-dev \
            libbz2-dev \
            check \
            graphviz \
            doxygen \
            llvm \
            clang \
            net-tools \
            gcovr \
            pandoc texlive texlive-latex-extra texlive-fonts-extra texlive-xetex \
            texlive-luatex texlive-science texlive-extra-utils

      - name: Install Eisvogel template for Pandoc
        run: |
          wget https://github.com/Wandmalfarbe/pandoc-latex-template/releases/download/v3.3.0/Eisvogel-3.3.0.tar.gz
          tar -xzf Eisvogel-3.3.0.tar.gz
          mkdir -p ~/.local/share/pandoc/templates
          mv Eisvogel-3.3.0/eisvogel.latex ~/.local/share/pandoc/templates/

      - name: Install PostgreSQL
        run: |
          sudo apt install -y postgresql curl ca-certificates
          sudo install -d /usr/share/postgresql-common/pgdg
          sudo curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc
          sudo sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
          sudo apt update
          sudo apt install -y postgresql-17 postgresql-common postgresql-contrib

      - name: Set Env Path Variable for PostgreSQL
        run: |
          echo "PATH=$PATH:/usr/lib/postgresql/17/bin" >> $GITHUB_ENV
          echo $PATH

      - name: Build Project
        run: |
          mkdir build
          cd build
          if [ "${{ matrix.compiler }}" = "gcc" ]; then
            export CC=/usr/bin/gcc
          else
            export CC=/usr/bin/clang
          fi

          cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} ..
           make -j$(nproc)
        working-directory: /home/runner/work/pgagroal/pgagroal/

      - name: Testsuite
        id: test
        run: |
          if [ "${{ matrix.compiler }}" = "gcc" ] && [ "${{ matrix.build_type }}" = "Debug" ]; then
            ASAN_LIB=$(gcc -print-file-name=libasan.so)
            if [ -n "$ASAN_LIB" ] && [ -f "$ASAN_LIB" ]; then
              echo "Using GCC AddressSanitizer preload for Debug build"
              export ASAN_OPTIONS=verify_asan_link_order=0
              export LD_PRELOAD=$ASAN_LIB
              export ASAN_OPTIONS=detect_leaks=0,verify_asan_link_order=0
            fi
          fi
          $(which bash) ./check.sh run-configs-ci-nonbuild
        working-directory: /home/runner/work/pgagroal/pgagroal/build

      # === Generate coverage reports ===
      - name: Generate Detailed HTML Coverage Report
        if: matrix.compiler == 'gcc' && matrix.build_type == 'Debug'
        uses: threeal/gcovr-action@v1.1.0
        with:
          root: /home/runner/work/pgagroal/pgagroal
          html-details: true
          html-out: coverage.html

      - name: Generate Cobertura Report
        if: matrix.compiler == 'gcc' && matrix.build_type == 'Debug'
        uses: threeal/gcovr-action@v1.1.0
        with:
          xml-out: cobertura.xml

      - name: Generate Coveralls JSON Report and Upload
        if: matrix.compiler == 'gcc' && matrix.build_type == 'Debug'
        uses: threeal/gcovr-action@v1.1.0
        with:
          root: /home/runner/work/pgagroal/pgagroal
          coveralls-out: coveralls.json

      - name: Bundle All Coverage Reports
        if: matrix.compiler == 'gcc' && matrix.build_type == 'Debug'
        run: |
          mkdir -p coverage-report
          mv *.html coverage-report/
          mv cobertura.xml coverage-report/
          mv coveralls.json coverage-report/


      - name: Upload All Coverage Reports as Artifact
        if: matrix.compiler == 'gcc' && matrix.build_type == 'Debug'
        uses: actions/upload-artifact@v5
        with:
          name: coverage-reports-${{ matrix.compiler }}-${{ matrix.build_type }}
          path: coverage-report
          retention-days: 90

      - name: Upload Build and Run Logs as Artifacts
        if: always()
        uses: actions/upload-artifact@v5
        with:
          name: logs-${{ matrix.compiler }}-${{ matrix.build_type }}
          path: |
           /home/runner/work/pgagroal/pgagroal/log
           /tmp/pgagroal-test/*
          retention-days: 90

      - name: Upload Generated Documentation Artifact
        if: matrix.compiler == 'gcc' && matrix.build_type == 'Release'
        uses: actions/upload-artifact@v5
        with:
          name: generated-docs
          path: /home/runner/work/pgagroal/pgagroal/build/doc
          retention-days: 90

  build-macos:
    needs: [format-check]
    runs-on: macos-latest
    env:
      PGAGROAL_ROOT: ${{ github.workspace }}
      BUILD_DIR: ${{ github.workspace }}/build
      POSTGRESQL_VERSION: "@17"
    steps:
      - name: Checkout code
        uses: actions/checkout@v6

      - name: Install dependencies
        run: |
          brew update
          brew install openssl libev zstd lz4 libssh bzip2 docutils check graphviz doxygen

      - name: Configure and build with clang
        run: |
          export OPENSSL_ROOT_DIR=$(brew --prefix openssl)
          mkdir -p build
          cd build
          cmake -DCMAKE_BUILD_TYPE=Debug ..
          make -j$(sysctl -n hw.ncpu)

  build-freebsd:
    needs: [format-check]
    runs-on: ubuntu-latest
    name: FreeBSD Build and Test
    timeout-minutes: 30
    strategy:
      matrix:
        compiler: [clang]
        build_type: [Debug, Release]
      fail-fast: false

    steps:
      - uses: actions/checkout@v6
      - name: Install QEMU dependencies
        run: |
          sudo apt-get update
          sudo apt-get install -y \
            qemu-system-x86 \
            qemu-utils \
            libvirt-daemon-system \
            libvirt-clients \
            bridge-utils
          sudo systemctl start libvirtd
      - name: Setup FreeBSD VM
        uses: vmactions/freebsd-vm@v1
        id: freebsd-vm
        with:
          release: "14.3"
          usesh: true
          envs: "PATH,GITHUB_ENV,GITHUB_WORKSPACE,GITHUB_OUTPUT"
          mem: 4096
          sync: rsync
          copyback: true
          run: |
            # System bootstrap
            ASSUME_ALWAYS_YES=yes pkg bootstrap
            pkg update
            pkg upgrade -y
            # Base dependencies
            pkg install -y \
              bash \
              sudo \
              libev \
              cmake \
              postgresql17-server \
              postgresql17-contrib \
              zstd \
              liblz4 \
              bzip2 \
              libssh \
              libarchive \
              check \
              py311-docutils \
              curl \
              doxygen \
              hs-pandoc \
              texlive-base \
              texlive-texmf \
              graphviz
            # Initialize Graphviz plugins after installation
            dot -c
      - name: Build Project
        shell: freebsd {0}
        run: |
          mkdir -p $GITHUB_WORKSPACE/build
          cd $GITHUB_WORKSPACE/build
          cmake -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} "$GITHUB_WORKSPACE"
          make -j$(sysctl -n hw.ncpu)
