#!/usr/bin/env bash

# Script expects the next environment variables to be set:
# - Environment
# - REGISTRY_PORT

# Configure shell.
set -u

# Set global success flag.
UPLOAD_SUCCESSFUL='true'

# User-friendly print wrapper.
log() {
  printf '[%s] [%s] %s\n' "${0##*/}" "$( date '+%Y-%m-%dT%H:%M:%S' )" "${@}"
}

# Enable read-write mode to be able to upload schemas.
enableReadWriteMode() {
  log 'Enabling schema-registry read-write mode'

  CURL_PAYLOAD='
    {
      "mode": "READWRITE"
    }'

  CURL_STATUS=$( curl -s -o /tmp/curl.response -w %{http_code} \
                  -X "PUT" "http://localhost:${REGISTRY_PORT}/mode" \
                  -H 'Accept: application/vnd.schemaregistry.v1+json, application/vnd.schemaregistry+json, application/json' \
                  -H 'Content-Type: application/vnd.schemaregistry.v1+json' \
                  -d "${CURL_PAYLOAD}" )

  if [[ "${CURL_STATUS}" != '200' ]]; then
    log "Error: Mode change has failed, got ${CURL_STATUS} response code."
    log "Error details: $( cat /tmp/curl.response )"
    return 1
  fi

  log 'Schema-registry mode has been changed to read-write.'

  return 0
}

# Schema definition file upload function.
uploadSchemaDefinition() {
  local SCHEMA_DIR="$1"

  # Check for schema definition file in the directory.
  if [[ ! -f "${SCHEMA_DIR}/schema.json" ]]; then
    log "Error: No schema.json file in the ${SCHEMA_DIR} directory"
    return 1
  fi

  # Set schema subject.
  SCHEMA_SUBJECT="${SCHEMA_DIR##*/}"

  # Upload schema definition file.
  log "Uploading ${SCHEMA_SUBJECT} schema definition"

  # Get schema type from the config.json file, default to AVRO if not present
  SCHEMA_TYPE=$( grep -o '"schemaType" *: *"[^"]*"' "${SCHEMA_DIR}/config.json" 2>/dev/null | sed 's/.*: *"\([^"]*\)"/\1/' )
  SCHEMA_TYPE="${SCHEMA_TYPE:-AVRO}"

  CURL_PAYLOAD='
    {
      "schemaType": "'"${SCHEMA_TYPE}"'",
      "schema": "'"$( cat "${SCHEMA_DIR}/schema.json" | sed 's|"|\\"|g' | expand -t1 | tr '\n' ' ' | sed 's|  *| |g' )"'"
    }'

  CURL_STATUS=$( curl -s -o /tmp/curl.response -w %{http_code} \
                  -X "POST" "http://localhost:${REGISTRY_PORT}/subjects/${SCHEMA_SUBJECT}/versions" \
                  -H 'Accept: application/vnd.schemaregistry.v1+json, application/vnd.schemaregistry+json, application/json' \
                  -H 'Content-Type: application/vnd.schemaregistry.v1+json' \
                  -d "${CURL_PAYLOAD}" )

  if [[ "${CURL_STATUS}" != '200' ]]; then
    log "Error: Upload has failed for ${SCHEMA_SUBJECT} schema definition, got ${CURL_STATUS} response code."
    log "Error details: $( cat /tmp/curl.response )"
    return 1
  fi

  log "Upload has succeeded for ${SCHEMA_SUBJECT} schema definition"

  return 0
}

# Schema config file upload function.
uploadSchemaConfig() {
  local SCHEMA_DIR="$1"

  # Check for schema config file in the directory.
  if [[ ! -f "${SCHEMA_DIR}/config.json" ]]; then
    log "Error: No config.json file in the ${SCHEMA_DIR} directory"
    return 1
  fi

  # Set schema subject.
  SCHEMA_SUBJECT="${SCHEMA_DIR##*/}"

  # Upload schema config file.
  log "Uploading ${SCHEMA_SUBJECT} schema config"

  # Remove schemaType from the config.json file to avoid conflict with the schemaType on upload.
  CURL_PAYLOAD=$( jq 'del(.schemaType)' "${SCHEMA_DIR}/config.json" )

  CURL_STATUS=$( curl -s -o /tmp/curl.response -w %{http_code} \
                  -X "PUT" "http://localhost:${REGISTRY_PORT}/config/${SCHEMA_SUBJECT}" \
                  -H 'Accept: application/vnd.schemaregistry.v1+json, application/vnd.schemaregistry+json, application/json' \
                  -H 'Content-Type: application/vnd.schemaregistry.v1+json' \
                  -d "${CURL_PAYLOAD}" )

  if [[ "${CURL_STATUS}" != '200' ]]; then
    log "Error: Upload has failed for ${SCHEMA_SUBJECT} schema config, got ${CURL_STATUS} response code."
    log "Error details: $( cat /tmp/curl.response )"
    return 1
  fi

  log "Upload has succeeded for ${SCHEMA_SUBJECT} schema config"

  return 0
}

# Wait for schema-registry initialization.
log 'Waiting for schema-registry to start...'
while [[ true ]]; do
  CURL_STATUS=$( curl -s -o /dev/null -w %{http_code} "http://localhost:${REGISTRY_PORT}/subjects" )
  if [[ "${CURL_STATUS}" == '200' ]]; then
    log 'Schema-registry has started'
    break
  fi
  log "Schema-registry listener HTTP state: ${CURL_STATUS}. Waiting for 200..."
  sleep 5
done

# Configure schema-registry runtime settings.
log 'Configuring schema-registry settings'
enableReadWriteMode
if [[ $? -ne 0 ]]; then
  log 'Failed to enable read-write mode for schema-registry.'
  exit 1
fi

# Process schema definition files.
log 'Processing shared schema definition files'
for SCHEMA_DIR in $( find /home/appuser/schemas/shared -mindepth 1 -maxdepth 1 -type d ); do
  uploadSchemaConfig "${SCHEMA_DIR}"
  if [[ $? -ne 0 ]]; then
    UPLOAD_SUCCESSFUL='false'
    continue
  fi

  uploadSchemaDefinition "${SCHEMA_DIR}"
  if [[ $? -ne 0 ]]; then
    UPLOAD_SUCCESSFUL='false'
  fi
done

if [[ -d "/home/appuser/schemas/${Environment}" ]]; then
  log "Processing ${Environment} environment schema definition files"
  for SCHEMA_DIR in $( find "/home/appuser/schemas/${Environment}" -mindepth 1 -maxdepth 1 -type d ); do
    uploadSchemaConfig "${SCHEMA_DIR}"
    if [[ $? -ne 0 ]]; then
      UPLOAD_SUCCESSFUL='false'
      continue
    fi

    uploadSchemaDefinition "${SCHEMA_DIR}"
    if [[ $? -ne 0 ]]; then
      UPLOAD_SUCCESSFUL='false'
    fi
  done
fi

if [[ "${UPLOAD_SUCCESSFUL}" != 'true' ]]; then
  log 'Schema definitions and configs upload has finished with errors. Check the above logs to find the details.'
  exit 1
fi

# Create the success flag file for the healthcheck script.
log 'Schema definitions and configs upload has finished successfully'
touch /home/appuser/upload-schemas.succeeded
