#!/bin/bash

# Set version variable for easy updates
VERSION="1.94"
# Versions (in addition to $VERSION) whose JARs should NOT be deleted.
# Example: PROTECTED_VERSIONS=("1.80" "1.81")
PROTECTED_VERSIONS=("1.91" "1.92" "1.93" "1.90" "1.87" "1.88" "1.89")

JAR_SUFFIX="-SNAPSHOT-linux-aarch64.jar"

# Define remote hosts
ORDER1="kioskOrder1.local"
ORDER2="kioskOrder2.local"
COOK="kioskCook.local"
COOK2="kioskCook2.local"

# Define paths
LOCAL_PATH="/home/user/spagetka"
RESOURCE_SRC="$LOCAL_PATH/${VERSION}_resources"
RESOURCE_DEST="/home/user/spagetka/resources"
RESOURCE_ZIP="$LOCAL_PATH/${VERSION}_resources.zip"
PROPERTIES_FILE="$LOCAL_PATH/resources/application.properties"
REMOTE_PROPERTIES_FILE="$RESOURCE_DEST/application.properties"
CONFIG_FILE="$LOCAL_PATH/resources/config.json"
REMOTE_CONFIG_FILE="$RESOURCE_DEST/config.json"
TMP_PATCH_FILE="/tmp/static_json_patch.json"

CUSTOMER_PATCH=$(mktemp)
CASHIER_PATCH=$(mktemp)

# Define MySQL variables
DB_NAME="spagetka"

# Function to check SCP success
check_scp() {
    if [ $? -ne 0 ]; then
        echo "SCP failed. Aborting."
        exit 1
    fi
}

# Function to update properties file
update_properties_file() {
    local FILE_PATH="$1"
    local IS_REMOTE="$2"
    local HOST="$3"

    for KEY in "${!PROPERTIES_TO_SET[@]}"; do
        VALUE="${PROPERTIES_TO_SET[$KEY]}"

        if [ "$IS_REMOTE" = true ]; then
            ssh "$HOST" "grep -qE '^$KEY=' '$FILE_PATH'" 2>/dev/null
            if [ $? -eq 0 ]; then
                ssh "$HOST" "sed -i 's|^$KEY=.*|$KEY=$VALUE|' '$FILE_PATH'"
                echo "$HOST: Updated $KEY to $VALUE"
            else
                ssh "$HOST" "echo '$KEY=$VALUE' >> '$FILE_PATH'"
                echo "$HOST: Added $KEY=$VALUE"
            fi
        else
            if grep -qE "^$KEY=" "$FILE_PATH"; then
                sed -i "s|^$KEY=.*|$KEY=$VALUE|" "$FILE_PATH"
                echo "Local: Updated $KEY to $VALUE"
            else
                echo "$KEY=$VALUE" >> "$FILE_PATH"
                echo "Local: Added $KEY=$VALUE"
            fi
        fi
    done
}

update_json_section() {
    local FILE="$1"
    local SECTION="$2"
    local PATCH="$3"
    local TMPFILE="$(mktemp)"

    jq --argjson patch "$(cat "$PATCH")" \
       --arg section "$SECTION" \
       '.[$section] = (.[$section] * $patch)' \
       "$FILE" > "$TMPFILE" && mv "$TMPFILE" "$FILE"
}

# --- Ensure jq is installed remotely ---
ensure_jq_remote() {
    local HOST="$1"
    echo "Checking jq on $HOST..."
    ssh "$HOST" "command -v jq &>/dev/null || (echo 'Installing jq on $HOST...' && sudo apt-get update && sudo apt-get install -y jq)" || {
        echo "ERROR: Failed to install jq on $HOST."
        exit 1
    }
}

ensure_rsync_locally() {
    if ! command -v rsync &>/dev/null; then
    echo "rsync not found. Installing locally..."
    sudo apt-get update && sudo apt-get install -y rsync || {
        echo "ERROR: Failed to install rsync locally."
        exit 1
    }
    else
        echo "rsync already installed locally."
    fi
}

ensure_rsync_remote() {
    local HOST="$1"
    echo "Checking rsync on $HOST..."
    ssh "$HOST" "command -v rsync &>/dev/null || (echo 'Installing rsync on $HOST...' && sudo apt-get update && sudo apt-get install -y rsync)" || {
        echo "ERROR: Failed to install rsync on $HOST."
        exit 1
    }
}

cleanup_old_jars() {
    local HOST="$1"
    local TARGET_PATH="$LOCAL_PATH"

    # Build the list of -not -name filters for versions we want to keep
    local EXCLUDE_FILTERS=""
    local KEEP_VER
    for KEEP_VER in "$VERSION" "${PROTECTED_VERSIONS[@]}"; do
        # Skip empty entries (in case PROTECTED_VERSIONS is empty)
        [ -z "$KEEP_VER" ] && continue
        EXCLUDE_FILTERS+=' ! -name "spagetka_*-'"$KEEP_VER$JAR_SUFFIX"'"'
    done

    if [ -z "$HOST" ]; then
        # Local cleanup
        eval "find \"$TARGET_PATH\" -maxdepth 1 -type f -name \"spagetka_*$JAR_SUFFIX\" $EXCLUDE_FILTERS -print -delete"
    else
        # Remote cleanup
        ssh "$HOST" "bash -lc 'find \"$TARGET_PATH\" -maxdepth 1 -type f -name \"spagetka_*$JAR_SUFFIX\" $EXCLUDE_FILTERS -print -delete'"
    fi
}

cleanup_resource_backups() {
    local HOST="$1"

    if [ -z "$HOST" ]; then
        # Local cleanup
        cd "$LOCAL_PATH" 2>/dev/null || return 0

        # List backups newest-first, keep 5, delete the rest
        ls -1t resources_backup_*.tar.gz 2>/dev/null | tail -n +6 | while read -r f; do
            [ -z "$f" ] && continue
            echo "Deleting old local resources backup: $LOCAL_PATH/$f"
            rm -- "$f"
        done
    else
        # Remote cleanup
        ssh "$HOST" "
            cd '$LOCAL_PATH' 2>/dev/null || exit 0
            ls -1t resources_backup_*.tar.gz 2>/dev/null | tail -n +6 | while read -r f; do
                [ -z \"\$f\" ] && continue
                echo 'Deleting old resources backup on $HOST:' \"\$PWD/\$f\"
                rm -- \"\$f\"
            done
        "
    fi
}



# Copy JAR files
echo "Copying JAR files"
scp "$LOCAL_PATH/spagetka_CustomerApp-$VERSION$JAR_SUFFIX" "$ORDER1:$LOCAL_PATH" && check_scp
scp "$LOCAL_PATH/spagetka_CustomerApp-$VERSION$JAR_SUFFIX" "$ORDER2:$LOCAL_PATH" && check_scp
scp "$LOCAL_PATH/spagetka_CookApp-$VERSION$JAR_SUFFIX" "$COOK:$LOCAL_PATH" && check_scp
scp "$LOCAL_PATH/spagetka_CookApp-$VERSION$JAR_SUFFIX" "$COOK2:$LOCAL_PATH" && check_scp


if [[ ! -f "$RESOURCE_ZIP" ]]; then
    echo "WARNING: Zip file $RESOURCE_ZIP not found. Skipping resources backup and deployment."
else
    # Backup resources folder on all machines (including local)
    echo "Running resources backups"
    tar -czf "$LOCAL_PATH/resources_backup_$(date +%F_%H-%M-%S).tar.gz" -C "$LOCAL_PATH" resources
    ssh "$ORDER1" "tar -czf $LOCAL_PATH/resources_backup_$(date +%F_%H-%M-%S).tar.gz -C $RESOURCE_DEST ."
    ssh "$ORDER2" "tar -czf $LOCAL_PATH/resources_backup_$(date +%F_%H-%M-%S).tar.gz -C $RESOURCE_DEST ."
    ssh "$COOK" "tar -czf $LOCAL_PATH/resources_backup_$(date +%F_%H-%M-%S).tar.gz -C $RESOURCE_DEST ."
    ssh "$COOK2" "tar -czf $LOCAL_PATH/resources_backup_$(date +%F_%H-%M-%S).tar.gz -C $RESOURCE_DEST ."

    echo "Transferring resources (from zip)"
    ensure_rsync_locally()
    for HOST in "$ORDER1" "$ORDER2" "$COOK" "$COOK2"; do
        ensure_rsync_remote "$HOST"
    done

    TMPDIR=$(mktemp -d) || { echo "ERROR: Cannot create temp dir"; exit 1; }
    cleanup() { rm -rf "$TMPDIR"; }
    trap cleanup EXIT

    # Unpack the zip silently
    if ! unzip -q "$RESOURCE_ZIP" -d "$TMPDIR"; then
        echo "ERROR: Failed to unzip $RESOURCE_ZIP"
        exit 1
    fi

    # If the zip contains a single top-level directory, use its contents; otherwise use the root
    CONTENT_ROOT="$TMPDIR"
    mapfile -t entries < <(find "$TMPDIR" -mindepth 1 -maxdepth 1 -not -name '__MACOSX' -printf '%P\n')
    if (( ${#entries[@]} == 1 )) && [[ -d "$TMPDIR/${entries[0]}" ]]; then
        CONTENT_ROOT="$TMPDIR/${entries[0]}"
    fi

    # Local copy (preserves perms/timestamps)
    mkdir -p "$LOCAL_PATH/resources/"
    rsync -a "$CONTENT_ROOT"/ "$LOCAL_PATH/resources/"

    # Remote copy to each host (also preserves perms/timestamps)
    for HOST in "$ORDER1" "$ORDER2" "$COOK" "$COOK2"; do
        rsync -a "$CONTENT_ROOT"/ "$HOST:$RESOURCE_DEST" && check_scp
    done
fi

# Ensure logs directory exists on local and remote machines
LOGS_PATH="$LOCAL_PATH/logs/api"
mkdir -p "$LOGS_PATH"
ssh "$ORDER1" "mkdir -p $LOGS_PATH"
ssh "$ORDER2" "mkdir -p $LOGS_PATH"
ssh "$COOK" "mkdir -p $LOGS_PATH"
ssh "$COOK2" "mkdir -p $LOGS_PATH"

# Update scripts
echo "Running update of start scripts"
sed -i "s/spagetka_CashierApp-[0-9]*\.[0-9]*$JAR_SUFFIX/spagetka_CashierApp-$VERSION$JAR_SUFFIX/g" "$LOCAL_PATH/startCashier.sh" || echo "WARNING: Failed to update startCashier.sh"

ssh "$COOK" "sed -i 's/spagetka_CookApp-[0-9]*\.[0-9]*$JAR_SUFFIX/spagetka_CookApp-$VERSION$JAR_SUFFIX/g' $LOCAL_PATH/startCook.sh" || echo "WARNING: Failed to update startCook.sh for Cook"

ssh "$COOK2" "sed -i 's/spagetka_CookApp-[0-9]*\.[0-9]*$JAR_SUFFIX/spagetka_CookApp-$VERSION$JAR_SUFFIX/g' $LOCAL_PATH/startCook.sh" || echo "WARNING: Failed to update startCook.sh for Cook2"

ssh "$ORDER1" "sed -i 's/spagetka_CustomerApp-[0-9]*\.[0-9]*$JAR_SUFFIX/spagetka_CustomerApp-$VERSION$JAR_SUFFIX/g' $LOCAL_PATH/startCustomer.sh" || echo "WARNING: Failed to update startCustomer.sh for Order1"

ssh "$ORDER2" "sed -i 's/spagetka_CustomerApp-[0-9]*\.[0-9]*$JAR_SUFFIX/spagetka_CustomerApp-$VERSION$JAR_SUFFIX/g' $LOCAL_PATH/startCustomer.sh" || echo "WARNING: Failed to update startCustomer.sh for Order2"

# Properties
declare -A PROPERTIES_TO_SET=(

)

# declare -A PROPERTIES_TO_SET=(
#     [property.key1]="value1"
#     [property.key2]="value2"
#     [property.key3]="value3 with spaces"
# )

if (( ${#PROPERTIES_TO_SET[@]} > 0 )); then
    # Update local application.properties
    echo "Updating local application.properties..."
    update_properties_file "$PROPERTIES_FILE" false ""

    # Update remote application.properties
    for HOST in "$ORDER1" "$ORDER2" "$COOK" "$COOK2"; do
        echo "Updating application.properties on $HOST..."
        update_properties_file "$REMOTE_PROPERTIES_FILE" true "$HOST"
    done
else
    echo "Skipping updates — PROPERTIES_TO_SET is empty."
fi

# # Update JSON files

# # --- Ensure jq is installed locally ---
# if ! command -v jq &>/dev/null; then
#     echo "jq not found. Installing locally..."
#     sudo apt-get update && sudo apt-get install -y jq || {
#         echo "ERROR: Failed to install jq locally."
#         exit 1
#     }
# else
#     echo "jq already installed locally."
# fi

# for HOST in "$ORDER1" "$ORDER2" "$COOK" "$COOK2"; do
#     ensure_jq_remote "$HOST"
# done

# # Local paths to temp JSON files
# CUSTOMER_PATCH=$(mktemp)
# CASHIER_PATCH=$(mktemp)

# # Define patches
# cat > "$CUSTOMER_PATCH" <<EOF
# {
#   "screensaverConfig" : {
#     "enableImageScreensaver": false,
#     "enableMediaScreensaver": false,
#     "relativeImagePath" : "/resources/screensaver/images",
#     "relativeMediaPath" : "/resources/screensaver/media",
#     "activationScreensaverTimeSeconds" : 120,
#     "nextImageTimeSeconds": 10,
#     "fadeOutTimeSeconds": 1,
#     "fadeInTimeSeconds": 1
#   }
# }
# EOF

# cat > "$CASHIER_PATCH" <<EOF
# {
#   "labelPrinterConfig": {
#     "enabled": false,
#     "printerName": "EML-300L",
#     "logoImageName": "spagetka_black_white_bg.png",
#     "codepage": "1250",
#     "font": 4,
#     "fontSize": 1,
#     "labelDimensions": {
#       "width": "50 mm",
#       "height": "50 mm",
#       "gapSize": "10.5 mm",
#       "gapOffset": "0 mm"
#     },
#     "referenceX": 0,
#     "referenceY": 0,
#     "speed": "6.0",
#     "density": 15,
#     "setPeel": "OFF",
#     "setCutter": "OFF",
#     "setPartialCutter": "OFF",
#     "setTear": "ON",
#     "setRibbon": "OFF",
#     "setDebug": "LABEL",
#     "direction": "0,0",
#     "shift": "0",
#     "offset": "0.0 mm",
#     "addCls": true,
#     "enabledCategories": [1, 2, 3, 8]
#   }
# }
# EOF

# echo "Updating local config.json..."
# update_json_section "$CONFIG_FILE" "customer" "$CUSTOMER_PATCH"
# update_json_section "$CONFIG_FILE" "cashier" "$CASHIER_PATCH"
# echo "Local update complete."

# # Update remote machines
# for HOST in "$ORDER1" "$ORDER2" "$COOK" "$COOK2"; do
#     echo "Updating config.json on $HOST..."

#     scp "$CUSTOMER_PATCH" "$HOST:/tmp/customer_patch.json"
#     scp "$CASHIER_PATCH" "$HOST:/tmp/cashier_patch.json"

#     ssh "$HOST" "jq -S --slurpfile patch /tmp/customer_patch.json \
#         '.customer = (.customer * \$patch[0])' '$REMOTE_CONFIG_FILE' > /tmp/tmp_config && mv /tmp/tmp_config '$REMOTE_CONFIG_FILE'"

#     ssh "$HOST" "jq -S --slurpfile patch /tmp/cashier_patch.json \
#         '.cashier = (.cashier * \$patch[0])' '$REMOTE_CONFIG_FILE' > /tmp/tmp_config && mv /tmp/tmp_config '$REMOTE_CONFIG_FILE'"

#     ssh "$HOST" "rm /tmp/customer_patch.json /tmp/cashier_patch.json"
#     echo "$HOST update complete."
# done

# # Clean up local temp files
# rm "$CUSTOMER_PATCH" "$CASHIER_PATCH"




# SQL section
SQL_COMMAND="alter table orders modify order_type enum ('PERSONAL_HERE', 'PERSONAL_TAKE_AWAY', 'ONLINE', 'DELIVERY', 'WOLT', 'FOODORA', 'BOLT', 'WOLT_PICKUP', 'FOODORA_PICKUP', 'BOLT_PICKUP', 'DELIVERY_PICKUP', 'DELIVERY_RESTIA', 'RESTIA_FOODORA_DELIVERY', 'RESTIA_FOODORA_PICKUP', 'RESTIA_BOLT_DELIVERY', 'RESTIA_BOLT_PICKUP', 'RESTIA_WOLT_DELIVERY', 'RESTIA_WOLT_PICKUP', 'RESTIA_JIDLOPODNOS_DELIVERY', 'RESTIA_JIDLOPODNOS_PICKUP') null;"

if [ -n "$SQL_COMMAND" ]; then

    # Prompt for MySQL credentials
    echo -n "Enter MySQL username: "
    read -r DB_USER
    echo -n "Enter MySQL password: "
    read -s DB_PASS
    echo

    # Run SQL queries
    echo "Starting to run SQL commands"


    echo "$SQL_COMMAND" | mysql -u "$DB_USER" -p"$DB_PASS" "$DB_NAME"
    if [ $? -ne 0 ]; then
        echo "ERROR: SQL execution failed. Debugging information:"
        echo "$SQL_COMMAND"
        exit 1
    fi
else
    echo "Skipping SQL execution as no commands are provided."
fi

echo "Cleaning up old JAR versions (local and remote)..."
cleanup_old_jars ""          # local machine
cleanup_old_jars "$ORDER1"
cleanup_old_jars "$ORDER2"
cleanup_old_jars "$COOK"
cleanup_old_jars "$COOK2"

echo "Cleaning up old resources_backup files (keeping 5 latest per machine)..."
cleanup_resource_backups           # local
cleanup_resource_backups "$ORDER1"
cleanup_resource_backups "$ORDER2"
cleanup_resource_backups "$COOK"
cleanup_resource_backups "$COOK2"


echo "Deployment completed successfully."