## UTILS functions that are used overall the script ##

## HERE ssh functions ##

# Function to test SSH connection
# NOTE Avoid adding key fingerprint procedure
test_ssh_connection(){
     # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"
  local source=$1
  local target=$2

  log $DEBUG_LEVEL $VERBOSE_INFO "Testing SSH connection from $source to $target..."

  ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $source@$target "echo SSH connection successful from $source to $target"

  if [ $? -eq 0 ]; then
    log $DEBUG_LEVEL $VERBOSE_INFO "SSH connection from $source to $target is successful."
  else
    log $DEBUG_LEVEL $VERBOSE_ERROR "SSH connection from $source to $target failed."
  fi
}

## HERE CSV functions ##

# Generalized function to load any CSV into a 2D array dynamically
load_csv_into_array(){
     # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"
  local path_to_csv_file="$1"
  
  # Extract the CSV file name (without path and extension)
  local csv_filename=$(basename "$path_to_csv_file" .csv)
  
  # Declare a global associative array based on the CSV file name
  declare -gA "${csv_filename}"
  
  # Read the CSV and load it into the global associative array
  row_index=0
  header_read=false
  columns=()  # To hold the header names (column names)

  while IFS=, read -r node rest; do
      if [ "$header_read" = false ]; then
          # First line is header, save column names
          IFS=, read -r -a columns <<< "$rest"
          header_read=true
          continue
      fi
      
      # Fill the data array
      eval "${csv_filename}[$row_index,0]='$node'"  # Node name as first column
      IFS=, read -r -a row <<< "$rest"  # Read the row data into an array
      for col_index in "${!row[@]}"; do
          eval "${csv_filename}[$row_index,${columns[$col_index]}]=\"${row[$col_index]}\""
      done
      
      ((row_index++))
  done < "$path_to_csv_file"
}

# HERE PARSING FUNCTIONS #

# Define the function to extract time from the timestamp
extract_time(){
     # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"
  local log_timestamp=$1
  # Extract the time from the timestamp (e.g., 08:37:50)
  extracted_time=$(echo "$log_timestamp" | grep -oP '\d{2}:\d{2}:\d{2}')
  extracted_time=$(echo $extracted_time | awk '{print $2}')
  echo "$extracted_time"
}
parse_rule_id() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local log_file_path=$1
    local rule_id=$2

    # Test if the log file exists and is readable
    if [ ! -f "$log_file_path" ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Error: Log file $log_file_path does not exist or is not accessible."
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Get today's date dynamically
    today_date=$(date +"%Y/%m/%d")

    # Extract the last log entry with the specified rule ID and today's date
    last_log=$(grep "$rule_id" "$log_file_path" | grep "$today_date" | sort -t' ' -k1,1 -k2,2 | tail -n 1)

    # Check if the log entry is found
    if [ -z "$last_log" ]; then
        log $DEBUG_LEVEL $VERBOSE_WARNING "Warning: No logs found for Rule ID $rule_id on $today_date."
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Parse the JSON-like string to extract the required information
    active_response=$(echo "$last_log" | grep -oP '"program":"\K[^"]+')
    agent_id=$(echo "$last_log" | grep -oP '"agent":{"id":"\K[^"]+')
    technique=$(echo "$last_log" | grep -oP '"technique":\["\K[^"]+')
    frequency=$(echo "$last_log" | grep -oP '"frequency":\K\d+')
    log_timestamp=$(echo "$last_log" | grep -oP '"timestamp":"\K[^"]+')

    # Check if all required fields are extracted
    if [ -z "$active_response" ] || [ -z "$agent_id" ] || [ -z "$technique" ] || [ -z "$frequency" ]; then
        log $DEBUG_LEVEL $VERBOSE_WARNING "Warning: Failed to extract some fields from the log entry."
        ERROR_COUNT=$((ERROR_COUNT + 1))
    fi

    # Extract time from the log timestamp using the extract_time function
    log_time=$(extract_time "$log_timestamp")

    # Log the time of last log retrieval and any delay
    log $DEBUG_LEVEL $VERBOSE_INFO "Last log retrieved at time: $log_time"

    # Log the extracted details using the log function
    if [ -n "$active_response" ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Active Response: $active_response"
    else
        log $DEBUG_LEVEL $VERBOSE_WARNING "Active Response: Not available"
    fi

    if [ -n "$agent_id" ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Agent ID: $agent_id"
    else
        log $DEBUG_LEVEL $VERBOSE_WARNING "Agent ID: Not available"
    fi

    if [ -n "$technique" ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Attack Technique: $technique"
    else
        log $DEBUG_LEVEL $VERBOSE_WARNING "Attack Technique: Not available"
    fi

    if [ -n "$frequency" ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Frequency: $frequency"
    else
        log $DEBUG_LEVEL $VERBOSE_WARNING "Frequency: Not available"
    fi

    # Get the current time in HH:MM:SS format
    current_time=$(date +"%H:%M:%S")

    # Convert both times to seconds since the start of the day for comparison
    log_seconds=$(date -d "$log_time" +"%s")
    current_seconds=$(date -d "$current_time" +"%s")

    # Calculate the difference in seconds
    time_difference=$((current_seconds - log_seconds))

    # Check if the difference is less than 5 minutes (300 seconds)
    if [ "$time_difference" -lt 300 ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "The log time is less than 5 minutes ago: $time_difference seconds"
    else
        log $DEBUG_LEVEL $VERBOSE_WARNING "Warning: The log time is more than 5 minutes ago: $time_difference seconds"
    fi

    return 0
}

# HERE XML functions #
# INFO : All this functions consider that there is only one ossec_config tag !
add_command() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local name="$1"
    local executable="$2"
    local timeout_allowed="$3"
    local path="${4:-/var/ossec/etc/ossec.conf}"

    # Check if the command is already present
    if grep -q "<name>${name}</name>" "$path"; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Command '${name}' is already activated in Wazuh."
        return 0
    fi

    local command_block="<command>\n  <name>${name}</name>\n  <executable>${executable}</executable>\n  <timeout_allowed>${timeout_allowed}</timeout_allowed>\n</command>"

    sudo sed -i "/<\/ossec_config>/i ${command_block}" "$path"
    if [ $? -eq 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Command '${name}' activated successfully in Wazuh."
    else
        log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to activate command '${name}' in Wazuh."
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi
}

add_active_response() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local command=$1
    local location=$2
    local rules_id=$3
    local timeout=$4
    local path="${5:-/var/ossec/etc/ossec.conf}"

    # Check if the required arguments are provided
    if [ -z "$command" ] || [ -z "$location" ] || [ -z "$rules_id" ] || [ -z "$timeout" ] || [ -z "$path" ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Usage: add_active_response <command> <location> <rules_id> <timeout> <config_file>"
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Check if the config file exists
    if [ ! -f "$path" ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Config file $path does not exist."
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Create the active response block
    local active_response_block="<active-response>\n  <command>${command}</command>\n  <location>${location}</location>\n  <rules_id>${rules_id}</rules_id>\n  <timeout>${timeout}</timeout>\n</active-response>"


    # Check if the active response block already exists
    if grep -q "<command>${command}</command>" "$path" && grep -q "<location>${location}</location>" "$path" && grep -q "<rules_id>${rules_id}</rules_id>" "$path" && grep -q "<timeout>${timeout}</timeout>" "$path"; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Active response block with command '${command}', location '${location}', rules_id '${rules_id}', and timeout '${timeout}' is already activated in Wazuh."
        return 0
    fi
    # Insert the new block before the closing </ossec_config> tag
    sed -i "/<\/ossec_config>/i ${active_response_block}" "$path"

    # Check if the sed command succeeded
    if [ $? -eq 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Active response with rules_id '${rules_id}' activated successfully in Wazuh."
    else
        log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to activate active response with rules_id '${rules_id}' in Wazuh."
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi
}


# Example usage:
# add_command "firewall-drop" "firewall-drop" "yes"
# add_active_response "firewall-drop" "local" "5763" "180"
# Function to add local rules
# Example usage
# add_local_rules "$RULES_FILE_PATH" "$local_rules_path"
add_local_rules(){
     # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Adding local rules ..."

    local rules_file_path="$1"
    local path="${2:-/var/ossec/etc/rules/local_rules.xml}"
    local group_name

    # Check if the rules file exists
    if [ ! -f "$rules_file_path" ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Rules file '$rules_file_path' does not exist."
        ERROR_COUNT=$((ERROR_COUNT + 1))
return 1
    fi

    # Extract the group name from the rules file
    group_name=$(grep -oP '<group name="\K[^"]+' "$rules_file_path")

    # Check if the group name is already present in the local_rules.xml file
    if grep -q "<group name=\"${group_name}\"" "$path"; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Group '${group_name}' is already present in $path. Not changing."
    else
        # Concatenate the contents of the rules_file to the local_rules.xml file
        cat "$rules_file_path" | sudo tee -a "$path" > /dev/null
        if [ $? -eq 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Group '${group_name}' activated successfully in Wazuh."
        else
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to activate group '${group_name}' in Wazuh."
            ERROR_COUNT=$((ERROR_COUNT + 1))
return 1
        fi
    fi
}
# Function to add a <localfile> tag to the ossec.conf file
# Example usage , default path to ossec.conf.
# add_local_file "syslog" "$PATH_TO_TELER_LOGS" "/var/ossec/etc/ossec.conf"
#NOTE : template for a adding function , nothing else !
add_local_file() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local log_format=$1
    local path_local_file=$2
    local path_config_file="${3:-/var/ossec/etc/ossec.conf}"

    # Check if the required arguments are provided
    if [ -z "$log_format" ] || [ -z "$path_local_file" ] || [ -z "$path_config_file" ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Usage: add_local_file <log_format> <path_local_file> <config_file>"
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Check if the config file exists
    if [ ! -f "$path_config_file" ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Config file $path_config_file does not exist."
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Check if the localfile tag already exists
    if grep -q "<location>$path_local_file</location>" "$path_config_file"; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Localfile tag for $path_local_file already exists in $path_config_file"
        return 0
    fi

    # Create the localfile tag
    local localfile_block="  <localfile>\n    <log_format>$log_format</log_format>\n    <location>$path_local_file</location>\n  </localfile>"

    # Use a temporary file to handle the multi-line insertion
    local temp_file=$(mktemp)
    echo "$localfile_tag" > "$temp_file"

    # Insert the localfile tag before the closing </ossec_config> tag
    sudo sed -i "/<\/ossec_config>/i ${localfile_block}" "$path_config_file"

    # Check if the sed command succeeded
    if [ $? -eq 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Added localfile tag to $path_config_file"
    else
        log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to add localfile tag to $path_config_file"
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    fi

    # Clean up the temporary file
    rm "$temp_file"
}







# Function to change level rules for web_rules
change_level_rules() {
  local rule_id=$1
  local level=$2
  local path_config_file="${3:-/var/ossec/etc/ossec.conf}"

  log $DEBUG_LEVEL $VERBOSE_DEBUG "Changing level for rule $rule_id to $level in $path_config_file..."
  sudo sed -i "s/<rule id=\"$rule_id\" level=\"[0-9]*\"/<rule id=\"$rule_id\" level=\"$level\"/g" $path_config_file
  if [ $? -eq 0 ]; then
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Rule level changed successfully."
  else
    log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to change rule level."
    ERROR_COUNT=$((ERROR_COUNT + 1))
  fi
}

# Function to enable log archive
enable_log_archive() {
  local path_config_file="${1:-/var/ossec/etc/ossec.conf}"

  log $DEBUG_LEVEL $VERBOSE_DEBUG "Enabling log archive in $path_config_file..."
  sudo sed -i 's/<logall>no<\/logall>/<logall>yes<\/logall>/g' $path_config_file
  if [ $? -eq 0 ]; then
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Log archive enabled successfully."
  else
    log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to enable log archive."
    ERROR_COUNT=$((ERROR_COUNT + 1))
  fi
}

# Function to add list to ossec.conf
add_list() {
  local list_file=$1
  local path_config_file="${2:-/var/ossec/etc/ossec.conf}"

  # Check if the list already exists in the file
  if grep -q "<list>$list_file</list>" "$path_config_file"; then
    log $DEBUG_LEVEL $VERBOSE_DEBUG "List $list_file already exists in $path_config_file. Skipping addition."
  else
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Adding list $list_file to $path_config_file..."
    sudo sed -i '/<ruleset>/a \ \ \ \ <list>'$list_file'</list>' $path_config_file
    if [ $? -eq 0 ]; then
      log $DEBUG_LEVEL $VERBOSE_DEBUG "List added successfully."
    else
      log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to add list."
      ERROR_COUNT=$((ERROR_COUNT + 1))
    fi
  fi
}

#HERE Cron jobs & Synchronization

# Main function to synchronize files
# Function to restart the appropriate Wazuh service
restart_wazuh_service() {
    local BACKUP_FILE=$1
    local DESTINATION_PATH=$2
    
    # Check if Wazuh Manager service exists
    if systemctl list-units --type=service | grep -q "wazuh-manager.service"; then
        SERVICE_NAME="wazuh-manager"
    elif systemctl list-units --type=service | grep -q "wazuh-agent.service"; then
        SERVICE_NAME="wazuh-agent"
    else
        log $DEBUG_LEVEL $VERBOSE_CRITICAL "No Wazuh service detected. Ensure Wazuh is installed."
        return 1
    fi
    
    # Attempt to restart the detected service
    if ! sudo systemctl restart "$SERVICE_NAME"; then
        # If the service restart failed, restore the backup
        log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to restart $SERVICE_NAME. Restoring original file."
        if ! restore_backup "$BACKUP_FILE" "$DESTINATION_PATH"; then
            log $DEBUG_LEVEL $VERBOSE_CRITICAL "Backup restoration failed. Manual intervention required."
            return 1
        fi
        log $DEBUG_LEVEL $VERBOSE_INFO "Restored the original file from backup after service failure."
        return 1
    fi
    
    log $DEBUG_LEVEL $VERBOSE_INFO "Successfully restarted $SERVICE_NAME."
    return 0
}

# Main function to synchronize files
synchronize_file() {
    local SOURCE_PATH=$1
    local DESTINATION_PATH=$2
    local LOG_FILE=$PATH_TO_CRON_JOB_LOGS
    local TMP_DIR="/tmp/ossec_conf_backup"  # Temporary directory for backups
    local BACKUP_FILE="$TMP_DIR/$(basename $DESTINATION_PATH).bak"

    # Initialize error flag
    local error_occurred=0

    # Ensure the tmp backup directory exists
    sudo mkdir -p "$TMP_DIR"

    # Back up the existing file if it exists
    back_up_file "$DESTINATION_PATH" "$BACKUP_FILE"
    if [ $? -ne 0 ]; then
        error_occurred=1
    fi

    # Create the destination directory if it doesn't exist
    sudo mkdir -p "$(dirname "$DESTINATION_PATH")"

    # Copy the file to the destination
    sudo cp "$SOURCE_PATH" "$DESTINATION_PATH"
    if [ $? -ne 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to copy file to $DESTINATION_PATH"
        error_occurred=1
    fi

    # Change the file permissions
    sudo chmod 640 "$DESTINATION_PATH"
    if [ $? -ne 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to change permissions of file"
        error_occurred=1
    fi

    # Check if any errors occurred and decide what to do
    if [ $error_occurred -eq 1 ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "One or more errors occurred. See log at $LOG_FILE"
        
        # Restore the original file if it was backed up
        restore_backup "$BACKUP_FILE" "$DESTINATION_PATH"
        if [ $? -ne 0 ]; then
            return 1
        fi
        
        return 1
    else
        log $DEBUG_LEVEL $VERBOSE_INFO "Successfully synchronized $SOURCE_PATH with $DESTINATION_PATH - see $LOG_FILE"
        
        # Restart the appropriate Wazuh service
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Restarting service..."
        if ! restart_wazuh_service "$BACKUP_FILE" "$DESTINATION_PATH"; then
            return 1
        fi
        
        # Clean up the backup after successful restart
        sudo rm -f "$BACKUP_FILE"
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Service restarted successfully"

        return 0
    fi
}




# -------------------------------------------------
# HERE: Docker
# -------------------------------------------------

install_docker() {
     # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Checking if Docker is installed..."
    if ! command -v docker &> /dev/null; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Installing Docker..."
        curl -fsSL https://get.docker.com | bash 2>&1 >/dev/null
        if [ $? -eq 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Docker installed successfully."
        else
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to install Docker."
            ERROR_COUNT=$((ERROR_COUNT + 1))
        fi
    else
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Docker is already installed."
    fi
}

# DVWA 
run_dvwa_container() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Checking if DVWA container is already running..."

    # Check if the DVWA container is already running
    if docker ps --format '{{.Names}}' | grep -q 'vulnerables/web-dvwa'; then
        log $DEBUG_LEVEL $VERBOSE_WARNING "DVWA container is already running. Skipping container startup."
        return 0
    fi

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running DVWA container..."
    output=$(docker run --rm -d -v /var/log/teler/:/var/log/apache2/ -p 80:80 vulnerables/web-dvwa 2>&1)
    if [ $? -eq 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "DVWA container running successfully."
    else
        if echo "$output" | grep -q "Bind for 0.0.0.0:80 failed: port is already allocated"; then
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Port 80 is already allocated. Skipping container startup."
        else
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to run DVWA container: $output"
            ERROR_COUNT=$((ERROR_COUNT + 1))
        fi
    fi
}



# -------------------------------------------------
# HERE: Teller
# -------------------------------------------------

install_teler() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    # Define the Teler installation directory
    local teler_dir="/teler"

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Checking if Teler is installed..."
    if ! command -v $teler_dir/teler &> /dev/null; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Installing Teler..."

        # Create the Teler directory if it doesn't exist
        mkdir -p $teler_dir

        # Change to the Teler directory
        cd $teler_dir

        # Download and extract Teler
        wget https://github.com/kitabisa/teler/releases/download/v2.0.0-rc.3/teler_2.0.0-rc.3_linux_amd64.tar.gz
        tar -xvzf teler_2.0.0-rc.3_linux_amd64.tar.gz

        if [ $? -eq 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Teler installed successfully."
            # Clean up the tar file
            rm teler_2.0.0-rc.3_linux_amd64.tar.gz
        else
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to install Teler."
            ERROR_COUNT=$((ERROR_COUNT + 1))
        fi
    else
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Teler is already installed."
    fi
}



configure_teler() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local teler_logs=$1
    local teler_dir="/teler"

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Checking Teler settings..."

    if [ ! -f $teler_dir/teler.yml ]; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Configuring Teler settings..."
        cat <<EOF > $teler_dir/teler.yml
log_format: |
  \$remote_addr - \$remote_user [\$time_local] "\$request_method \$request_uri \$request_protocol" \$status \$body_bytes_sent "\$http_referer" "\$http_user_agent"
logs:
  file:
    active: true
    json: true
    path: $PATH_TO_TELER_LOGS
EOF
        if [ $? -eq 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Teler settings configured successfully."
        else
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to configure Teler settings."
            ERROR_COUNT=$((ERROR_COUNT + 1))
        fi
    else
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Teler settings already configured."
    fi
}



# HERE Responsive measures #
ensure_reachability() {
    local defender_ip="$1"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Checking if the $defender_ip is reachable..."

    # Ping the defender IP
    ping -c 4 $defender_ip

    if [ $? -eq 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_DEBUG "$defender_ip is reachable."
    else
        log $DEBUG_LEVEL $VERBOSE_ERROR "$defender_ip is not reachable."
        ERROR_COUNT=$((ERROR_COUNT + 1))
    fi
}


# Check if the target is still reachable

ensure_unreachability() {
    local defender_ip="$1"

    log $DEBUG_LEVEL $VERBOSE_DEBUG "Checking if the target is still reachable..."
    ping -c 4 $DEFENDER_IP
    if [ $? -eq 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_ERROR "Target is still reachable after the attack"
            ERROR_COUNT=$((ERROR_COUNT + 1))
    else
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Target is no more reachable."

    fi
}

# HERE OTHERS #
check_and_install_package(){
     # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"
    # Example usage:
    # check_and_install_package "hydra" 

    local package="$1"

    # Check if the package is installed
    if ! command -v "$package" &> /dev/null; then
        log $DEBUG_LEVEL $VERBOSE_WARNING "$package is not installed. Installing $package..."
        sudo apt update && sudo apt install -y "$package"
        if [ $? -eq 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_DEBUG "$package installed successfully."
        else
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to install $package."
            ERROR_COUNT=$((ERROR_COUNT + 1))
return 1
        fi
    else
        log $DEBUG_LEVEL $VERBOSE_DEBUG "$package is already installed."
    fi
}

# Function to create or clear the log file with proper permissions
initialize_log_file(){
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"
    
    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local log_file="$1"
    
    if [ ! -f "$log_file" ]; then
        # Create the log file if it does not exist
        touch "$log_file"
        log $DEBUG_LEVEL $VERBOSE_INFO "Log file created: $log_file"
        
        
    else
        # Clear the log file if it exists
        > "$log_file"
        log $DEBUG_LEVEL $VERBOSE_INFO "Log file cleared: $log_file"
    fi

    # Set appropriate permissions and ownership
    chmod 0644 "$log_file"  # Read/write for owner, read for others
    log $DEBUG_LEVEL $VERBOSE_INFO "Permissions set: 0644, Owner: $USER"
}



# Function to check for the existence of files
check_file_existence() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local files=("$@")
    local number_of_file_not_found=0

    for file in "${files[@]}"; do
        if [ ! -f "$file" ]; then
            log $DEBUG_LEVEL $VERBOSE_WARNING "File not found: $file. Creating the file."
            touch "$file"
            number_of_file_not_found=$((number_of_file_not_found + 1))
        else
            log $DEBUG_LEVEL $VERBOSE_DEBUG "File found: $file"
        fi
    done

    if [ $number_of_file_not_found -gt 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Total warnings: $number_of_file_not_found"
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    else
        log $DEBUG_LEVEL $VERBOSE_INFO "All files found."
        return 0
    fi
}

check_folder_existence() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    local folders=("$@")
    local number_of_folders_not_found=0

    for folder in "${folders[@]}"; do
        if [ ! -d "$folder" ]; then
            log $DEBUG_LEVEL $VERBOSE_WARNING "Folder not found: $folder. Creating the folder."
            mkdir -p "$folder"
            number_of_folders_not_found=$((number_of_folders_not_found + 1))
        else
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Folder found: $folder"
        fi
    done

    if [ $number_of_folders_not_found -gt 0 ]; then
        log $DEBUG_LEVEL $VERBOSE_INFO "Total warnings: $number_of_folders_not_found"
        ERROR_COUNT=$((ERROR_COUNT + 1))
        return 1
    else
        log $DEBUG_LEVEL $VERBOSE_INFO "All folders found."
        return 0
    fi
}

## Function to back up the file to a temporary folder
back_up_file() {
    local DESTINATION_PATH=$1
    local BACKUP_FILE=$2
    
    if [ -f "$DESTINATION_PATH" ]; then
        sudo cp "$DESTINATION_PATH" "$BACKUP_FILE"
        if [ $? -ne 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to back up $DESTINATION_PATH to $BACKUP_FILE"
            return 1
        fi
    fi
    return 0
}

# Function to restore the backup file
restore_backup() {
    local BACKUP_FILE=$1
    local DESTINATION_PATH=$2
    
    if [ -f "$BACKUP_FILE" ]; then
        sudo cp "$BACKUP_FILE" "$DESTINATION_PATH"
        if [ $? -ne 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_ERROR "Failed to restore the backup file from $BACKUP_FILE to $DESTINATION_PATH"
            return 1
        fi
    fi
    return 0
}


# HERE test for conf files : 
test_conf_file() {
    # Capture the current function's name
    local function_name="${FUNCNAME[0]}"

    # Log the function execution
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Running function $function_name"

    # Parameters passed to the function
    local conf_file=$1
    local is_agent=$2

    # Log the received conf_file path
    log $DEBUG_LEVEL $VERBOSE_DEBUG "Received conf_file path: $conf_file"

    # Define commands for verification
    declare -A commands
    if [ "$is_agent" = "true" ]; then
        # Commands for the agent
        commands["wazuh-agentd"]="wazuh-agentd -t -f -c $conf_file"
        commands["wazuh-syscheckd"]="wazuh-syscheckd -t -f -c $conf_file"
        commands["wazuh-logcollector"]="wazuh-logcollector -t -f -c $conf_file"
        commands["wazuh-modulesd"]="wazuh-modulesd"
    else
        # Commands for the manager
        commands["wazuh-analysisd"]="wazuh-analysisd -t -f -c $conf_file"
        commands["wazuh-syscheckd"]="wazuh-syscheckd -t -f -c $conf_file"
        commands["wazuh-logcollector"]="wazuh-logcollector -t -f -c $conf_file"
        commands["wazuh-modulesd"]="wazuh-modulesd"
    fi

    # Execute each command and check the result
    for cmd_name in "${!commands[@]}"; do
        log $DEBUG_LEVEL $VERBOSE_DEBUG "Verifying configuration with: $cmd_name"
        /var/ossec/bin/${commands[$cmd_name]}
        if [ $? -ne 0 ]; then
            log $DEBUG_LEVEL $VERBOSE_ERROR "Error: Command '$cmd_name' failed."
            exit 1
        else
            log $DEBUG_LEVEL $VERBOSE_DEBUG "Command '$cmd_name' verified successfully."
        fi
    done
}

