#!/usr/bin/env bash
set -euo pipefail

NAMESPACE="pcp-dev"
POSTGRES_POD="pcp-postgres-0"

validate_db_name() {
  local db_name="$1"

  if [[ ! "$db_name" =~ ^[a-z][a-z0-9_]*$ ]]; then
    echo "ERROR: invalid database name: $db_name" >&2
    echo "Allowed: lowercase letters, digits, underscore; must start with a letter." >&2
    exit 1
  fi
}

secret_name_for_db() {
  local db_name="$1"
  echo "${db_name//_/-}-db"
}

user_name_for_db() {
  local db_name="$1"
  echo "${db_name}_user"
}

get_or_create_password() {
  local secret_name="$1"

  if kubectl -n "$NAMESPACE" get secret "$secret_name" >/dev/null 2>&1; then
    kubectl -n "$NAMESPACE" get secret "$secret_name" \
      -o jsonpath='{.data.SPRING_DATASOURCE_PASSWORD}' | base64 -d
  else
    openssl rand -base64 32 | tr -d '/+=' | head -c 32
  fi
}

create_db_user_and_secret() {
  local db_name="$1"

  validate_db_name "$db_name"

  local db_user
  local secret_name
  local db_password

  db_user="$(user_name_for_db "$db_name")"
  secret_name="$(secret_name_for_db "$db_name")"
  db_password="$(get_or_create_password "$secret_name")"

  echo
  echo "============================================================"
  echo "Creating database package"
  echo "  database: $db_name"
  echo "  user:     $db_user"
  echo "  secret:   $secret_name"
  echo "============================================================"

  echo "1/4 Create or update PostgreSQL user and database"

  kubectl -n "$NAMESPACE" exec -i "$POSTGRES_POD" -- psql \
    -U postgres \
    -d postgres <<SQL
DO \$\$
BEGIN
  IF NOT EXISTS (
    SELECT FROM pg_roles WHERE rolname = '$db_user'
  ) THEN
    CREATE ROLE "$db_user" LOGIN PASSWORD '$db_password';
  ELSE
    ALTER ROLE "$db_user" WITH LOGIN PASSWORD '$db_password';
  END IF;
END
\$\$;

SELECT 'CREATE DATABASE "$db_name" OWNER "$db_user"'
WHERE NOT EXISTS (
  SELECT FROM pg_database WHERE datname = '$db_name'
) \gexec

ALTER DATABASE "$db_name" OWNER TO "$db_user";
GRANT CONNECT ON DATABASE "$db_name" TO "$db_user";
SQL

  echo "2/4 Enable PostGIS"

  kubectl -n "$NAMESPACE" exec -i "$POSTGRES_POD" -- psql \
    -U postgres \
    -d "$db_name" <<SQL
CREATE EXTENSION IF NOT EXISTS postgis;
CREATE EXTENSION IF NOT EXISTS postgis_topology;

ALTER SCHEMA public OWNER TO "$db_user";
GRANT USAGE, CREATE ON SCHEMA public TO "$db_user";
SQL

  echo "3/4 Create or update Kubernetes Secret"

  kubectl -n "$NAMESPACE" create secret generic "$secret_name" \
    --from-literal=SPRING_DATASOURCE_USERNAME="$db_user" \
    --from-literal=SPRING_DATASOURCE_PASSWORD="$db_password" \
    --dry-run=client -o yaml | kubectl apply -f -

  echo "4/4 Check connection and PostGIS"

  kubectl -n "$NAMESPACE" exec -i "$POSTGRES_POD" -- env PGPASSWORD="$db_password" psql \
    -h localhost \
    -U "$db_user" \
    -d "$db_name" \
    -c 'select current_database(), current_user, postgis_full_version();'

  echo "Done: $db_name"
}

if [[ "$#" -eq 0 ]]; then
  echo "Usage: $0 <db_name> [db_name...]"
  exit 1
fi

for db_name in "$@"; do
  create_db_user_and_secret "$db_name"
done

echo
echo "All requested databases processed."
