name: Reusable build
on:
  workflow_call:
    inputs:
      runs_on:
        description: Runner to run the job on
        required: true
        type: string
        default: heavy

      container:
        description: "The container object as a JSON string (leave empty to run natively)"
        required: true
        type: string
        default: ""

      conan_profile:
        description: Conan profile to use
        required: true
        type: string

      build_type:
        description: Build type
        required: true
        type: string

      disable_cache:
        description: Whether ccache and conan cache should be disabled
        required: false
        type: boolean
        default: false

      code_coverage:
        description: Whether to enable code coverage
        required: true
        type: boolean
        default: false

      static:
        description: Whether to build static binaries
        required: true
        type: boolean
        default: true

      unit_tests:
        description: Whether to run unit tests
        required: true
        type: boolean
        default: false

      integration_tests:
        description: Whether to run integration tests
        required: true
        type: boolean
        default: false

      clio_server:
        description: Whether to build clio_server
        required: true
        type: boolean
        default: true

      target:
        description: Build target name
        required: false
        type: string
        default: all

      sanitizer:
        description: Sanitizer to use
        required: false
        type: string
        default: "false"

jobs:
  build:
    name: Build ${{ inputs.container != '' && 'in container' || 'natively' }}
    runs-on: ${{ inputs.runs_on }}
    container: ${{ inputs.container != '' && fromJson(inputs.container) || null }}

    steps:
      - name: Clean workdir
        if: ${{ runner.os == 'macOS' }}
        uses: kuznetsss/workspace-cleanup@80b9863b45562c148927c3d53621ef354e5ae7ce #v1.0

      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Prepare runner
        uses: ./.github/actions/prepare_runner
        with:
          disable_ccache: ${{ inputs.disable_cache }}

      - name: Setup conan
        uses: ./.github/actions/setup_conan
        with:
          conan_profile: ${{ inputs.conan_profile }}

      - name: Restore cache
        if: ${{ !inputs.disable_cache }}
        uses: ./.github/actions/restore_cache
        id: restore_cache
        with:
          conan_dir: ${{ env.CONAN_USER_HOME }}/.conan
          conan_profile: ${{ inputs.conan_profile }}
          ccache_dir: ${{ env.CCACHE_DIR }}
          build_type: ${{ inputs.build_type }}
          code_coverage: ${{ inputs.code_coverage }}

      - name: Run conan and cmake
        uses: ./.github/actions/generate
        with:
          conan_profile: ${{ inputs.conan_profile }}
          conan_cache_hit: ${{ !inputs.disable_cache && steps.restore_cache.outputs.conan_cache_hit }}
          build_type: ${{ inputs.build_type }}
          code_coverage: ${{ inputs.code_coverage }}
          static: ${{ inputs.static }}
          sanitizer: ${{ inputs.sanitizer }}

      - name: Build Clio
        uses: ./.github/actions/build_clio
        with:
          target: ${{ inputs.target }}

      - name: Show ccache's statistics
        if: ${{ !inputs.disable_cache }}
        shell: bash
        id: ccache_stats
        run: |
          ccache -s > /tmp/ccache.stats
          miss_rate=$(cat /tmp/ccache.stats | grep 'Misses' | head -n1 | sed 's/.*(\(.*\)%).*/\1/')
          echo "miss_rate=${miss_rate}" >> $GITHUB_OUTPUT
          cat /tmp/ccache.stats

      - name: Strip unit_tests
        if: ${{ inputs.unit_tests && !inputs.code_coverage && inputs.sanitizer == 'false' }}
        run: strip build/clio_tests

      - name: Strip integration_tests
        if: ${{ inputs.integration_tests && !inputs.code_coverage }}
        run: strip build/clio_integration_tests

      - name: Upload clio_server
        if: ${{ inputs.clio_server }}
        uses: actions/upload-artifact@v4
        with:
          name: clio_server_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
          path: build/clio_server

      - name: Upload clio_tests
        if: ${{ inputs.unit_tests && !inputs.code_coverage }}
        uses: actions/upload-artifact@v4
        with:
          name: clio_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
          path: build/clio_tests

      - name: Upload clio_integration_tests
        if: ${{ inputs.integration_tests && !inputs.code_coverage }}
        uses: actions/upload-artifact@v4
        with:
          name: clio_integration_tests_${{ runner.os }}_${{ inputs.build_type }}_${{ inputs.conan_profile }}
          path: build/clio_integration_tests

      - name: Save cache
        if: ${{ !inputs.disable_cache && github.ref == 'refs/heads/develop' }}
        uses: ./.github/actions/save_cache
        with:
          conan_dir: ${{ env.CONAN_USER_HOME }}/.conan
          conan_hash: ${{ steps.restore_cache.outputs.conan_hash }}
          conan_cache_hit: ${{ steps.restore_cache.outputs.conan_cache_hit }}
          ccache_dir: ${{ env.CCACHE_DIR }}
          ccache_cache_hit: ${{ steps.restore_cache.outputs.ccache_cache_hit }}
          ccache_cache_miss_rate: ${{ steps.ccache_stats.outputs.miss_rate }}
          build_type: ${{ inputs.build_type }}
          code_coverage: ${{ inputs.code_coverage }}
          conan_profile: ${{ inputs.conan_profile }}

      # TODO: This is not a part of build process but it is the easiest way to do it here.
      # It will be refactored in https://github.com/XRPLF/clio/issues/1075
      - name: Run code coverage
        if: ${{ inputs.code_coverage }}
        uses: ./.github/actions/code_coverage

  upload_coverage_report:
    if: ${{ inputs.code_coverage }}
    name: Codecov
    needs: build
    uses: ./.github/workflows/upload_coverage_report.yml
    secrets:
      CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
