name: CI

on:
  pull_request:

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

jobs:
  changed_files:
    name: Get Changed Files
    runs-on: ubuntu-latest
    outputs:
      backend: ${{ steps.filter.outputs.backend }}
      frontend: ${{ steps.filter.outputs.frontend }}
      workflow: ${{ steps.filter.outputs.workflow }}
    steps:
      - uses: actions/checkout@v4
      - name: Check for file changes
        uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            backend:
              - 'backend/**'
            frontend:
              - 'frontend/**'
            workflow:
              - '.gitea/workflows/**'

  test-backend:
    runs-on: ubuntu-latest
    name: "Backend Tests"
    needs: changed_files
    if: ${{ needs.changed_files.outputs.backend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: "cimg/openjdk:23.0-node"
    steps:
      - name: "Checkout"
        uses: actions/checkout@v4

      - name: "Run tests"
        working-directory: ./backend
        run: |
          ./gradlew test

      - name: "Cache checkstyle results"
        uses: actions/upload-artifact@v4
        with:
          name: checkstyle-results
          path: backend/build/reports/checkstyle

      - name: "Stop Gradle"
        working-directory: ./backend
        run: ./gradlew --stop

  checkstyle:
    runs-on: ubuntu-latest
    name: "Checkstyle Main"
    needs: changed_files
    if: ${{ needs.changed_files.outputs.backend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: "cimg/openjdk:23.0-node"
    steps:
      - name: "Checkout"
        uses: actions/checkout@v4
      - name: "Cache Gradle dependencies"
        uses: https://github.com/actions/cache@v4
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
            backend/build/reports/checkstyle
          key: gradle-${{ runner.os }}-${{ hashFiles('backend/**/*.java', 'backend/config/checkstyle/checkstyle.xml') }}
          restore-keys: |
            gradle-${{ runner.os }}-
      - name: "Check cache for checkstyle reports"
        id: check-cache
        run: |
          if [ -d "backend/build/reports/checkstyle" ] && [ -f "backend/build/reports/checkstyle/main.xml" ]; then
            echo "Cache hit! Using cached checkstyle results"
            echo "cache-hit=true" >> $GITHUB_OUTPUT
          else
            echo "Cache miss! Running checkstyle check"
            echo "cache-hit=false" >> $GITHUB_OUTPUT
          fi

      - name: "Run checkstyle"
        if: steps.check-cache.outputs.cache-hit != 'true'
        working-directory: ./backend
        run: |
          gradle checkstyleMain

      - name: "Cache checkstyle results"
        if: steps.check-cache.outputs.cache-hit != 'true'
        uses: actions/upload-artifact@v4
        with:
          name: checkstyle-results
          path: backend/build/reports/checkstyle

      - name: "Stop Gradle"
        if: steps.check-cache.outputs.cache-hit != 'true'
        working-directory: ./backend
        run: gradle --stop

  validate-docker-frontend:
    runs-on: ubuntu-latest
    name: Docker frontend validation
    needs: changed_files
    if: ${{ needs.changed_files.outputs.frontend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: catthehacker/ubuntu:act-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Build
        uses: docker/build-push-action@v6
        with:
          context: frontend/
          file: frontend/.docker/Dockerfile
          push: false

  validate-docker-backend:
    runs-on: ubuntu-latest
    name: Docker backend validation
    needs: changed_files
    if: ${{ needs.changed_files.outputs.backend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: catthehacker/ubuntu:act-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Build
        uses: docker/build-push-action@v6
        with:
          context: backend/
          file: backend/.docker/Dockerfile
          push: false

  eslint:
    runs-on: docker
    container:
      image: git.kjan.de/actions/runner-bun:latest
    name: eslint
    needs: changed_files
    if: ${{ needs.changed_files.outputs.frontend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - uses: actions/cache@v4
        working-directory: ./frontend
        with:
          path: |
            frontend/node_modules/
          key: ${{ runner.os }}-bun-
          restore-keys: |
            ${{ runner.os }}-bun-
      - name: Install dependencies
        run: |
          cd frontend
          bun install
      - name: Run Eslint
        run: |
          cd frontend
          bun run lint

  oxlint:
    runs-on: docker
    name: oxlint
    needs: changed_files
    if: ${{ needs.changed_files.outputs.frontend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: git.kjan.de/actions/runner-bun:latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - uses: actions/cache@v4
        working-directory: ./frontend
        with:
          path: |
            frontend/node_modules/
          key: ${{ runner.os }}-bun-
          restore-keys: |
            ${{ runner.os }}-bun-
      - name: Install dependencies
        run: |
          cd frontend
          bun install
      - name: Run oxlint
        run: |
          cd frontend
          bun run oxlint

  prettier:
    runs-on: docker
    name: prettier
    needs: changed_files
    if: ${{ needs.changed_files.outputs.frontend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: git.kjan.de/actions/runner-bun:latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - uses: actions/cache@v4
        working-directory: ./frontend
        with:
          path: |
            frontend/node_modules/
          key: ${{ runner.os }}-bun-
          restore-keys: |
            ${{ runner.os }}-bun-
      - name: Install dependencies
        run: |
          cd frontend
          bun install
      - name: Run prettier
        run: |
          cd frontend
          bun run format:check

  test-build:
    runs-on: docker
    name: test-build
    needs: changed_files
    if: ${{ needs.changed_files.outputs.frontend == 'true' || needs.changed_files.outputs.workflow == 'true' }}
    container:
      image: git.kjan.de/actions/runner-bun:latest
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
      - uses: actions/cache@v4
        working-directory: ./frontend
        with:
          path: |
            frontend/node_modules/
          key: ${{ runner.os }}-bun-
          restore-keys: |
            ${{ runner.os }}-bun-
      - uses: actions/cache@v4
        working-directory: ./frontend
        with:
          path: |
            frontend/dist/
          key: ${{ runner.os }}-dist-
          restore-keys: |
            ${{ runner.os }}-dist-
      - name: Install dependencies
        run: |
          cd frontend
          bun install
      - name: Test build
        run: |
          cd frontend
          bun run build
