#!/usr/bin/env bash
#
# Copyright (c) 2023-2025, 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.
#

SCRIPT_PATH="$(
  cd "$(dirname "$0")" >/dev/null 2>&1 || exit
  pwd -P
)"

# Defaults for the script inputs
CMA_APP_DATA_DIR=${CMA_APP_DATA_DIR:-${HOME}/.cma}

CMA_DIST_TYPE=${CMA_DIST_TYPE:-distributed}
export CMA_DIST_TYPE
export CMA_STACK_NAME=${CMA_STACK_NAME:-cma}

DOCKER_OS=rhel
DEFAULT_CMA_DOCKER_IMAGE_VERSION=latest
DOCKER_HOST_PORT=8090
PYPI_WEBSERVER_PORT=9003
DOCKER_CONTAINER_NAME=cma-server
DOCKER_EXTRA_ARGS=

AIRGAPPED=false

args=("${@}")
for i in "${!args[@]}"; do

  if [ "${skip_next}" = true ]; then
    skip_next=false
    continue
  fi

  case ${args[i]} in
  start | --start)
    if [ "${RUN_SSL_SETUP}" = true ]; then
      echo "'$1' conflicts with SSL setup action."
      HELP=true
    else
      ACTION_START=true
      RUN_SSL_SETUP=false
    fi
    unset "args[i]"
    ;;
  stop | --stop)
    if [ "${RUN_SSL_SETUP}" = true ]; then
      echo "'$1' conflicts with SSL setup action."
      HELP=true
    else
      ACTION_STOP=true
      RUN_SSL_SETUP=false
    fi
    unset "args[i]"
    ;;
  restart | --restart)
    if [ "${RUN_SSL_SETUP}" = true ]; then
      echo "'$1' conflicts with SSL setup action."
      HELP=true
    else
      ACTION_STOP=true
      ACTION_START=true
      RUN_SSL_SETUP=false
    fi
    unset "args[i]"
    ;;
  # setup is coming from agent setup script, the meaning is the same as rebuild
  rebuild | --rebuild | setup)
    if [ "${RUN_SSL_SETUP}" = true ]; then
      echo "'$1' conflicts with SSL setup action."
      HELP=true
    else
      ACTION_REBUILD=true
      RUN_SSL_SETUP=false
    fi
    unset "args[i]"
    ;;
  ssl)
    if [ "${RUN_SSL_SETUP}" = false ]; then
      echo "'$1' conflicts with star/stop/restart/rebuild actions."
      HELP=true
    else
      RUN_SSL_SETUP=true
    fi
    unset "args[i]"
    ;;
  -s | --service-type)
    CMA_SERVICE_TYPE="${args[i+1]}"
    if [[ ! "${CMA_SERVICE_TYPE}" =~ ^(master|server|agent)$ ]]; then
      echo "Invalid service type: ${CMA_SERVICE_TYPE}. Valid types are: master, server, agent."
      HELP=true
    fi
    skip_next=true
    ;;
  -os=* | --docker-os=*)
    DOCKER_OS=${args[i]#*=}
    ;;
  -os | --docker-os)
    DOCKER_OS="${args[i+1]}"
    skip_next=true
    ;;
  -iv=* | --image-version=*)
    CMA_DOCKER_IMAGE_VERSION=${args[i]#*=}
    ;;
  -iv | --image-version)
    CMA_DOCKER_IMAGE_VERSION="${args[i+1]}"
    skip_next=true
    ;;
  -P=* | --host-port=*)
    DOCKER_HOST_PORT=${args[i]#*=}
    ;;
  -P | --host-port)
    DOCKER_HOST_PORT="${args[i+1]}"
    skip_next=true
    ;;
  --skip-host-port-check)
    CMA_SKIP_HOST_PORT_CHECK=true
    ;;
  # TODO remove this option after GH check is changed
  --ssl)
    CMA_SERVER_SSL=true
    ;;
  --ldap)
    CMA_SERVER_LDAP=true
    ;;
  --airgapped)
    AIRGAPPED=true
    ;;
  --vault)
    CMA_VAULT=true
    ;;
  --db-pass=*)
    CMA_DBA_PASS=${args[i]#*=}
    ;;
  --db-pass)
    CMA_DBA_PASS="${args[i+1]}"
    skip_next=true
    ;;
  --auth-db-pass=*)
    CMA_AUTH_DBA_PASS=${args[i]#*=}
    ;;
  --auth-db-pass)
    CMA_AUTH_DBA_PASS="${args[i+1]}"
    skip_next=true
    ;;
  --client-secret=*)
    CMA_CLIENT_SECRET=${args[i]#*=}
    ;;
  --client-secret)
    CMA_CLIENT_SECRET="${args[i+1]}"
    skip_next=true
    ;;
  --pypi-webserver-port=*)
    PYPI_WEBSERVER_PORT=${args[i]#*=}
    ;;
  --pypi-webserver-port)
    PYPI_WEBSERVER_PORT="${args[i+1]}"
    skip_next=true
    ;;
  --cma-extras-gpl-tar-location=*)
    CMA_EXTRAS_GPL_TAR_LOCATION=${args[i]#*=}
    ;;
  --cma-extras-gpl-tar-location)
    CMA_EXTRAS_GPL_TAR_LOCATION="${args[i+1]}"
    skip_next=true
    ;;
  -n=* | --container-name=* | --instance-name=*)
    DOCKER_CONTAINER_NAME=${args[i]#*=}
    ;;
  -n | --container-name | --instance-name)
    DOCKER_CONTAINER_NAME="${args[i+1]}"
    skip_next=true
    ;;
  -p=* | --profile=*)
    CMA_SERVER_EXTRA_PROFILE=${args[i]#*=}
    ;;
  -p | --profile)
    CMA_SERVER_EXTRA_PROFILE="${args[i+1]}"
    skip_next=true
    ;;
  --env-file=*)
    DOCKER_CONTAINER_ENV_FILE=${args[i]#*=}
    ;;
  --env-file)
    DOCKER_CONTAINER_ENV_FILE="${args[i+1]}"
    skip_next=true
    ;;
  --user=*)
    DOCKER_USER=${args[i]#*=}
    ;;
  --user)
    DOCKER_USER="${args[i+1]}"
    skip_next=true
    ;;
  --network=*)
    CUSTOM_DOCKER_NETWORK=${args[i]#*=}
    ;;
  --network)
    CUSTOM_DOCKER_NETWORK="${args[i+1]}"
    skip_next=true
    ;;
  -ad=* | --host-app-data-dir=* | --app-data-dir=*)
    CMA_APP_DATA_DIR=${args[i]#*=}
    ;;
  -ad | --host-app-data-dir | --app-data-dir)
    CMA_APP_DATA_DIR="${args[i+1]}"
    skip_next=true
    ;;
  --agent-client-id=*)
    CMA_AGENT_CLIENT_ID=${args[i]#*=}
    ;;
  --agent-client-id)
    CMA_AGENT_CLIENT_ID="${args[i+1]}"
    skip_next=true
    ;;
  --agent-client-secret=*)
    CMA_AGENT_CLIENT_SECRET=${args[i]#*=}
    ;;
  --agent-client-secret)
    CMA_AGENT_CLIENT_SECRET="${args[i+1]}"
    skip_next=true
    ;;
  --gateway-url=*)
    CMA_GATEWAY_URL=${args[i]#*=}
    ;;
  --gateway-url)
    CMA_GATEWAY_URL="${args[i+1]}"
    skip_next=true
    ;;
  --master-host=*)
    CMA_MASTER_HOST=${args[i]#*=}
    ;;
  --master-host)
    CMA_MASTER_HOST="${args[i+1]}"
    skip_next=true
    ;;
  --grpc-port=*)
    CMA_MASTER_GRPC_PORT=${args[i]#*=}
    ;;
  --grpc-port)
    CMA_MASTER_GRPC_PORT="${args[i+1]}"
    skip_next=true
    ;;
  --auth-server-uri=*)
    CMA_AUTH_SERVER_URI=${args[i]#*=}
    ;;
  --auth-server-uri)
    CMA_AUTH_SERVER_URI="${args[i+1]}"
    skip_next=true
    ;;
  -h | --help)
    HELP=true
    ;;
  *)
    if [ "${RUN_SSL_SETUP}" = false ]; then
      echo "Unknown option: ${args[i]}"
      HELP=true
    fi
    ;;
  esac
done

DEPRECATED_COMMANDS_MESSAGE="Actions starting with '--' are deprecated and will be removed in future releases. Instead, use them without the '--'."

__usage="
Usage: ${CMA_CLI_COMMAND:-$(basename "$0")} [actions] [options]
Available actions:
   start,     --start:  Start the container
   stop,      --stop: Stop the container
   restart,   --restart: Restart the server
   rebuild,   --rebuild: Rebuild the docker image
   ssl: Enable SSL setup
 **Note $DEPRECATED_COMMANDS_MESSAGE
Options:
   --ssl: Enable ssl for the CMA server (deprecated, will be removed in future releases, use 'ssl' action instead)
   -os, --docker-os: OS to build on (rhel,amazonlinux) (Default: ${DOCKER_OS})
   -iv, --image-version: Set the version tag for the docker image ${DEFAULT_CMA_DOCKER_IMAGE_VERSION})
   -P,  --host-port: Set the host port to which the container port will be mapped (Default: ${DOCKER_HOST_PORT})
                     Special values:
                                    * 0 - in this case, random available port will be selected on host
                                    * -1 - no port publishing will be set up at all
        --skip-host-port-check: Skip host port check. This is not recommended unless the check fails even though the specified host port is not in use by other process.
   -ad, --host-app-data-dir: Set the host folder where configs, logs and data are placed for containers (Default: ${CMA_APP_DATA_DIR}}) (**NOTE app-data-dir is also supported)
   -n,  --container-name: Set the name of the container (Default: ${DOCKER_CONTAINER_NAME}) (**NOTE: --instance-name is also supported)
   -p,  --profile: Set additional profile(s) for the cma-server
        --env-file: Set a file of environment variables for the docker container
        --user: Set the docker user by providing uid:gid
        --network: Name of the docker network to connect the container into (Default: Not specified)
        --gateway-url: CMA Gateway base URL — derives master host, gRPC port, and auth-server-uri automatically (required for external agent)
        --master-host: Override the CMA Master hostname discovered from the gateway (useful when the gateway returns an internal hostname not routable from this agent)
        --grpc-port: Override the CMA Master gRPC port discovered from the gateway
        --auth-server-uri: Override the auth server URI discovered from the gateway
        --agent-client-id: OAuth2 client ID for the CMA Agent (Default: cma-agent)
        --agent-client-secret: OAuth2 client secret for the CMA Agent (auto-generated if not specified)
        --db-pass: Database password (required; prompted interactively if omitted)
        --auth-db-pass: Auth server database password (prompted interactively if omitted; defaults to --db-pass if left empty)
        --client-secret: OAuth2 client secret shared by auth and gateway servers (required; prompted interactively if omitted; persisted across restarts)
        --airgapped: Turn on airgapped mode (meaning: install all pypi deps from cma & cma-extras artifact) (Default: $AIRGAPPED)
        --pypi-webserver-port: Set the host port of the webserver running pypi in the container
        --cma-extras-gpl-tar-location: Location of GPL extras TAR (Default: ROOT_DIR/..) NOTE: this a requirement for airgapped mode!!
   -h,  --help: Print this help
"

if [ "${HELP}" = true ]; then
  if [ "${RUN_SSL_SETUP}" = true ]; then
    source "$SCRIPT_PATH"/common.sh # load commons
    if [ "${CMA_MASTER}" = true ]; then
      service_type="master"
    else
      service_type="server"
    fi
    run_ssl_setup "${service_type}" "docker" "${args[@]}"
  else
    echo "$__usage"
  fi
  exit 0
fi

echo "WARNING: ${DEPRECATED_COMMANDS_MESSAGE}"

export CMA_GATEWAY_URL="${CMA_GATEWAY_URL:-}"
export CMA_MASTER_HOST="${CMA_MASTER_HOST:-}"
export CMA_MASTER_GRPC_PORT="${CMA_MASTER_GRPC_PORT:-}"
export CMA_AUTH_SERVER_URI="${CMA_AUTH_SERVER_URI:-}"

source "$SCRIPT_PATH"/docker-common.sh # load docker commons

if [ "${RUN_SSL_SETUP}" = true ]; then
  if [ "${CMA_MASTER}" = true ]; then
    echo "Running SSL setup for master CMA server"
    run_ssl_setup "master" "docker" "${args[@]}"
  else
    echo "Running SSL setup for local CMA server"
    run_ssl_setup "server" "docker" "${args[@]}"
  fi
  exit $?
fi

export CMA_INSTANCE_NAME="${CMA_INSTANCE_NAME:-${DOCKER_CONTAINER_NAME}}"

export CMA_SERVICE_TYPE
export CMA_DOCKER_IMAGE_VERSION

if [ "${ACTION_STOP}" = true ]; then
  if [ -z "${ACTIVE_PROFILES}" ]; then
    # if ACTIVE_PROFILES is not set, try to read it from cma-server.properties
    if [ -f "${CMA_SERVER_CONF_FILE}" ]; then
      # read the active profiles from cma-server.properties
      ACTIVE_PROFILES=$(get_cma_conf_value "cma.server.profiles" "${CMA_SERVER_CONF_FILE}")
    else
      echo "CMA Server configuration file not found: ${CMA_SERVER_CONF_FILE}"
      ACTIVE_PROFILES=$(get_server_profiles)
    fi
    export ACTIVE_PROFILES
    echo "Active profiles: ${ACTIVE_PROFILES}"
    UNSET_ACTIVE_PROFILES=true
  fi

  if [ -n "${CMA_SERVICE_TYPE}" ]; then
    "stop_${CMA_SERVICE_TYPE}"
  else
    "stop_${CMA_DIST_TYPE}"
  fi

  if [ "${UNSET_ACTIVE_PROFILES}" = true ]; then
    # unset ACTIVE_PROFILES to be recalculated on next start
    unset ACTIVE_PROFILES
  fi
fi

if [ "${ACTION_REBUILD}" = true ]; then
  rebuild_image
fi


if [ "${ACTION_START}" = true ]; then

  update_server_profiles

  if [ -z "${ACTIVE_PROFILES}" ]; then
    if [ -f "${CMA_SERVER_CONF_FILE}" ]; then
      # read the active profiles from cma-server.properties
      ACTIVE_PROFILES=$(get_cma_conf_value "cma.server.profiles" "${CMA_SERVER_CONF_FILE}")
    else
      echo "CMA Server configuration file not found: ${CMA_SERVER_CONF_FILE}"
      ACTIVE_PROFILES=$(get_server_profiles)
    fi
    export ACTIVE_PROFILES
    echo "Active profiles: ${ACTIVE_PROFILES}"
  fi


  export CMA_INSTANCE_NAME=${CMA_INSTANCE_NAME:-${DOCKER_CONTAINER_NAME:-cma-server}}
  export ACTIVE_PROFILES=${ACTIVE_PROFILES:-$(get_cma_conf_value "cma.server.profiles")}

  # Write env file before docker compose starts — the container entrypoint
  # chowns bind-mounted dirs to UID 1001, making them unwritable by the host user.
  write_env_file "${ENV_FILE}"

  if [ -n "${CMA_SERVICE_TYPE}" ]; then
    "start_${CMA_SERVICE_TYPE}"
  else
    "start_${CMA_DIST_TYPE}"
  fi

fi
