#######################################################################################
# Copyright ETSI Contributors and Others.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#######################################################################################

set -e -o pipefail

export HERE=$(dirname "$(readlink --canonicalize "$BASH_SOURCE")")
source "${HERE}/library/functions.sh"
source "${HERE}/library/trap.sh"



# Input values
export CLUSTER_DIR="$1"
export PROJECT_DIR="$2"
export PROFILE_NAME="$3"
export TEMPLATES_DIR="$4"
export PUBLIC_KEY="$5"


# Helper functions to create the profile ConfigMaps
function safe_name() {
  echo "$1" | \
    sed '/\.\// s|./||' | \
    sed 's|\.|-|g' | \
    sed 's|/|-|g' | \
    sed 's|_|-|g' | \
    sed 's| |-|g'
}

function create_profile_configmap() {
  local CONFIGMAP_NAME=$(safe_name "$1")
  local PROFILE_REPO_URL="$2"
  local PROFILE_PATH="$3"
  kubectl create configmap ${CONFIGMAP_NAME} \
    --namespace flux-system \
    --from-literal=repo="${PROFILE_REPO_URL}" \
    --from-literal=path="${PROFILE_PATH}" \
    -o yaml \
    --dry-run=client
}

# Helper functions to clone secret from one namespace to other
function clone_secret_to_new_ns_stdout() {
  local SECRET_NAME="$1"
  local SOURCE_NS="$2"
  local DESTINATION_NS="$3"

  kubectl get secret "${SECRET_NAME}" -n "${SOURCE_NS}" -o yaml | \
  yq 'del(.metadata.uid) | del(.metadata.resourceVersion) | del(.metadata.creationTimestamp)' | \
  yq ".metadata.namespace = \"${DESTINATION_NS}\""
}

# Helper function to encrypt secrets from stdin
function encrypt_secret_from_stdin() {
  local PUBLIC_KEY="$1"

  # Save secret manifest to temporary file
  local TMPFILE=$(mktemp /tmp/secret.XXXXXXXXXX.yaml) || exit 1
  cat > "${TMPFILE}"

  # Encrypt
  sops \
    --age=${PUBLIC_KEY} \
    --encrypt \
    --encrypted-regex '^(data|stringData)$' \
    --in-place "${TMPFILE}"

  # Outputs the result and removes the temporary file
  cat "${TMPFILE}" && rm -f "${TMPFILE}"
}

# Creates all folders in the profile (as well as env var aliases)
export ADDON_CTRL_DIR="${PROJECT_DIR}/infra-controller-profiles/${PROFILE_NAME}"
export ADDON_CONFIG_DIR="${PROJECT_DIR}/infra-config-profiles/${PROFILE_NAME}"
export RESOURCES_DIR="${PROJECT_DIR}/managed-resources/${PROFILE_NAME}"
export APPS_DIR="${PROJECT_DIR}/app-profiles/${PROFILE_NAME}"
mkdir -p "${ADDON_CTRL_DIR}"
mkdir -p "${ADDON_CONFIG_DIR}"
mkdir -p "${RESOURCES_DIR}"
mkdir -p "${APPS_DIR}"

# Copies the templates for cluster setup
cp "${TEMPLATES_DIR}"/* "${CLUSTER_DIR}/"

# Repo URLs
export FLEET_REPO_URL="${GITEA_HTTP_URL}/${GITEA_STD_USERNAME}/fleet-osm.git"
export SW_CATALOGS_REPO_URL="${GITEA_HTTP_URL}/${GITEA_STD_USERNAME}/sw-catalogs-osm.git"
export INFRA_CONTROLLERS_PATH="./${MGMT_PROJECT_NAME}/infra-controller-profiles/_management"
export INFRA_CONFIGS_PATH="./${MGMT_PROJECT_NAME}/infra-config-profiles/_management"
export MANAGED_RESOURCES_PATH="./${MGMT_PROJECT_NAME}/managed-resources/_management"
export APPS_PATH="./${MGMT_PROJECT_NAME}/app-profiles/_management"

# Render Flux `GitRepository` objects with proper Git URL and relative repo paths
envsubst < "${TEMPLATES_DIR}/fleet-repo.yaml" > "${CLUSTER_DIR}/fleet-repo.yaml"
envsubst < "${TEMPLATES_DIR}/sw-catalogs-repo.yaml" > "${CLUSTER_DIR}/sw-catalogs-repo.yaml"

# Secrets to access both Git repos
# (NOTE: these are the last secrets to be added imperatively)
kubectl delete secret fleet-repo --namespace flux-system 2> /dev/null || true
kubectl create secret generic fleet-repo \
    --namespace flux-system \
    --from-literal=username="${GITEA_STD_USERNAME}" \
    --from-literal=password="${GITEA_STD_USER_PASS}"

kubectl delete secret sw-catalogs --namespace flux-system 2> /dev/null || true
kubectl create secret generic sw-catalogs \
    --namespace flux-system \
    --from-literal=username="${GITEA_STD_USERNAME}" \
    --from-literal=password="${GITEA_STD_USER_PASS}"

# Render Flux `Kustomizations` to sync with default profiles
envsubst < "${TEMPLATES_DIR}/infra-controllers.yaml" > "${CLUSTER_DIR}/infra-controllers.yaml"
envsubst < "${TEMPLATES_DIR}/infra-configs.yaml" > "${CLUSTER_DIR}/infra-configs.yaml"
envsubst < "${TEMPLATES_DIR}/managed-resources.yaml" > "${CLUSTER_DIR}/managed-resources.yaml"
envsubst < "${TEMPLATES_DIR}/apps.yaml" > "${CLUSTER_DIR}/apps.yaml"

# Create `ConfigMaps` into profiles (and `Namespace` specs when needed) to avoid sync errors
## Infra controllers ConfigMap
CONFIGMAP_NAME="infra-controllers"
PROFILE_REPO_URL="${FLEET_REPO_URL}"
PROFILE_PATH="${INFRA_CONTROLLERS_PATH}"
create_profile_configmap \
  "${CONFIGMAP_NAME}" \
  "${PROFILE_REPO_URL}" \
  "${PROFILE_PATH}" \
  > "${ADDON_CTRL_DIR}/profile-configmap.yaml"

## Infra configurations ConfigMap
CONFIGMAP_NAME="infra-configs"
PROFILE_REPO_URL="${FLEET_REPO_URL}"
PROFILE_PATH="${INFRA_CONFIGS_PATH}"
create_profile_configmap \
  "${CONFIGMAP_NAME}" \
  "${PROFILE_REPO_URL}" \
  "${PROFILE_PATH}" \
  > "${ADDON_CONFIG_DIR}/profile-configmap.yaml"

## Managed resources ConfigMap
CONFIGMAP_NAME="managed-resources"
PROFILE_REPO_URL="${FLEET_REPO_URL}"
PROFILE_PATH="${MANAGED_RESOURCES_PATH}"
create_profile_configmap \
  "${CONFIGMAP_NAME}" \
  "${PROFILE_REPO_URL}" \
  "${PROFILE_PATH}" \
  > "${RESOURCES_DIR}/profile-configmap.yaml"

## Managed resources namespace
kubectl create ns ${CONFIGMAP_NAME} \
    -o yaml \
    --dry-run=client \
    > "${RESOURCES_DIR}/namespace.yaml"

### Copy secrets for Git repos from `flux-system` to `managed-resources` namespace
clone_secret_to_new_ns_stdout \
  flux-system \
  flux-system \
  "${CONFIGMAP_NAME}" | \
encrypt_secret_from_stdin \
  "${PUBLIC_KEY}" \
> "${RESOURCES_DIR}/secret-flux-system.yaml"

clone_secret_to_new_ns_stdout \
  fleet-repo \
  flux-system \
  "${CONFIGMAP_NAME}" | \
encrypt_secret_from_stdin \
  "${PUBLIC_KEY}" \
> "${RESOURCES_DIR}/secret-fleet-repo.yaml"

clone_secret_to_new_ns_stdout \
  sw-catalogs \
  flux-system \
  "${CONFIGMAP_NAME}" | \
encrypt_secret_from_stdin \
  "${PUBLIC_KEY}" \
> "${RESOURCES_DIR}/secret-sw-catalogs.yaml"

## Apps ConfigMap
CONFIGMAP_NAME="apps"
PROFILE_REPO_URL="${FLEET_REPO_URL}"
PROFILE_PATH="${APPS_PATH}"
create_profile_configmap \
  "${CONFIGMAP_NAME}" \
  "${PROFILE_REPO_URL}" \
  "${PROFILE_PATH}" \
  > "${APPS_DIR}/profile-configmap.yaml"
