name: docker-images

on:
  push:
    branches:
      - main
      - master
    paths:
      - backend/**
      - frontend/**
      - admin/**
      - deploy/docker/**
      - .gitea/workflows/backend-docker.yml
  workflow_dispatch:

permissions:
  contents: read
  packages: write

jobs:
  build-and-push:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      max-parallel: 1
      matrix:
        include:
          - component: backend
            dockerfile: backend/Dockerfile
            context: backend
            default_image_name: termi-astro-backend
          - component: frontend
            dockerfile: frontend/Dockerfile
            context: frontend
            default_image_name: termi-astro-frontend
          - component: admin
            dockerfile: admin/Dockerfile
            context: admin
            default_image_name: termi-astro-admin

    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Resolve image metadata
        id: meta
        shell: bash
        env:
          COMPONENT: ${{ matrix.component }}
          DEFAULT_IMAGE_NAME: ${{ matrix.default_image_name }}
          VAR_REGISTRY_HOST: ${{ vars.REGISTRY_HOST }}
          VAR_IMAGE_NAMESPACE: ${{ vars.IMAGE_NAMESPACE }}
          VAR_IMAGE_NAME: ${{ vars.IMAGE_NAME }}
          VAR_BACKEND_IMAGE_NAME: ${{ vars.BACKEND_IMAGE_NAME }}
          VAR_FRONTEND_IMAGE_NAME: ${{ vars.FRONTEND_IMAGE_NAME }}
          VAR_ADMIN_IMAGE_NAME: ${{ vars.ADMIN_IMAGE_NAME }}
          VAR_FRONTEND_PUBLIC_API_BASE_URL: ${{ vars.FRONTEND_PUBLIC_API_BASE_URL }}
          VAR_ADMIN_VITE_API_BASE: ${{ vars.ADMIN_VITE_API_BASE }}
          VAR_ADMIN_VITE_FRONTEND_BASE_URL: ${{ vars.ADMIN_VITE_FRONTEND_BASE_URL }}
          VAR_ADMIN_VITE_BASENAME: ${{ vars.ADMIN_VITE_BASENAME }}
        run: |
          set -euo pipefail

          REGISTRY_HOST="${VAR_REGISTRY_HOST:-${GITEA_SERVER_URL#https://}}"
          if [ -z "${REGISTRY_HOST}" ]; then
            REGISTRY_HOST="git.init.cool"
          fi

          REPO_OWNER="${GITHUB_REPOSITORY_OWNER:-${GITEA_REPOSITORY_OWNER:-cool}}"
          IMAGE_NAMESPACE="${VAR_IMAGE_NAMESPACE:-${REPO_OWNER}}"

          case "${COMPONENT}" in
            backend)
              IMAGE_NAME="${VAR_BACKEND_IMAGE_NAME:-${VAR_IMAGE_NAME:-${DEFAULT_IMAGE_NAME}}}"
              ;;
            frontend)
              IMAGE_NAME="${VAR_FRONTEND_IMAGE_NAME:-${DEFAULT_IMAGE_NAME}}"
              ;;
            admin)
              IMAGE_NAME="${VAR_ADMIN_IMAGE_NAME:-${DEFAULT_IMAGE_NAME}}"
              ;;
            *)
              IMAGE_NAME="${DEFAULT_IMAGE_NAME}"
              ;;
          esac

          REF_NAME="${GITHUB_REF_NAME:-${GITEA_REF_NAME:-main}}"
          SAFE_REF="$(echo "${REF_NAME}" | tr '[:upper:]' '[:lower:]' | sed 's#[^a-z0-9._-]#-#g')"

          COMMIT_SHA="${GITHUB_SHA:-${GITEA_SHA:-dev}}"
          SHORT_SHA="$(echo "${COMMIT_SHA}" | cut -c1-12)"

          IMAGE_BASE="${REGISTRY_HOST}/${IMAGE_NAMESPACE}/${IMAGE_NAME}"

          FRONTEND_PUBLIC_API_BASE_URL="${VAR_FRONTEND_PUBLIC_API_BASE_URL:-http://localhost:5150/api}"
          ADMIN_VITE_API_BASE="${VAR_ADMIN_VITE_API_BASE:-http://localhost:5150}"
          ADMIN_VITE_FRONTEND_BASE_URL="${VAR_ADMIN_VITE_FRONTEND_BASE_URL:-http://localhost:4321}"
          ADMIN_VITE_BASENAME="${VAR_ADMIN_VITE_BASENAME:-}"

          {
            echo "registry_host=${REGISTRY_HOST}"
            echo "image_base=${IMAGE_BASE}"
            echo "tag_latest=latest"
            echo "tag_branch=${SAFE_REF}"
            echo "tag_sha=${SHORT_SHA}"
            echo "frontend_public_api_base_url=${FRONTEND_PUBLIC_API_BASE_URL}"
            echo "admin_vite_api_base=${ADMIN_VITE_API_BASE}"
            echo "admin_vite_frontend_base_url=${ADMIN_VITE_FRONTEND_BASE_URL}"
            echo "admin_vite_basename=${ADMIN_VITE_BASENAME}"
          } >> "$GITHUB_OUTPUT"

      - name: Login registry
        shell: bash
        env:
          REGISTRY_HOST: ${{ steps.meta.outputs.registry_host }}
          REGISTRY_USER: ${{ secrets.REGISTRY_USERNAME }}
          REGISTRY_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
          BUILTIN_GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
          GITHUB_ACTOR_NAME: ${{ github.actor }}
          GITHUB_REPOSITORY_OWNER_NAME: ${{ github.repository_owner }}
        run: |
          set -euo pipefail

          CUSTOM_REGISTRY_USER="${REGISTRY_USER:-}"
          CUSTOM_REGISTRY_TOKEN="${REGISTRY_TOKEN:-}"
          BUILTIN_REGISTRY_TOKEN="${BUILTIN_GITEA_TOKEN:-}"
          ACTOR_USER="${GITHUB_ACTOR_NAME:-}"
          OWNER_USER="${GITHUB_REPOSITORY_OWNER_NAME:-}"

          if [ -n "${CUSTOM_REGISTRY_TOKEN}" ]; then
            REGISTRY_TOKEN="${CUSTOM_REGISTRY_TOKEN}"
          else
            REGISTRY_TOKEN="${BUILTIN_REGISTRY_TOKEN}"
          fi

          if [ -z "${REGISTRY_TOKEN}" ]; then
            echo "Missing registry credentials: set REGISTRY_USERNAME/REGISTRY_TOKEN, or rely on the built-in GITEA_TOKEN with packages:write permission."
            exit 1
          fi

          CANDIDATE_USERS=()
          for candidate in "${CUSTOM_REGISTRY_USER}" "${ACTOR_USER}" "${OWNER_USER}"; do
            if [ -n "${candidate}" ] && [[ ! " ${CANDIDATE_USERS[*]} " =~ [[:space:]]${candidate}[[:space:]] ]]; then
              CANDIDATE_USERS+=("${candidate}")
            fi
          done

          if [ ${#CANDIDATE_USERS[@]} -eq 0 ]; then
            echo "Missing registry username: set REGISTRY_USERNAME or ensure github.actor/repository_owner are available."
            exit 1
          fi

          LOGIN_OK=0
          for candidate in "${CANDIDATE_USERS[@]}"; do
            if echo "${REGISTRY_TOKEN}" | docker login "${REGISTRY_HOST}" --username "${candidate}" --password-stdin; then
              LOGIN_OK=1
              break
            fi
          done

          if [ "${LOGIN_OK}" -ne 1 ]; then
            echo "Registry login failed for all candidate usernames."
            exit 1
          fi

      - name: Setup docker buildx
        shell: bash
        run: |
          set -euo pipefail

          if docker buildx inspect gitea-builder >/dev/null 2>&1; then
            docker buildx use gitea-builder
          else
            docker buildx create --name gitea-builder --driver docker-container --use
          fi

          docker buildx inspect --bootstrap

      - name: Build and push image
        shell: bash
        env:
          COMPONENT: ${{ matrix.component }}
          DOCKERFILE: ${{ matrix.dockerfile }}
          CONTEXT_DIR: ${{ matrix.context }}
          IMAGE_BASE: ${{ steps.meta.outputs.image_base }}
          TAG_LATEST: ${{ steps.meta.outputs.tag_latest }}
          TAG_BRANCH: ${{ steps.meta.outputs.tag_branch }}
          TAG_SHA: ${{ steps.meta.outputs.tag_sha }}
          FRONTEND_PUBLIC_API_BASE_URL: ${{ steps.meta.outputs.frontend_public_api_base_url }}
          ADMIN_VITE_API_BASE: ${{ steps.meta.outputs.admin_vite_api_base }}
          ADMIN_VITE_FRONTEND_BASE_URL: ${{ steps.meta.outputs.admin_vite_frontend_base_url }}
          ADMIN_VITE_BASENAME: ${{ steps.meta.outputs.admin_vite_basename }}
        run: |
          set -euo pipefail

          BUILD_ARGS=()
          if [ "${COMPONENT}" = "frontend" ]; then
            BUILD_ARGS+=(--build-arg "PUBLIC_API_BASE_URL=${FRONTEND_PUBLIC_API_BASE_URL}")
          fi

          if [ "${COMPONENT}" = "admin" ]; then
            BUILD_ARGS+=(--build-arg "VITE_API_BASE=${ADMIN_VITE_API_BASE}")
            BUILD_ARGS+=(--build-arg "VITE_FRONTEND_BASE_URL=${ADMIN_VITE_FRONTEND_BASE_URL}")
            BUILD_ARGS+=(--build-arg "VITE_ADMIN_BASENAME=${ADMIN_VITE_BASENAME}")
          fi

          docker buildx build \
            --file "${DOCKERFILE}" \
            "${BUILD_ARGS[@]}" \
            --build-arg BUILDKIT_INLINE_CACHE=1 \
            --cache-from "type=registry,ref=${IMAGE_BASE}:${TAG_BRANCH}" \
            --cache-from "type=registry,ref=${IMAGE_BASE}:${TAG_LATEST}" \
            --cache-to "type=inline" \
            --tag "${IMAGE_BASE}:${TAG_LATEST}" \
            --tag "${IMAGE_BASE}:${TAG_BRANCH}" \
            --tag "${IMAGE_BASE}:${TAG_SHA}" \
            --push \
            "${CONTEXT_DIR}"

      - name: Output image tags
        shell: bash
        env:
          COMPONENT: ${{ matrix.component }}
          IMAGE_BASE: ${{ steps.meta.outputs.image_base }}
          TAG_LATEST: ${{ steps.meta.outputs.tag_latest }}
          TAG_BRANCH: ${{ steps.meta.outputs.tag_branch }}
          TAG_SHA: ${{ steps.meta.outputs.tag_sha }}
        run: |
          echo "[${COMPONENT}] pushed tags:"
          echo "- ${IMAGE_BASE}:${TAG_LATEST}"
          echo "- ${IMAGE_BASE}:${TAG_BRANCH}"
          echo "- ${IMAGE_BASE}:${TAG_SHA}"
