name: CI - Build

on:
  workflow_call:
  workflow_dispatch:

jobs:
  build:
    outputs:
      allow_push: ${{ steps.meta.outputs.allow_push }}
      ref_name: ${{ steps.meta.outputs.ref_name }}
      event_name: ${{ steps.meta.outputs.event_name }}
      sha: ${{ steps.meta.outputs.sha }}
    runs-on: ubuntu-latest
    env:
      DEFAULT_BRANCH: main
      REGISTRY_URL: ${{ secrets.REGISTRY_URL }}
      REGISTRY_USERNAME: ${{ secrets.REGISTRY_USERNAME }}
      REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
      REGISTRY_CONTAINER_NAME: calminer
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Collect workflow metadata
        id: meta
        shell: bash
        env:
          DEFAULT_BRANCH: ${{ env.DEFAULT_BRANCH }}
        run: |
          git_ref="${GITEA_REF:-${GITHUB_REF:-}}"
          ref_name="${GITEA_REF_NAME:-${GITHUB_REF_NAME:-}}"
          if [ -z "$ref_name" ] && [ -n "$git_ref" ]; then
            ref_name="${git_ref##*/}"
          fi
          event_name="${GITEA_EVENT_NAME:-${GITHUB_EVENT_NAME:-}}"
          sha="${GITEA_SHA:-${GITHUB_SHA:-}}"
          if [ -z "$sha" ]; then
            sha="$(git rev-parse HEAD)"
          fi

          if [ "$ref_name" = "${DEFAULT_BRANCH:-main}" ] && [ "$event_name" != "pull_request" ]; then
            echo "allow_push=true" >> "$GITHUB_OUTPUT"
          else
            echo "allow_push=false" >> "$GITHUB_OUTPUT"
          fi

          echo "ref_name=$ref_name" >> "$GITHUB_OUTPUT"
          echo "event_name=$event_name" >> "$GITHUB_OUTPUT"
          echo "sha=$sha" >> "$GITHUB_OUTPUT"

      - name: Validate registry configuration
        shell: bash
        run: |
          set -euo pipefail
          if [ -z "${REGISTRY_URL}" ]; then
            echo "::error::REGISTRY_URL secret not configured. Configure it with your Gitea container registry host." >&2
            exit 1
          fi
          server_url="${GITEA_SERVER_URL:-${GITHUB_SERVER_URL:-}}"
          server_host="${server_url#http://}"
          server_host="${server_host#https://}"
          server_host="${server_host%%/*}"
          server_host="${server_host%%:*}"
          registry_host="${REGISTRY_URL#http://}"
          registry_host="${registry_host#https://}"
          registry_host="${registry_host%%/*}"
          registry_host="${registry_host%%:*}"
          if [ -n "${server_host}" ] && ! printf '%s' "${registry_host}" | grep -qi "${server_host}"; then
            echo "::warning::REGISTRY_URL (${REGISTRY_URL}) does not match current Gitea host (${server_host}). Ensure this registry endpoint is managed by Gitea." >&2
          fi

      - name: Set up QEMU and Buildx
        uses: docker/setup-buildx-action@v3

      - name: Log in to gitea registry
        if: ${{ steps.meta.outputs.allow_push == 'true' }}
        uses: docker/login-action@v3
        continue-on-error: true
        with:
          registry: ${{ env.REGISTRY_URL }}
          username: ${{ env.REGISTRY_USERNAME }}
          password: ${{ env.REGISTRY_PASSWORD }}

      - name: Build image
        id: build-image
        env:
          REGISTRY_URL: ${{ env.REGISTRY_URL }}
          REGISTRY_CONTAINER_NAME: ${{ env.REGISTRY_CONTAINER_NAME }}
          SHA_TAG: ${{ steps.meta.outputs.sha }}
          PUSH_IMAGE: ${{ steps.meta.outputs.allow_push == 'true' && env.REGISTRY_URL != '' && env.REGISTRY_USERNAME != '' && env.REGISTRY_PASSWORD != '' }}
        run: |
          set -eo pipefail
          LOG_FILE=build.log
          if [ "${PUSH_IMAGE}" = "true" ]; then
            docker buildx build \
              --push \
              --tag "${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:latest" \
              --tag "${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:${SHA_TAG}" \
              --file Dockerfile \
              . 2>&1 | tee "${LOG_FILE}"
          else
            docker buildx build \
              --load \
              --tag "${REGISTRY_CONTAINER_NAME}:ci" \
              --file Dockerfile \
              . 2>&1 | tee "${LOG_FILE}"
          fi

      - name: Upload docker build logs
        if: failure()
        uses: actions/upload-artifact@v4
        with:
          name: docker-build-logs
          path: build.log

  deploy:
    needs: build
    if: needs.build.outputs.allow_push == 'true'
    runs-on: ubuntu-latest
    env:
      REGISTRY_URL: ${{ secrets.REGISTRY_URL }}
      REGISTRY_CONTAINER_NAME: calminer
      KUBE_CONFIG: ${{ secrets.KUBE_CONFIG }}
      STAGING_KUBE_CONFIG: ${{ secrets.STAGING_KUBE_CONFIG }}
      PROD_KUBE_CONFIG: ${{ secrets.PROD_KUBE_CONFIG }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Capture commit metadata
        id: commit_meta
        run: |
          set -euo pipefail
          message="$(git log -1 --pretty=%B | tr '\n' ' ')"
          echo "message=$message" >> "$GITHUB_OUTPUT"

      - name: Set up kubectl for staging
        if: contains(steps.commit_meta.outputs.message, '[deploy staging]')
        uses: azure/k8s-set-context@v3
        with:
          method: kubeconfig
          kubeconfig: ${{ env.STAGING_KUBE_CONFIG }}

      - name: Set up kubectl for production
        if: contains(steps.commit_meta.outputs.message, '[deploy production]')
        uses: azure/k8s-set-context@v3
        with:
          method: kubeconfig
          kubeconfig: ${{ env.PROD_KUBE_CONFIG }}

      - name: Deploy to staging
        if: contains(steps.commit_meta.outputs.message, '[deploy staging]')
        run: |
          kubectl set image deployment/calminer-app calminer=${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:latest
          kubectl apply -f k8s/configmap.yaml
          kubectl apply -f k8s/secret.yaml
          kubectl rollout status deployment/calminer-app

      - name: Collect staging deployment logs
        if: contains(steps.commit_meta.outputs.message, '[deploy staging]')
        run: |
          mkdir -p logs/deployment/staging
          kubectl get pods -o wide > logs/deployment/staging/pods.txt
          kubectl get deployment calminer-app -o yaml > logs/deployment/staging/deployment.yaml
          kubectl logs deployment/calminer-app --all-containers=true --tail=500 > logs/deployment/staging/calminer-app.log

      - name: Deploy to production
        if: contains(steps.commit_meta.outputs.message, '[deploy production]')
        run: |
          kubectl set image deployment/calminer-app calminer=${REGISTRY_URL}/allucanget/${REGISTRY_CONTAINER_NAME}:latest
          kubectl apply -f k8s/configmap.yaml
          kubectl apply -f k8s/secret.yaml
          kubectl rollout status deployment/calminer-app

      - name: Collect production deployment logs
        if: contains(steps.commit_meta.outputs.message, '[deploy production]')
        run: |
          mkdir -p logs/deployment/production
          kubectl get pods -o wide > logs/deployment/production/pods.txt
          kubectl get deployment calminer-app -o yaml > logs/deployment/production/deployment.yaml
          kubectl logs deployment/calminer-app --all-containers=true --tail=500 > logs/deployment/production/calminer-app.log

      - name: Upload deployment logs
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: deployment-logs
          path: logs/deployment
          if-no-files-found: ignore
