name: Build and Push Container

on:
  push:
    branches:
      - master
      - main
    tags:
      - v*
  workflow_dispatch:

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    env:
      REGISTRY: gitea.wayfinderak.com
      IMAGE_NAME: gitea.wayfinderak.com/wayfinderak/goff
    container:
      options: --dns 172.16.30.10
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Go and Docker CLI if needed
        shell: bash
        run: |
          set -euo pipefail

          need_apt=0
          need_apk=0
          if ! command -v go >/dev/null 2>&1 || ! command -v docker >/dev/null 2>&1; then
            if command -v apt-get >/dev/null 2>&1; then
              need_apt=1
            elif command -v apk >/dev/null 2>&1; then
              need_apk=1
            else
              echo "No supported package manager found" >&2
              exit 1
            fi
          fi

          if [ "$need_apt" -eq 1 ]; then
            apt-get update
            if ! command -v go >/dev/null 2>&1; then
              apt-get install -y golang-go
            fi
            if ! command -v docker >/dev/null 2>&1; then
              apt-get install -y docker.io curl dnsutils iputils-ping
            fi
          fi

          if [ "$need_apk" -eq 1 ]; then
            if ! command -v go >/dev/null 2>&1; then
              apk add --no-cache go
            fi
            if ! command -v docker >/dev/null 2>&1; then
              apk add --no-cache docker-cli curl bind-tools iputils
            fi
          fi

          go version
          docker version

      - name: Run tests
        run: go test ./...

      - name: Log in to Gitea Container Registry
        shell: bash
        run: |
          set -euo pipefail
          for attempt in 1 2 3; do
            echo "docker login attempt $attempt"
            if echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "$REGISTRY" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin; then
              exit 0
            fi
            sleep 5
          done
          echo "docker login failed after 3 attempts" >&2
          exit 1

      - name: Determine image tags
        id: meta
        shell: bash
        env:
          REF: ${{ gitea.ref }}
          REF_NAME: ${{ gitea.ref_name }}
          SHA: ${{ gitea.sha }}
        run: |
          set -euo pipefail
          tags=()

          if [[ "$REF" == refs/tags/* ]]; then
            version="$REF_NAME"
            tags+=("$IMAGE_NAME:$version")
            tags+=("$IMAGE_NAME:latest")
          else
            branch="$REF_NAME"
            branch_safe="$(echo "$branch" | tr '/_' '--')"
            sha_short="$(echo "$SHA" | cut -c1-7)"
            tags+=("$IMAGE_NAME:$branch_safe")
            tags+=("$IMAGE_NAME:$branch_safe-$sha_short")
            if [[ "$branch" == "main" ]]; then
              tags+=("$IMAGE_NAME:latest")
            fi
          fi

          printf 'tags<<EOF\n' >> "$GITHUB_OUTPUT"
          printf '%s\n' "${tags[@]}" >> "$GITHUB_OUTPUT"
          printf 'EOF\n' >> "$GITHUB_OUTPUT"

      - name: Build image
        shell: bash
        run: |
          set -euo pipefail
          mapfile -t tags <<'EOF'
          ${{ steps.meta.outputs.tags }}
          EOF

          build_args=()
          for tag in "${tags[@]}"; do
            build_args+=(--tag "$tag")
          done

          docker build "${build_args[@]}" .

      - name: Push image
        shell: bash
        run: |
          set -euo pipefail
          while IFS= read -r tag; do
            [ -n "$tag" ] || continue
            docker push "$tag"
          done <<'EOF'
          ${{ steps.meta.outputs.tags }}
          EOF