#!/usr/bin/env bash
#
# Copyright (c) 2026, Cloudera, Inc. All Rights Reserved.
#
# 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.
#

#
# One-time setup script: creates CMA databases and users in a MySQL instance.
#
# Usage:
#   ./setup-cma-mysql.sh --host <mysql-host> --port <mysql-port> --admin-user <superuser> --admin-password <password>
#   ./setup-cma-mysql.sh --host <mysql-host> --admin-user root --admin-password <password>
#
# The script creates:
#   - Database 'cma' with user 'cma'
#   - Database 'cma_auth' with user 'cma' (shared user by default, or separate 'cma_auth' user with --auth-user)
#   - Database 'cma_agent' with user 'cma_agent'
#
# After running this script, configure CMA in Cloudera Manager:
#   Database Type = mysql
#   Database Host = <mysql-host>
#   Database User = cma          (for CMA Master)
#   Database User = cma_agent    (for CMA Agent)
#

set -euo pipefail

MY_HOST=""
MY_PORT="3306"
MY_ADMIN_USER=""
MY_ADMIN_PASS=""
CMA_DB_USER="cma"
CMA_DB_PASS=""
CMA_AUTH_DB_USER=""
CMA_AUTH_DB_PASS=""
CMA_AGENT_DB_USER="cma_agent"
CMA_AGENT_DB_PASS=""

usage() {
  echo "Usage: $(basename "$0") --host <mysql-host> --admin-user <superuser> --admin-password <password> [options]"
  echo ""
  echo "Creates CMA databases and users in a MySQL instance."
  echo ""
  echo "Required:"
  echo "  --host              MySQL hostname or IP"
  echo "  --admin-user        MySQL superuser (e.g. root)"
  echo "  --admin-password    MySQL superuser password"
  echo ""
  echo "Optional:"
  echo "  --port              MySQL port (default: 3306)"
  echo "  --cma-user          CMA Master database user (default: cma)"
  echo "  --cma-password      CMA Master database user password (auto-generated if omitted)"
  echo "  --auth-user         CMA Auth database user (default: same as --cma-user)"
  echo "  --auth-password     CMA Auth database user password (default: same as --cma-password)"
  echo "  --agent-user        CMA Agent database user (default: cma_agent)"
  echo "  --agent-password    CMA Agent database user password (auto-generated if omitted)"
  echo "  -h, --help          Show this help message"
}

# Parse arguments
while [[ $# -gt 0 ]]; do
  case $1 in
    --host)            MY_HOST="$2"; shift 2 ;;
    --host=*)          MY_HOST="${1#*=}"; shift ;;
    --port)            MY_PORT="$2"; shift 2 ;;
    --port=*)          MY_PORT="${1#*=}"; shift ;;
    --admin-user)      MY_ADMIN_USER="$2"; shift 2 ;;
    --admin-user=*)    MY_ADMIN_USER="${1#*=}"; shift ;;
    --admin-password)  MY_ADMIN_PASS="$2"; shift 2 ;;
    --admin-password=*) MY_ADMIN_PASS="${1#*=}"; shift ;;
    --cma-user)        CMA_DB_USER="$2"; shift 2 ;;
    --cma-user=*)      CMA_DB_USER="${1#*=}"; shift ;;
    --cma-password)    CMA_DB_PASS="$2"; shift 2 ;;
    --cma-password=*)  CMA_DB_PASS="${1#*=}"; shift ;;
    --auth-user)       CMA_AUTH_DB_USER="$2"; shift 2 ;;
    --auth-user=*)     CMA_AUTH_DB_USER="${1#*=}"; shift ;;
    --auth-password)   CMA_AUTH_DB_PASS="$2"; shift 2 ;;
    --auth-password=*) CMA_AUTH_DB_PASS="${1#*=}"; shift ;;
    --agent-user)      CMA_AGENT_DB_USER="$2"; shift 2 ;;
    --agent-user=*)    CMA_AGENT_DB_USER="${1#*=}"; shift ;;
    --agent-password)  CMA_AGENT_DB_PASS="$2"; shift 2 ;;
    --agent-password=*) CMA_AGENT_DB_PASS="${1#*=}"; shift ;;
    -h|--help)         usage; exit 0 ;;
    *)                 echo "Unknown option: $1"; usage; exit 1 ;;
  esac
done

# Validate required args
if [ -z "$MY_HOST" ] || [ -z "$MY_ADMIN_USER" ] || [ -z "$MY_ADMIN_PASS" ]; then
  echo "ERROR: --host, --admin-user, and --admin-password are required."
  echo ""
  usage
  exit 1
fi

# Auto-generate passwords if not provided
generate_password() {
  openssl rand -base64 24 2>/dev/null || head -c 32 /dev/urandom | base64 | tr -d '/+=' | head -c 24
}

if [ -z "$CMA_DB_PASS" ]; then
  CMA_DB_PASS=$(generate_password)
fi
if [ -z "$CMA_AUTH_DB_USER" ]; then
  CMA_AUTH_DB_USER="$CMA_DB_USER"
fi
if [ -z "$CMA_AUTH_DB_PASS" ]; then
  CMA_AUTH_DB_PASS="$CMA_DB_PASS"
fi
if [ -z "$CMA_AGENT_DB_PASS" ]; then
  CMA_AGENT_DB_PASS=$(generate_password)
fi

# Verify mysql client is available
if ! command -v mysql &>/dev/null; then
  echo "ERROR: mysql command not found. Install the MySQL client:"
  echo "  yum install mysql  # RHEL/CentOS"
  echo "  apt install mysql-client  # Debian/Ubuntu"
  exit 1
fi

MYSQL_CMD=(mysql -h "${MY_HOST}" -P "${MY_PORT}" -u "${MY_ADMIN_USER}" "-p${MY_ADMIN_PASS}" --batch --skip-column-names)

# Test connection
echo "Connecting to MySQL at ${MY_HOST}:${MY_PORT} as ${MY_ADMIN_USER}..."
if ! "${MYSQL_CMD[@]}" -e "SELECT 1" &>/dev/null; then
  echo "ERROR: Cannot connect to MySQL at ${MY_HOST}:${MY_PORT} as ${MY_ADMIN_USER}."
  echo "Verify the host, port, and credentials."
  exit 1
fi
echo "Connection verified."

# Escape single quotes for safe SQL string interpolation (' -> '')
sql_escape() {
  echo "${1//\'/\'\'}"
}

# Create user if not exists, or update password
create_user() {
  local db_user="$1"
  local db_pass
  db_pass=$(sql_escape "$2")
  local user_exists
  user_exists=$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM mysql.user WHERE user = '${db_user}' AND host = '%'")
  if [ "$user_exists" -gt 0 ]; then
    echo "User '${db_user}' already exists, updating password."
    "${MYSQL_CMD[@]}" -e "ALTER USER '${db_user}'@'%' IDENTIFIED BY '${db_pass}';"
  else
    echo "Creating user '${db_user}'..."
    "${MYSQL_CMD[@]}" -e "CREATE USER '${db_user}'@'%' IDENTIFIED BY '${db_pass}';"
  fi
}

# Create database if not exists, grant privileges
create_db() {
  local db_name="$1"
  local db_owner="$2"
  local db_exists
  db_exists=$("${MYSQL_CMD[@]}" -e "SELECT COUNT(*) FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = '${db_name}'")
  if [ "$db_exists" -gt 0 ]; then
    echo "Database '${db_name}' already exists, skipping creation."
  else
    echo "Creating database '${db_name}'..."
    "${MYSQL_CMD[@]}" -e "CREATE DATABASE \`${db_name}\` CHARACTER SET utf8mb3 COLLATE utf8mb3_unicode_ci;"
  fi
  "${MYSQL_CMD[@]}" -e "GRANT ALL PRIVILEGES ON \`${db_name}\`.* TO '${db_owner}'@'%';"
  "${MYSQL_CMD[@]}" -e "FLUSH PRIVILEGES;"
}

# Create CMA Master user and database
create_user "$CMA_DB_USER" "$CMA_DB_PASS"
create_db "cma" "$CMA_DB_USER"

# Create CMA Auth user and database (may be same user as Master)
if [ "$CMA_AUTH_DB_USER" != "$CMA_DB_USER" ]; then
  create_user "$CMA_AUTH_DB_USER" "$CMA_AUTH_DB_PASS"
fi
create_db "cma_auth" "$CMA_AUTH_DB_USER"

# Create CMA Agent user and database
create_user "$CMA_AGENT_DB_USER" "$CMA_AGENT_DB_PASS"
create_db "cma_agent" "$CMA_AGENT_DB_USER"

mask_password() {
  local pass="$1"
  if [ ${#pass} -le 4 ]; then
    echo "****"
  else
    echo "${pass:0:2}$(printf '*%.0s' $(seq 1 $((${#pass} - 4))))${pass: -2}"
  fi
}

echo ""
echo "======================================"
echo "CMA MySQL setup complete!"
echo "======================================"
echo ""
echo "CMA Master database:"
echo "  Database: cma"
echo "  User:     ${CMA_DB_USER}"
echo "  Password: $(mask_password "${CMA_DB_PASS}")"
echo ""
echo "CMA Auth database:"
echo "  Database: cma_auth"
echo "  User:     ${CMA_AUTH_DB_USER}"
echo "  Password: $(mask_password "${CMA_AUTH_DB_PASS}")"
if [ "$CMA_AUTH_DB_USER" = "$CMA_DB_USER" ]; then
  echo "  (shared with CMA Master user)"
fi
echo ""
echo "CMA Agent database:"
echo "  Database: cma_agent"
echo "  User:     ${CMA_AGENT_DB_USER}"
echo "  Password: $(mask_password "${CMA_AGENT_DB_PASS}")"
echo ""
echo "Configure in Cloudera Manager:"
echo "  CMA Master service:"
echo "    Database Type          = mysql"
echo "    Database Host          = ${MY_HOST}"
echo "    Database Port          = ${MY_PORT}"
echo "    Database User          = ${CMA_DB_USER}"
echo "    Database Password      = <use the password shown above>"
if [ "$CMA_AUTH_DB_USER" != "$CMA_DB_USER" ]; then
  echo "    Auth Database User     = ${CMA_AUTH_DB_USER}"
  echo "    Auth Database Password = <use the password shown above>"
fi
echo ""
echo "  CMA Agent service:"
echo "    Database Type          = mysql"
echo "    Database Host          = ${MY_HOST}"
echo "    Database Port          = ${MY_PORT}"
echo "    Database User          = ${CMA_AGENT_DB_USER}"
echo "    Database Password      = <use the password shown above>"
echo ""
echo "IMPORTANT: Save these passwords securely. They will not be shown again."
