#!/bin/bash

set -e
set -u

clear
echo "############# Bootstrapping Omni K3D Cluster #############"

# Cluster name to check
CLUSTER_NAME=omni-local-cluster
KC_VERSION=22.0.1
HA_INSTANCES=3
DOMAIN_NAME=localhost
INGRESS_CLASS=traefik
OMNI_HELM_VERSION=1.0.0
REGISTRY_USERNAME=''
REGISTRY_PASSWORD=''

if [ -f .env ]; then
    # Load the .env file
    set -o allexport
    source .env
    set -o allexport
fi

echo $REGISTRY_USERNAME

function fail {
    printf '%s\n' "$1" >&2
    exit "${2-1}"
}

function new_step {
  echo ""
  echo "$1"
}

function verify_context {
  NODES=$(kubectl get nodes)
  if ! echo "$NODES" | grep -q "$CLUSTER_NAME"; then
    echo "Uh Oh! The 'kubectl' context doesn't look correct. Please verify."
    kubectl get nodes
    fail "Kubectl context doesn't appear to be correct"
  fi
}

function apply_yaml {
  echo $1 | kubectl apply -f -

  # Check if the apply command was successful
  if [ $? -eq 0 ]; then
    echo "YAML configuration applied successfully."
  else
    fail "Failed to apply YAML configuration."
  fi
}

function wait_for_pod() {
  local pod_name=$1
  local namespace=$2
  local timeout=${3:-300}
  local interval=${4:-10}
  local elapsed=0

  # Wait for the pod to be created
  echo "Waiting for pod '$pod_name' to be created..."
  while [[ $(kubectl get pod "$pod_name" -n "$namespace" --ignore-not-found -o jsonpath='{.status.phase}' 2>/dev/null) != "Running" && $elapsed -lt $timeout ]]; do
    sleep $interval
    elapsed=$((elapsed + interval))
  done

  if [[ $elapsed -ge $timeout ]]; then
    echo "Timeout waiting for pod '$pod_name' to be created or become running."
    return 1
  fi

  echo "Pod '$pod_name' is now running."
  return 0
}

# Check if the cluster exists
if k3d cluster list | grep -q "^${CLUSTER_NAME} "; then
  echo ""
  echo "K3D Cluster '$CLUSTER_NAME' already exists!"
  read -p "Do you want to recreate this cluster? (y/n) " DO_RECREATE_CLUSTER

  if echo $DO_RECREATE_CLUSTER | grep -q "y"; then
    echo ""
    k3d cluster delete $CLUSTER_NAME
  else
    fail "Cluster '${CLUSTER_NAME}' already exists. You must delete this cluster to run the process again."
  fi
fi

new_step "1) Creating cluster."
k3d cluster create -p "80:80@loadbalancer" -p "443:443@loadbalancer" $CLUSTER_NAME
verify_context

new_step "2) Installing Postgres Operator"
helm repo add cnpg https://cloudnative-pg.github.io/charts
helm upgrade --install cnpg --namespace cnpg-system --create-namespace cnpg/cloudnative-pg --wait

new_step "3) Installing Keycloak CRDs"
kubectl create namespace keycloak
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/$KC_VERSION/kubernetes/keycloaks.k8s.keycloak.org-v1.yml
kubectl apply -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/$KC_VERSION/kubernetes/keycloakrealmimports.k8s.keycloak.org-v1.yml
kubectl apply -n keycloak -f https://raw.githubusercontent.com/keycloak/keycloak-k8s-resources/$KC_VERSION/kubernetes/kubernetes.yml

new_step "4) Creating Keycloak DB"
echo "
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgres
  namespace: keycloak
spec:
  instances: ${HA_INSTANCES}
  storage:
    size: 25Gi
  bootstrap:
    initdb:
      database: keycloak
      owner: keycloaky
  monitoring:
    enablePodMonitor: true
" | kubectl apply -f -

wait_for_pod "postgres-$HA_INSTANCES" keycloak

new_step "5) Creating Keycloak Cluster"
echo "
apiVersion: k8s.keycloak.org/v2alpha1
kind: Keycloak
metadata:
  name: keycloak
  namespace: keycloak
spec:
  instances: ${HA_INSTANCES}
  ingress:
    enabled: true
    className: ${INGRESS_CLASS}
  http:
    httpEnabled: true
  db:
    vendor: postgres
    usernameSecret:
      name: postgres-app
      key: username
    passwordSecret:
      name: postgres-app
      key: password
    host: postgres-rw.keycloak.svc
    database: keycloak
  hostname:
    hostname: identity.${DOMAIN_NAME}
  additionalOptions:
    - name: proxy
      value: edge
" | kubectl apply -f -

# Keycloaks starts counting from 0, so we need to subtract 1.
KC_INSTANCES=$(($HA_INSTANCES - 1))
wait_for_pod "keycloak-$KC_INSTANCES" keycloak

new_step "6) Create Omni DB"
kubectl create namespace omni
echo "
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgres
  namespace: omni
spec:
  instances: ${HA_INSTANCES}
  storage:
    size: 25Gi
  bootstrap:
    initdb:
      database: omni
      owner: omni
  monitoring:
    enablePodMonitor: true
" | kubectl apply -f -

wait_for_pod "postgres-$HA_INSTANCES" omni

new_step "7) Deploy Omni resources"
kubectl create secret docker-registry rizing-registry -n omni \
  --docker-server=registry.rizing.cloud \
  --docker-username="$REGISTRY_USERNAME" \
  --docker-password="$REGISTRY_PASSWORD"

KC_USERNAME=$(kubectl get secrets/keycloak-initial-admin -n keycloak --template='{{.data.username | base64decode}}')
KC_PASSWORD=$(kubectl get secrets/keycloak-initial-admin -n keycloak --template='{{.data.password | base64decode}}')

echo "
timezone: UTC
image:
  tag: 'release'
host: ${DOMAIN_NAME}
app:
  replicaCount: 1
api:
  replicaCount: 3
  db:
    type: postgres
    host: postgres-rw.omni.svc
    database: omni
    username: omni
    usernameSecretName: postgres-app
    passwordSecretName: postgres-app
  keycloak:
    host: 'http://keycloak-service.keycloak.svc.cluster.local:8080'
    username: ${KC_USERNAME}
    password: ${KC_PASSWORD}
docs:
  replicaCount: 1
" | helm install omni oci://registry.rizing.cloud/library/omni -n omni --version $OMNI_HELM_VERSION --wait --values -

echo ""
echo "#####################################################"
echo "Cluster bootstrap completed"
echo "#####################################################"
echo ""
echo "Your local HA Omni deployment is complete."
echo ""
echo "Visit https://omni.$DOMAIN_NAME/master"
echo ""
echo "Username: admin"
echo "Password: $KC_PASSWORD"