#!/bin/bash
set -e

# Colors & icons
YELLOW='\033[1;93m'; CYAN='\033[1;96m'; GREEN='\033[1;92m'; RED='\033[1;91m'; NC='\033[0m'
CHECK="\033[1;92m✅\033[0m"; ERROR="\033[1;91m❌\033[0m"; ARROW="\033[1;93m➡️\033[0m"

# Header function
print_header() {
  printf "${YELLOW}----------------------------------------------------${NC}\n"
  printf "$1\n"
  printf "${YELLOW}----------------------------------------------------${NC}\n"
}

#!/bin/bash


echo " "
echo " "
echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
echo -e "\e[1;93mMESSAGE BROKER INSTALLER SCRIPT VERSION 1.0.3 (September 19th, 2025)\e[0m"
echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
echo " "
echo " "


# notes: Text colours: Blue 34, Yellow 33, Bright yellow 93, Magenta 35, red 31, bright red 91.

directory="/etc/exan/config/messagebroker"
loggingdir="/etc/exan/logs"
scriptsdir="/etc/exan/scripts"
installerconfigfullpath="$directory/messagebrokerinstaller.cfg"


confportprod=3020
confporttest=3021


rabbituser="axium"
#rabbitpass=$(LC_ALL=C tr -dc 'A-Za-z0-9!?%=' < /dev/urandom | head -c 12) #Has special chars
rabbitpass=$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom | head -c 12)

confdbtimeout=1200000
ignorepromptforconfig=N

# Kafka message size configuration constants (10MB in bytes)
KAFKA_MESSAGE_MAX_BYTES=10485760
KAFKA_REPLICA_FETCH_MAX_BYTES=10485760
KAFKA_FETCH_MAX_BYTES=10485760
KAFKA_MAX_PARTITION_FETCH_BYTES=10485760

strip_double_slashes_in_path() {
    local input="$1"
    # Replace double slashes with a single slash
    input="${input//\/\//\/}"
    # Replace double backslashes with a single backslash
    input="${input//\\\\/\\}"
	# Remove trailing slashes (either / or \)
    input="${input%/}"
    input="${input%\\}"
    echo "$input"
}

prompt_for_value() {
    local config_key=$1
    local default_value=$2

    # If config file exists, try to read the value from it
    if [[ -f $installerconfigfullpath ]]; then
        local current_value=$(grep "^$config_key=" "$installerconfigfullpath" | cut -d'=' -f2-)
        if [[ -n "$current_value" ]]; then
            default_value=$current_value
        fi
    fi

    # Prompt user for input, prepopulate with default_value if available
    read -r -e -i "$default_value" user_input

    # If user input is empty, use the default_value
    if [[ -z "$user_input" ]]; then
        user_input=$default_value
    fi

    # Use sed to replace the line with the config_key or add it if it doesn't exist
    if grep -q "^$config_key=" "$installerconfigfullpath"; then
        # If key exists, replace the value
        sed -i "s|^$config_key=.*|$config_key=$user_input|" "$installerconfigfullpath"
    else
        # If key doesn't exist, add it
        echo "$config_key=$user_input" >> "$installerconfigfullpath"
    fi
	
	echo "$user_input"
}

check_docker_installed() {

	echo " "
	echo " "
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mChecking pre-requisites: Docker \e[0m"
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "

    if command -v docker >/dev/null 2>&1; then
        echo "Docker is installed:"
        docker --version
		IS_DOCKER_INSTALLED="Y"
    else
        echo "Docker is not installed"
		IS_DOCKER_INSTALLED="N"
		IS_DOCKER_CONTAINER_REGISTRY_SAVED="N"
    fi
}


check_pass_packages_installed_rhel() {
	echo " "
	echo " "
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mChecking pre-requisites (RHEL): Pass Packages \e[0m"
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "
	
	local missing=()
	#gnupg2 and golang packages are default installed in RHEL 9
    local dependencies=(pass git make go jq)
	
	
    for cmd in "${dependencies[@]}"; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            missing+=("$cmd")
        fi
    done

    if [ ${#missing[@]} -ne 0 ]; then
        echo "Missing dependencies: ${missing[*]}"
		IS_PASS_PACKAGES_INSTALLED="N"
    else
        echo "All dependencies are installed."
        IS_PASS_PACKAGES_INSTALLED="Y"
    fi
}

check_pass_packages_installed_ubuntu() {
	echo " "
	echo " "
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mChecking pre-requisites (Ubuntu): Pass Packages \e[0m"
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "
	
	local missing=()
    local dependencies=(pass jq)
	
	#golang-docker-credential-helpers doesnt work in this for loop?
    for cmd in "${dependencies[@]}"; do
        if ! command -v "$cmd" >/dev/null 2>&1; then
            missing+=("$cmd")
        fi
    done

    if [ ${#missing[@]} -ne 0 ]; then
        echo "Missing dependencies: ${missing[*]}"
		IS_PASS_PACKAGES_INSTALLED="N"
    else
        echo "All dependencies are installed."
        IS_PASS_PACKAGES_INSTALLED="Y"
    fi
}

check_docker_container_registry_saved() {

	echo " "
	echo " "
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mChecking pre-requisites: Valid working Docker Registry Credentials \e[0m"
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "

	# Validate Docker credentials by attempting to authenticate
	echo "[*] Validating Docker login for registry.gitlab.com..."
	output=$(sudo docker-credential-pass list 2>/dev/null)
	status=$?
	
	if [ $status -ne 0 ]; then
		echo "Unable to retrieve any saved credentials, exit status $status."
		IS_DOCKER_CREDENTIALS_VALID=N
		return
	fi
	
	if [[ "$output" == "{}" ]]; then
		echo "Credential store is empty."
		IS_DOCKER_CREDENTIALS_VALID=N
		return
	fi
	
	sudo docker login registry.gitlab.com
	status=$?
	if [ $status -ne 0 ]; then
		echo "Docker container registry credentials failed with exit status $status."
		IS_DOCKER_CREDENTIALS_VALID=N
		return
	fi
	
	IS_DOCKER_CREDENTIALS_VALID=Y
	
}


check_OS() {

	echo " "
	echo " "
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mVerifying compatible environment\e[0m"
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "
	# Check if /etc/os-release exists
	if [ -f /etc/os-release ]; then
		. /etc/os-release
		OS_NAME=$ID
		OS_PRETTY_NAME=$PRETTY_NAME
		OS_VERSION=$VERSION_ID
		OS_CODENAME=$VERSION_CODENAME
	else
		echo "Cannot determine OS: /etc/os-release not found."
		exit 1
	fi

	# Display OS details
	echo "Detected OS: $OS_PRETTY_NAME"
	echo "OS ID: $OS_NAME"
	echo "Version: $OS_VERSION"
	if [ -n "$OS_CODENAME" ]; then
		echo "Codename: $OS_CODENAME"
	fi

	# Additional logic for specific OS types
	case "$OS_NAME" in
		ubuntu)
			echo "This is Ubuntu Linux."
			;;
		debian)
			echo "This is Debian Linux."
			;;
		rhel | redhat)
			echo "This is Red Hat Enterprise Linux."
			;;
		centos)
			echo "This is CentOS. not compatible, exiting."
			exit 1
			;;
		*)
			echo "Unknown or unsupported OS: $OS_NAME"
			;;
	esac

}


summarize_prereq() {
	echo " "
	echo " "
	echo -e "\e[1;95m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mPre-installation summary\e[0m"
	echo -e "\e[1;95m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "
	echo "Operating System (OS): $OS_NAME $OS_VERSION"
	echo "Docker Installation: $IS_DOCKER_INSTALLED"
	echo "Pass Packages: $IS_PASS_PACKAGES_INSTALLED"
	echo "Docker Container Registry saved credentials: $IS_DOCKER_CREDENTIALS_VALID"
	echo "Existing Message Broker configuration file: $IS_EXISTING_CONFIGURATION"
	
	echo -e "\e[1;95m-------------------------------------------------------------------\e[0m"

	
	if [ "$IS_DOCKER_INSTALLED" = "N" ] || [ "$IS_PASS_PACKAGES_INSTALLED" = "N" ] || [ "$IS_DOCKER_CREDENTIALS_VALID" = "N" ]; then
		echo "Attempting to install or update pre-requisites now..."
	fi
	read -p "Press Enter to continue..."
}

check_existing_config() {

#if config folder doesn't exist, create it
if [ ! -d "$directory" ]; then
  sudo mkdir -p "$directory"
fi

#if config file doesn't exist, create it
if [ ! -f "$installerconfigfullpath" ]; then
    sudo touch "$installerconfigfullpath"
fi

if [ ! -s "$installerconfigfullpath" ]; then
  IS_EXISTING_CONFIGURATION="N"
else
  IS_EXISTING_CONFIGURATION="Y"
fi

} 


install_docker_for_ubuntu() {
echo -e "\e[1;93mAttempting Docker Install.\e[0m"

	dockerinstall=Y;

	sudo apt-get update
	 
	sudo apt-get install ca-certificates curl gnupg
	 
	sudo apt install docker.io

	{
	dockercheck=$(docker -v | cut -d " " -f3)
	} || {
	dockercheck="FAILURE"
	}

	if [ "$dockercheck" = "" ]; then
	dockercheck="FAILURE"
	fi
	if [ "$dockercheck" = "FAILURE" ]; then
	echo -e "\e[1;91mDocker install failed.\e[0m"
	echo -e "\e[1;91mPlease install Docker and try again.\e[0m"
	echo -e "\e[1;91mEXITING SCRIPT...\e[0m"
	echo " "
	echo " "
	echo " "
	exit
	#Install succeeded - wait for processes and daemons to start.
	else
	if [ "$dockerinstall" = "Y" ]; then
	echo -e "\e[1;96mStarting Processes...\e[0m"
	sleep 15
	fi
	echo -e "\e[1;96mDocker installation Successful.\e[0m"
	echo -e "\e[1;96mDocker version = $dockercheck\e[0m"
	echo -e "\e[1;96mProceeding...\e[0m"
	fi
}


install_docker_for_rhel() {

sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# Install Docker Engine
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# Enable and start Docker
sudo systemctl enable --now docker

if systemctl is-active --quiet docker; then
  echo "Docker has been successfully installed and is running."
else
  echo "Docker installation completed, but the service is not running. Please check the logs."
  echo "Try these three commands:"
  echo "journalctl -u docker.service --no-pager"
  echo "journalctl -xe --no-pager"
  echo "docker info"
  exit 1
fi
}

install_pass_packages_for_rhel() {
echo "Attempting to install pass packages..."
local dependencies=(pass gnupg2 git make go jq golang)

sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm
sudo dnf makecache
sudo dnf install -y "${dependencies[@]}"


echo "Attempt to install pass packages complete, setting up keyring"

echo ">>> Generating GPG key for root (if not already present)..."
if ! sudo gpg --batch --list-secret-keys | grep -q 'sec'; then
  cat > /tmp/root-gpg-batch <<EOF
%no-protection
%transient-key
Key-Type: 1
Key-Length: 2048
Name-Real: "axium"
Name-Email: "axium@exansoftware.com"
Expire-Date: 0
%commit
EOF
  sudo gpg --batch --gen-key /tmp/root-gpg-batch
  rm -f /tmp/root-gpg-batch
else
  echo "Root GPG key already exists."
fi

GPG_KEY_ID=$(sudo gpg --list-secret-keys --with-colons | grep '^sec' | head -n1 | cut -d: -f5)
echo ">>> Using GPG Key ID: $GPG_KEY_ID"

echo ">>> Initializing pass for root..."
sudo pass init "$GPG_KEY_ID"

echo ">>> Installing docker-credential-pass..."
if ! command -v docker-credential-pass >/dev/null; then
  TMP_DIR=$(mktemp -d)
  git clone https://github.com/docker/docker-credential-helpers.git "$TMP_DIR"
  pushd "$TMP_DIR"
  sudo cd "$TMP_DIR"
  sudo make pass
  ls -R
  sudo cp bin/build/docker-credential-pass /usr/bin/
  popd
  rm -rf "$TMP_DIR"
else
  echo "docker-credential-pass is already installed."
fi




#echo ">>> Saving Docker registry credentials to pass..."
#CRED_JSON=$(jq -n --arg u "$gituser" --arg p "$gitpass" '{"Username":$u,"Secret":$p}')
#echo "$CRED_JSON" | sudo pass insert -m "docker/registry.gitlab.com"

echo ">>> Configuring Docker for root to use pass..."
DOCKER_CONFIG="/root/.docker/config.json"
sudo mkdir -p "$(dirname "$DOCKER_CONFIG")"
if [[ ! -f "$DOCKER_CONFIG" ]]; then
  echo '{}' | sudo tee "$DOCKER_CONFIG" > /dev/null
fi

if ! sudo jq -e '.credsStore == "pass"' "$DOCKER_CONFIG" > /dev/null 2>&1; then
  sudo jq '. + { "credsStore": "pass" }' "$DOCKER_CONFIG" > /tmp/docker_config.json
  sudo mv /tmp/docker_config.json "$DOCKER_CONFIG"
  echo "Added credsStore: pass to Docker config"
else
  echo "Docker config already uses pass"
fi


}

install_pass_packages_for_ubuntu() {
sudo cat > /tmp/gpg_batch_file <<EOF
%no-protection
%transient-key
Key-Type: 1
Key-Length: 2048
Name-Real: "axium"
Name-Email: "axium@exansoftware.com"
Expire-Date: 0
%commit
EOF
	sudo gpg --batch --gen-key /tmp/gpg_batch_file
	KEY_ID=$(gpg --list-secret-keys --with-colons | grep '^sec' | cut -d: -f5)
	echo -e "Generated GPG Key ID: $KEY_ID"
	sudo rm /tmp/gpg_batch_file
	sudo apt-get -y install pass
	sudo apt install golang-docker-credential-helpers
	sudo apt install jq 
	sudo pass init $KEY_ID

	# Path to Docker config file
	DOCKER_CONFIG="$HOME/.docker/config.json"

	echo ">>> Configuring Docker for root to use pass..."
	DOCKER_CONFIG="/root/.docker/config.json"
	sudo mkdir -p "$(dirname "$DOCKER_CONFIG")"
	if [[ ! -f "$DOCKER_CONFIG" ]]; then
	  echo '{}' | sudo tee "$DOCKER_CONFIG" > /dev/null
	fi

	if ! sudo jq -e '.credsStore == "pass"' "$DOCKER_CONFIG" > /dev/null 2>&1; then
	  sudo jq '. + { "credsStore": "pass" }' "$DOCKER_CONFIG" > /tmp/docker_config.json
	  sudo mv /tmp/docker_config.json "$DOCKER_CONFIG"
	  echo "Added credsStore: pass to Docker config"
	else
	  echo "Docker config already uses pass"
	fi
}



setup_docker_credentials() {

	echo " "
	echo " "
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo -e "\e[1;93mSetting up docker credentials \e[0m"
	echo -e "\e[1;93m-------------------------------------------------------------------\e[0m"
	echo " "
	echo " "

echo "Insert GitLab credentials provided to you by the axiUm team"
	echo -e "\e[1;96mEnter gitlab container registry username:\e[0m"
	echo -e "\e[1;93mEnter [QUIT] to exit.\e[0m"
	read -r gituser
	if [ "$gituser" = "QUIT" ]; then
		echo -e "\e[1;91mEXITING SCRIPT...\e[0m"
		echo " "
		echo " "
		echo " "
		exit
	fi

	echo -e "\e[1;96mEnter gitlab container registry password:\e[0m"
	echo -e "\e[1;93mEnter [QUIT] to exit.\e[0m"
	read -r gitpass

	if [ "$gitpass" = "QUIT" ]; then
		echo -e "\e[1;91mEXITING SCRIPT...\e[0m"
		echo " "
		echo " "
		echo " "
		exit
	fi
	
sudo docker login registry.gitlab.com -u $gituser -p $gitpass

status=$?

	if [ $status -ne 0 ]; then
		echo "Docker container registry credentials failed with exit status. Retry with valid credentials! $status."
		exit 1
	fi

}


# ------------------------------end of all functions--------------------------------------------------

check_OS
check_docker_installed


if [[ "$OS_NAME" == "ubuntu" ]]; then
check_pass_packages_installed_ubuntu
elif [[ "$OS_NAME" == "rhel" ]]; then
check_pass_packages_installed_rhel
fi

# only check the credentials if docker and the pass packages are ready
IS_DOCKER_CREDENTIALS_VALID="N"
if [[ "$IS_DOCKER_INSTALLED" == "Y" && "$IS_PASS_PACKAGES_INSTALLED" == "Y" ]]; then
check_docker_container_registry_saved
fi

# check if a previous config exists or not
check_existing_config

#summary of system state
summarize_prereq


if [[ "$IS_DOCKER_INSTALLED" == "N" && "$OS_NAME" == "ubuntu" ]]; then
echo -e "\e[1;96mAttempting to install Docker for $OS_NAME \e[0m"
install_docker_for_ubuntu
fi

if [[ "$IS_DOCKER_INSTALLED" == "N" && "$OS_NAME" == "rhel" ]]; then
echo -e "\e[1;96mAttempting to install Docker for $OS_NAME \e[0m"
install_docker_for_rhel
fi

if [[ "$IS_PASS_PACKAGES_INSTALLED" == "N" && "$OS_NAME" == "ubuntu" ]]; then
echo -e "\e[1;96mAttempting to install pass packages for $OS_NAME \e[0m"
install_pass_packages_for_ubuntu
fi

if [[ "$IS_PASS_PACKAGES_INSTALLED" == "N" && "$OS_NAME" == "rhel" ]]; then
echo -e "\e[1;96mAttempting to install pass packages for $OS_NAME \e[0m"
install_pass_packages_for_rhel
fi

if [[ "$IS_DOCKER_CREDENTIALS_VALID" == "N" ]]; then
echo -e "\e[1;96mAttempting to setup docker container registry credentials \e[0m"
setup_docker_credentials
fi


#if [[ "$IS_EXISTING_CONFIGURATION" == "Y" ]]; then
#echo -e "\e[1;96mExisting configuration detected: Ignore prompting and automatically use existing? \e[0m"
#ignoreprompting=$(prompt_for_value "ignoreprompting" "N")

# --------------------------------- User Input for Config --------------------------------------

# Determine script directory for reliable volume mounting
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

print_header() {
  printf "${YELLOW}----------------------------------------------------${NC}\n"
  printf "$1\n"
  printf "${YELLOW}----------------------------------------------------${NC}\n"
}

check_port_available() {
  local port=$1
  if lsof -iTCP:"$port" -sTCP:LISTEN -t >/dev/null 2>&1; then
    return 1
  else
    return 0
  fi
}

ask_port_input() {
  local prompt="$1"
  local var_name="$2"
  local default="$3"
  local port="${!var_name}"

  if [[ -n "$port" ]]; then
    if check_port_available "$port"; then
      echo -e "$CHECK Using $var_name from config: ${CYAN}${port}${NC}"
      return
    else
      echo -e "$ERROR Port $port from config is already in use."
      port=""
    fi
  fi

  while true; do
    printf "%b" "- $ARROW $prompt [default: $default]: "
    read port
    port="${port:-$default}"
    if [[ ! "$port" =~ ^[0-9]+$ ]]; then
      echo -e "$ERROR Invalid port: must be a number"
      continue
    fi
    if check_port_available "$port"; then
      eval "$var_name=\"\$port\""
      break
    else
      echo -e "$ERROR Port $port is already in use. Please choose another."
    fi
  done
}

# Prompt for config
print_header "Kafka Broker Configuration"

echo -e "\e[1;93mEnvironment name (TEST/PROD).\e[0m"
ENV_NAME=$(prompt_for_value "ENV_NAME" "TEST")

echo -e "\e[1;93mKafka image, use default of apache/kafka:latest if not otherwise instructed.\e[0m"
KAFKA_IMAGE=$(prompt_for_value "KAFKA_IMAGE" "apache/kafka:latest")

echo -e "\e[1;93mBroker ID, use default of 1 if not otherwise instructed\e[0m"
KAFKA_BROKER_ID=$(prompt_for_value "KAFKA_BROKER_ID" "1")

echo -e "\e[1;93mCluster ID, use default of MkU3OEVBNTcwNTJENDM2Qk if not otherwise instructed.\e[0m"
CLUSTER_ID=$(prompt_for_value "CLUSTER_ID" "MkU3OEVBNTcwNTJENDM2Qk")

echo -e "\e[1;96mSet the kafka sever hostname:\e[0m"
ip=$(hostname -I | awk '{print $1}')
fqdn=$(hostname -f 2>/dev/null)
echo -e "\e[1;96mCurrent IP Address Detected: $ip\e[0m"
if [[ -n "$fqdn" ]]; then
    echo -e "\e[1;96mCurrent FQDN Address Detected: $fqdn\e[0m"
	echo -e "\e[1;96m(set the value to ${fqdn} unless otherwise instructed)\e[0m"
	KAFKA_HOSTNAME=$(prompt_for_value "KAFKA_HOSTNAME" "$fqdn")
else
echo -e "\e[1;96m(set the value to $ip unless otherwise instructed)\e[0m"
KAFKA_HOSTNAME=$(prompt_for_value "KAFKA_HOSTNAME" "$ip")
fi


echo -e "\e[1;93mKafka SASL port (should be set to 29094 unless otherwise instructed, this one needs to be opened).\e[0m"
KAFKA_SASLPORT=$(prompt_for_value "KAFKA_SASLPORT" "29094")

echo -e "\e[1;93mKafka Local port (should be set to 9094 unless otherwise instructed).\e[0m"
KAFKA_LOCALPORT=$(prompt_for_value "KAFKA_LOCALPORT" "9094")

echo -e "\e[1;93mKafka quourum port (should be set to 29093 unless otherwise instructed).\e[0m"
KAFKA_QUOURUMPORT=$(prompt_for_value "KAFKA_QUOURUMPORT" "29093")

echo -e "\e[1;93mSet the kafka username for other serivces to use the Message Broker (e.g the value that appsettings.json in other services will use to connect to the message broker). SAVE THIS VALUE!\e[0m"
KAFKA_USER=$(prompt_for_value "KAFKA_USER" "kafka-default-user")

echo -e "\e[1;93mSet the kafka password for other serivces to use the Message Broker (e.g the value that appsettings.json in other services will use to connect to the message broker). SAVE THIS VALUE!\e[0m"
KAFKA_PASS=$(prompt_for_value "KAFKA_PASS" "kafka-default-password")



# Set container name
CONTAINER_NAME="kafka-${ENV_NAME}"

# Generate JAAS file
print_header "️  Generating JAAS Config"
JAAS_FILE="$directory/kafka_server_jaas.conf"
cat > "$JAAS_FILE" <<EOF
KafkaServer {
  org.apache.kafka.common.security.plain.PlainLoginModule required
    user_$KAFKA_USER="$KAFKA_PASS";
};
EOF
chmod 644 "$JAAS_FILE"
echo -e "$CHECK JAAS file created at $JAAS_FILE"

# Generate client.properties
print_header " Generating client.properties"
CLIENT_PROPS_FILE="$directory/client.properties"
cat > "$CLIENT_PROPS_FILE" <<EOF
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \\
  username="$KAFKA_USER" \\
  password="$KAFKA_PASS";
EOF
chmod 644 "$CLIENT_PROPS_FILE"
echo -e "$CHECK Client config created at $CLIENT_PROPS_FILE"

# Summary
print_header " Final Configuration Summary"
echo -e "Environment Name     : ${CYAN}${ENV_NAME}${NC}"
echo -e "Container Name       : ${CYAN}${CONTAINER_NAME}${NC}"
echo -e "Kafka Image          : ${CYAN}${KAFKA_IMAGE}${NC}"
echo -e "Broker ID            : ${CYAN}${KAFKA_BROKER_ID}${NC}"
echo -e "Cluster ID           : ${CYAN}${CLUSTER_ID}${NC}"
echo -e "Kafka Hostname:Port  : ${CYAN}${KAFKA_HOSTNAME}:${KAFKA_SASLPORT}${NC}"
echo -e "Kafka User           : ${CYAN}${KAFKA_USER}${NC}"
echo -e "Kafka Password       : ${CYAN}${KAFKA_PASS}${NC}"
echo -e "JAAS File Path       : ${CYAN}${JAAS_FILE}${NC}"
echo -e "Client Config Path   : ${CYAN}${CLIENT_PROPS_FILE}${NC}"

printf "%b" "Proceed with container creation? [yes/no]: "
read CONFIRM
[[ "$CONFIRM" != "yes" ]] && { echo -e "$ERROR Cancelled by user."; exit 1; }


# Check if container already exists
if sudo docker ps -a --format '{{.Names}}' | grep -q "^$CONTAINER_NAME$"; then
    sudo docker rm -f "$CONTAINER_NAME"
    echo -e "Removed existing container $CONTAINER_NAME"
fi

# Run container
print_header "Starting Kafka Container"

sudo docker pull "$KAFKA_IMAGE"

docker create \
  --name "$CONTAINER_NAME" \
  --hostname "$HOSTNAME" \
  --network host \
  --restart always \
  -v "$JAAS_FILE":/etc/kafka/kafka_server_jaas.conf:ro \
  -v "$CLIENT_PROPS_FILE":/tmp/client.properties:ro \
  -e KAFKA_BROKER_ID="$KAFKA_BROKER_ID" \
  -e KAFKA_LISTENER_SECURITY_PROTOCOL_MAP="PLAINTEXT:PLAINTEXT,SASL_PLAINTEXT:SASL_PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT,SASL_PLAINTEXT_HOST:SASL_PLAINTEXT,CONTROLLER:PLAINTEXT" \
  -e KAFKA_ADVERTISED_LISTENERS="PLAINTEXT://${KAFKA_HOSTNAME}:29092,SASL_PLAINTEXT://${KAFKA_HOSTNAME}:${KAFKA_SASLPORT},PLAINTEXT_HOST://${KAFKA_HOSTNAME}:9092,SASL_PLAINTEXT_HOST://${KAFKA_HOSTNAME}:${KAFKA_LOCALPORT}" \
  -e KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR="1" \
  -e KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS="0" \
  -e KAFKA_TRANSACTION_STATE_LOG_MIN_ISR="1" \
  -e KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR="1" \
  -e KAFKA_PROCESS_ROLES="broker,controller" \
  -e KAFKA_NODE_ID="1" \
  -e KAFKA_CONTROLLER_QUORUM_VOTERS="1@${KAFKA_HOSTNAME}:${KAFKA_QUOURUMPORT}" \
  -e KAFKA_LISTENERS="PLAINTEXT://${KAFKA_HOSTNAME}:29092,SASL_PLAINTEXT://${KAFKA_HOSTNAME}:${KAFKA_SASLPORT},CONTROLLER://${KAFKA_HOSTNAME}:${KAFKA_QUOURUMPORT},PLAINTEXT_HOST://0.0.0.0:9092,SASL_PLAINTEXT_HOST://0.0.0.0:${KAFKA_LOCALPORT}" \
  -e KAFKA_INTER_BROKER_LISTENER_NAME="SASL_PLAINTEXT" \
  -e KAFKA_CONTROLLER_LISTENER_NAMES="CONTROLLER" \
  -e KAFKA_LOG_DIRS="/tmp/kraft-combined-logs" \
  -e CLUSTER_ID="$CLUSTER_ID" \
  -e KAFKA_SASL_ENABLED_MECHANISMS="PLAIN" \
  -e KAFKA_SASL_MECHANISM_INTER_BROKER_PROTOCOL="PLAIN" \
  -e KAFKA_OPTS="-Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf" \
  -e KAFKA_MESSAGE_MAX_BYTES="$KAFKA_MESSAGE_MAX_BYTES" \
  -e KAFKA_REPLICA_FETCH_MAX_BYTES="$KAFKA_REPLICA_FETCH_MAX_BYTES" \
  -e KAFKA_FETCH_MAX_BYTES="$KAFKA_FETCH_MAX_BYTES" \
  -e KAFKA_MAX_PARTITION_FETCH_BYTES="$KAFKA_MAX_PARTITION_FETCH_BYTES" \
  "$KAFKA_IMAGE"

docker start "$CONTAINER_NAME"

# Wait for Kafka readiness
print_header "Waiting for Kafka to be ready..."

timeout=30
elapsed=0
until docker exec "$CONTAINER_NAME" bash -c "</dev/tcp/localhost/${KAFKA_LOCALPORT}" 2>/dev/null; do
  sleep 2
  elapsed=$((elapsed+2))
  if [[ $elapsed -ge $timeout ]]; then
    echo -e "$ERROR Kafka did not start within ${timeout}s. Check logs with: docker logs $CONTAINER_NAME"
    exit 1
  fi
done

echo -e "$CHECK Kafka is now accepting connections on port ${KAFKA_LOCALPORT}"

# Create Kafka topics
print_header "Creating Kafka Topics"
TOPICS=(
  "claim-validation-errors"
  "file-submission-ready"
  "file-validated"
  "file-submitted"
  "file-created"
  "response-file-detected"
)

for topic in "${TOPICS[@]}"; do
  echo -e "Creating topic: ${CYAN}${topic}${NC}"
  sudo docker exec -i "$CONTAINER_NAME" /opt/kafka/bin/kafka-topics.sh \
    --create \
    --if-not-exists \
    --bootstrap-server localhost:"${KAFKA_LOCALPORT}" \
    --command-config /tmp/client.properties \
    --partitions 1 \
    --replication-factor 1 \
    --topic "$topic"
  echo -e "Done creating topic: ${CYAN}${topic}${NC}"
done

echo -e "Message Broker Installation complete"
