#!/bin/bash

###################################################################################################
# Created by CVI                                                                                  #
# Version 1.0 Deploy ment for APIGateway                                                          #
# - Slots in use - APIGateway(https) 5xx89 APIGateway(http) 5xx89 Helth (https)                   #
###################################################################################################

# Define paths
ABS_DIR="/abs"
BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_DIR="$BASE_DIR/repo"
CONFIG_DIR="$BASE_DIR/config"
LOG_DIR="$BASE_DIR/logs"
LOG_FILE="$LOG_DIR/APIGateway.log"
CUSTOM_PROPERTIES_FILE="$CONFIG_DIR/custom_properties.cfg"
#######################
# Define Java version #
#######################

# Check logs directory exists
mkdir -p "$LOG_DIR" || { echo "Error: Failed to create logs directory at $LOG_DIR"; exit 1; }

log_message() {
    local MESSAGE=$1
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $MESSAGE" >> "$LOG_FILE"
}

# Check required tools are installed
for TOOL in unzip dos2unix awk grep sed; do
    if ! command -v "$TOOL" &> /dev/null; then
        echo "Error: $TOOL is not installed. Please install it and try again."
        exit 1
    fi
done

# Log messages to a log file
log_message() {
    local MESSAGE=$1
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $MESSAGE" >> "$LOG_FILE"
}

################################
# Install the APIGateway #
################################
install_APIGateway() {

    # Validate slot number
    if ! grep -q "^$ABS_SLOT" "$CUSTOM_PROPERTIES_FILE"; then
        echo "Error: Invalid slot number. Slot $ABS_SLOT not found in $CUSTOM_PROPERTIES_FILE."
        log_message "Error: Invalid slot number $ABS_SLOT entered."
		read -p "Invalid number try again"
		clear
        show_menu
    fi

    # List available APIGateway files versions
    echo "Available APIGateway files:"
    ZIP_FILES=("$REPO_DIR"/*.zip) # Store all ZIP files location
    for i in "${!ZIP_FILES[@]}"; do
        echo -e "\e[33m$((i + 1))) $(basename "${ZIP_FILES[i]}")\e[0m"
    done

    # Choose the ABSSolute slot number
    read -p "Enter the number corresponding to the ZIP file you want to install: " ZIP_CHOICE

    # Validate the choice
    if ! [[ "$ZIP_CHOICE" =~ ^[0-9]+$ ]] || (( ZIP_CHOICE < 1 || ZIP_CHOICE > ${#ZIP_FILES[@]} )); then
        echo "Error: Invalid choice. Please select a valid number from the list."
        log_message "Error: Invalid ZIP file choice $ZIP_CHOICE entered."
		read -p "Invalid number try again"
		clear
		show_menu
    fi

    # Get the selected APIGateway file to unzip. Backup and clean up
    ZIP_FILE="${ZIP_FILES[ZIP_CHOICE-1]}"
    SLOT_DIR="$ABS_DIR/$ABS_SLOT/APIGateway"

    if [[ -d "$SLOT_DIR" ]]; then
        BACKUP_DIR="$BASE_DIR/Backup/$ABS_SLOT"
        NEW_BACKUP="$BACKUP_DIR/APIGateway_backup_$(date '+%Y%m%d%H%M')"
        
        mkdir -p "$BACKUP_DIR" || { echo "Error: Failed to create backup directory at $BACKUP_DIR"; return; }
        
        read -p "Warning: Old installation found in $SLOT_DIR. Do you want to update it? (y/n): " CLEAN_CHOICE
        if [[ "$CLEAN_CHOICE" =~ ^[Yy]$ ]]; then
            echo "Backing up old installation to $NEW_BACKUP..."
            mv "$SLOT_DIR" "$NEW_BACKUP" || { echo "Error: Failed to back up the old installation."; return; }
            log_message "Old installation backed up to $NEW_BACKUP."
            
            # Remove old backups, 5 backups retention
            BACKUP_COUNT=$(ls -d "$BACKUP_DIR"/APIGateway_backup_* 2>/dev/null | wc -l)
            if [[ "$BACKUP_COUNT" -gt 5 ]]; then
                ls -d "$BACKUP_DIR"/APIGateway_backup_* | sort | head -n -5 | xargs rm -rf
            fi
        else
            echo "Skipping old installation cleanup."
        fi
    fi

    # Create a new ABSSolute slot directory if it doesn't exist
    mkdir -p "$SLOT_DIR" || { echo "Error: Failed to create directory $SLOT_DIR."; return; }

    # Unzip the chosen file into the ABSSolute slot directory
    echo "Unzipping $ZIP_FILE into $SLOT_DIR..."
    unzip -o "$ZIP_FILE" -d "$SLOT_DIR" || { echo "Error: Failed to unzip $ZIP_FILE."; return; }

    # Prepare application.properties
    SAMPLE_PROPERTIES="$SLOT_DIR/config/sample_application.properties"
    FINAL_PROPERTIES="$SLOT_DIR/config/application.properties"

    if [[ ! -f "$SAMPLE_PROPERTIES" ]]; then
        echo "Error: Sample properties file $SAMPLE_PROPERTIES not found!"
        log_message "Error: Sample properties file missing for slot $ABS_SLOT."
        exit 1
    fi

    cp "$SAMPLE_PROPERTIES" "$FINAL_PROPERTIES"
	
    # Replace existing server and management port values
    sed -i "s/^server\.port=.*/server.port=5${ABS_SLOT}89/" "$FINAL_PROPERTIES"
	
    # Parse custom_properties.cfg and apply changes to application.properties
    echo "Applying custom properties for ABSSolute slot $ABS_SLOT..."
    grep "^$ABS_SLOT" "$CUSTOM_PROPERTIES_FILE" | while read -r line; do
        FILE_NAME=$(echo "$line" | awk '{print $2}')
        PROPERTY_KEY=$(echo "$line" | awk '{print $3}')
        PROPERTY_VALUE=$(echo "$line" | sed -E 's/^[^ ]+ +[^ ]+ +[^ ]+ +(.*)/\1/')

        TARGET_FILE="$SLOT_DIR/config/$FILE_NAME"

        if [[ ! -f "$TARGET_FILE" ]]; then
            echo "Error: $FILE_NAME not found in $SLOT_DIR/config."
            log_message "Error: $FILE_NAME missing for slot $ABS_SLOT."
            continue
        fi

        if grep -q "^$PROPERTY_KEY=" "$TARGET_FILE"; then
            sed -i "s|^$PROPERTY_KEY=.*|$PROPERTY_KEY=$PROPERTY_VALUE|" "$TARGET_FILE"
        else
            echo "$PROPERTY_KEY=$PROPERTY_VALUE" >> "$TARGET_FILE"
        fi
    done

    # Define the start_application location
    START_SCRIPT="$SLOT_DIR/start_application.sh"
    
    # Ensure the start_application exists (or create a new one)
    echo "Replacing $START_SCRIPT with a new version..."
    JMXport="5${ABS_SLOT}88"
    mkdir $SLOT_DIR/logs

    cat > "$START_SCRIPT" <<EOF
#!/bin/sh

# APP_HOME is the Server folder of the APIGateway structure
APP_HOME=$SLOT_DIR
JAVA_HOME=jre/bin
JMXport=$JMXport
echo "Starting application..."
cd \$APP_HOME
nohup \$JAVA_HOME/java -Dcom.sun.management.jmxremote.port=\$JMXport -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar APIGateway.jar > "\$APP_HOME/logs/apigateway.log" 2>&1 &
EOF


    # Ensure the script is executable
    chmod +x "$START_SCRIPT" || { echo "Error: Failed to set execute permission on $START_SCRIPT."; return; }
	# Ensure jre folder has proper permissions
    chmod -R 775 "$SLOT_DIR/jre" || { echo "Error: Failed to set execute permission on $SLOT_DIR/jre."; return; }
    
    log_message "Replaced start_application.sh with a new script."
    echo "start_application.sh has been updated successfully."

    # Cleanup Windows *bat *.xml or *.exe unnecessary files in $SLOT_DIR
if [[ -d "$SLOT_DIR" ]]; then
    echo "Checking for unnecessary files in $SLOT_DIR..."
    
    FILES_FOUND=$(find "$SLOT_DIR" -type f \( -name "*.bat" -o -name "*.xml" -o -name "*.exe" \))
    
    if [[ -n "$FILES_FOUND" ]]; then
        echo "Removing .bat .xml and .exe files from $SLOT_DIR..."
        find "$SLOT_DIR" -type f \( -name "*.bat" -o -name "*.xml" -o -name "*.exe" \) -exec rm -f {} +
        log_message "Removed Windows *.bat *.xml *.exe files from $SLOT_DIR."
    else
        echo "No .bat or .xml or *.bat files found in $SLOT_DIR. Skipping cleanup."
    fi
else
    echo "Warning: $SLOT_DIR directory not found. Skipping cleanup."
fi

    echo "Installation complete. Check $FINAL_PROPERTIES for the updated properties."
    log_message "Installation complete for slot $ABS_SLOT."
    read -p "Press enter to continue"
}

####################################
# Function to check the APIGateway #
####################################
application_check() {
    # Assuming $ABS_SLOT will be set in the menu - easy then to prompt each time the slot selection
    ABS_SLOT=$1
    FINAL_PROPERTIES="$ABS_DIR/$ABS_SLOT/APIGateway/config/application.properties"
    
    # Check if SSL is enabled
    SERVER_SSL_ENABLED=$(grep '^server.ssl.enabled=' "$FINAL_PROPERTIES" | cut -d '=' -f2 | tr -d '[:space:]')
    # Get the value of abs.server.uri
    ABS_SERVER_URI=$(grep '^abs.server.uri=' "$FINAL_PROPERTIES" | cut -d '=' -f2 | tr -d '[:space:]')
    
    # Determine the protocol (HTTP/HTTPS)
    if [[ "$SERVER_SSL_ENABLED" == "true" ]]; then
        PROTOCOL="https"
        CURL_FLAGS="-k"  # Ignore SSL verification
    else
        PROTOCOL="http"
        CURL_FLAGS=""  # No need to ignore SSL
    fi

    # Construct the URL for health check
	HOST=$(hostname -s)
    URL="$PROTOCOL://$HOST:5${ABS_SLOT}89"
    
    # Retry parameters
    MAX_RETRIES=3
    RETRY_DELAY=10
    ATTEMPTS=0
    
    echo "Checking application health at $URL..."

    # Retry loop
    while (( ATTEMPTS < MAX_RETRIES )); do
        # Perform the curl request to check application health
        RESPONSE=$(curl $CURL_FLAGS -s "$URL")
        
        # Handle empty response
        if [[ -z "$RESPONSE" ]]; then
            echo -e "\033[0;33mNo response from server. The application might still be starting...\033[0m"
        elif [[ "$RESPONSE" == 'Gateway up and connected to the Abssolute server.' ]]; then
            # Success message application deployed corectly
            echo -e "\033[0;32mApplication is deployed correctly and operational.\033[0m"
            log_message "Application is deployed correctly for slot $ABS_SLOT."
            read -p "Press enter to continue"
			return
        elif [[ "$RESPONSE" == 'APIGateway is operational but cannot establish a connection to the server.' ]]; then
            # Error message: communication with Application server failed
            echo -e "\033[0;31mApplication has issues: Cannot establish a connection to the application server $ABS_SERVER_URI.\033[0m"
            log_message "Application has issues for slot $ABS_SLOT: Cannot establish a connection."
            read -p "Press enter to continue"
			return
        else
            # Error: MobileGateway did not start
            echo -e "\033[0;31mUnexpected response or error in health check.\033[0m"
            log_message "Error in health check for slot $ABS_SLOT. APIGateway did not start correctly. Check logs."
			read -p "Press enter to continue"
			return
        fi
        
        # If response was not successful, retry after a delay
        sleep $RETRY_DELAY
        ((ATTEMPTS++))
    done

    # All retries failed, print a final error message
    echo -e "\033[0;31mApplication failed to respond after $MAX_RETRIES attempts: $URL\033[0m"
    log_message "Application failed to respond for slot $ABS_SLOT after $MAX_RETRIES attempts."
	read -p "Press enter to continue"
}

#################################################
# Function to start the APIGatewayService #
#################################################
start_APIGateway() {
    ABS_SLOT=$1
    START_SCRIPT="$ABS_DIR/$ABS_SLOT/APIGateway/start_application.sh"

    if [[ ! -f "$START_SCRIPT" ]]; then
        echo "Error: start_application.sh not found in $START_SCRIPT"
        log_message "Error: start_application.sh missing for slot $ABS_SLOT."
        exit 1
    fi

    dos2unix "$START_SCRIPT" || { echo "Error: Failed to convert $START_SCRIPT to Unix format."; exit 1; }

    # Check if service is already running
    if pgrep -f "APIGateway.*$ABS_SLOT" > /dev/null; then
        echo "Service is already running for slot $ABS_SLOT."
        log_message "Attempted to start service, but it is already running for slot $ABS_SLOT."
		read -p "Press enter to continue"
		return
    fi

    # Start the application
    echo "Starting APIGatewayService for ABSSolute slot $ABS_SLOT..."
    bash "$START_SCRIPT" || { echo "Error: Failed to start the service."; exit 1; }
    log_message "Service started for slot $ABS_SLOT."
    read -p "Press enter to continue"
}

################################################
# Function to stop the APIGatewayService #
################################################
stop_APIGateway() {
    ABS_SLOT=$1
    STOP_SCRIPT="$ABS_DIR/$ABS_SLOT/APIGateway/stop_application.sh"

    if [[ ! -f "$STOP_SCRIPT" ]]; then
        echo "Warning: stop_application.sh not found at $STOP_SCRIPT. Skipping stop process."
        log_message "Warning: stop_application.sh missing. Skipping stop process for slot $ABS_SLOT."
        return 0  
    fi

    dos2unix "$STOP_SCRIPT" || {
        echo "Warning: Failed to convert $STOP_SCRIPT to Unix format. Continuing..."
        log_message "Warning: Failed to convert $STOP_SCRIPT to Unix format for slot $ABS_SLOT."
    }

    # Stop the application without exiting on failure
    echo "Stopping APIGatewayService for ABSSolute slot $ABS_SLOT..."
    if ! bash "$STOP_SCRIPT"; then
        echo "Warning: Failed to stop the service. Continuing with installation..."
        log_message "Warning: Failed to stop APIGateway for slot $ABS_SLOT. Proceeding with installation."
    fi

    read -p "Press enter to continue"
}

############################################
# Function to add the APIGateway in startAll.sh
############################################
startAll_APIGateway() {
    if [ -f /abs/startAll.sh ]; then
        # Check if the lines are already present
        grep -q "# Startup APIGateway on slot $ABS_SLOT" /abs/startAll.sh && grep -q "$SLOT_DIR/start_application.sh" /abs/startAll.sh
        if [ $? -ne 0 ]; then
            echo "# Startup APIGateway on slot $ABS_SLOT" >> /abs/startAll.sh
            echo "$SLOT_DIR/start_application.sh" >> /abs/startAll.sh
			echo -e "\033[0;32mStartup APIGateway on slot $ABS_SLOT was added to /abs/startAll.sh.\033[0m"
        else
            echo -e "\033[0;32mThe slot $ABS_SLOT is already set start in /abs/startAll.sh.\033[0m"
        fi
    else
        echo "Error: /abs/startAll.sh does not exist."
    fi
}

##########################################
# Display the menu and handle user input #
##########################################
show_menu() {
    echo "|---------------------------------------------------------------------------------------|"
    echo "|Setup for APIGateway - release date 01.2025                                            |"
    echo  -e "|Dedicated for ABSSolute ABSSolute slot setup -\e[92m script version 1.0 \e[0m                     |"
    echo "|Check the configuration file in /abs/APIGateway/config/custom_properties.cfg           |"
    echo "|---------------------------------------------------------------------------------------|"
    echo "===================================="
    echo "1) Install APIGatewayService"
	echo
    echo "2) Start APIGatewayService"
    echo "3) Stop APIGatewayService"
    echo "4) Restart APIGatewayService"
	echo
	echo "5) APIGatewayService status"
    echo
    echo "0) Exit"
    echo "===================================="
    read -p "Choose an option (1-4). Press 0 to exit : " choice

    case $choice in
        1)
	        echo "Available ABSSolute slot numbers:"
            grep -oP "^\d+" "$CUSTOM_PROPERTIES_FILE" | sort -u
            read -p "Enter the ABSSolute slot number to stop: " ABS_SLOT
            stop_APIGateway "$ABS_SLOT"
            install_APIGateway "$ABS_SLOT"
		    startAll_APIGateway "$ABS_SLOT"
			start_APIGateway "$ABS_SLOT"
			application_check "$ABS_SLOT"
            ;;
        2)
		    echo "Available ABSSolute slot numbers:"
            grep -oP "^\d+" "$CUSTOM_PROPERTIES_FILE" | sort -u
            read -p "Enter the ABSSolute slot number to start: " ABS_SLOT
            start_APIGateway "$ABS_SLOT"
			application_check "$ABS_SLOT"
            ;;
        3)
		    echo "Available ABSSolute slot numbers:"
            grep -oP "^\d+" "$CUSTOM_PROPERTIES_FILE" | sort -u
            read -p "Enter the ABSSolute slot number to stop: " ABS_SLOT
            stop_APIGateway "$ABS_SLOT"
            ;;
        4)
            echo "Available ABSSolute slot numbers:"
			grep -oP "^\d+" "$CUSTOM_PROPERTIES_FILE" | sort -u
            read -p "Enter the ABSSolute slot number to restart: " ABS_SLOT
            stop_APIGateway "$ABS_SLOT"
			start_APIGateway "$ABS_SLOT"
            ;;
		5)
		    echo "Available ABSSolute slot numbers:"
            grep -oP "^\d+" "$CUSTOM_PROPERTIES_FILE" | sort -u
            read -p "Enter the ABSSolute slot number to stop: " ABS_SLOT
            application_check "$ABS_SLOT"
            ;;
        0)
            echo "Exiting..."
            exit 0
            ;;
        *)
            echo "Invalid option. Please choose a number between 1 and 5 - Press 0 to exit."
            ;;
    esac
}

# Main loop to show menu until the user exits
while true; do
  clear
  show_menu
done
