#!/bin/bash

# This script calls the redelivery endpoint on the message service
# Usage e.g. : ./as4_messages_re-delivery.sh

# Optional oAuth2 usage
# Ensure that the user's keycloak username and password is set in the following env variables: KEYCLOAK_USERNAME, KEYCLOAK_PASSWORD,

# Pre-requisites:
# * curl installed (command line tool)
# * date installed (command line tool)

# Stop script execution on error
set -e

# Edit following constants as needed

# Message service URL
AS4_MESSAGE_SERVICE_URL="http://localhost:8099/aep-as4-message-service"
REDELIVERY_PATH="/as4-message/redelivery"

AS4_MESSAGE_REDELIVERY_API=$AS4_MESSAGE_SERVICE_URL$REDELIVERY_PATH

#-------------------------
# oAuth2 configuration

USE_OAUTH2="y"
AUTH_SERVER_URL="http://host.docker.internal:9000/auth/realms/as4/protocol/openid-connect/token"
CLIENT_ID="as4-message-service"
USERNAME=$KEYCLOAK_USERNAME
PASSWORD=$KEYCLOAK_PASSWORD

# ------------------------
# Important parameters for redelivery:

# Max messages per **minute** to process
MAX_MESSAGES=60

# Value is in seconds (determines how many intervals) - default is 1 minute time slices [can be extended to minutes, hours, days]
TIME_SLICE=60

# This represents +02:00 (Europe/Berlin)
TIMEZONE="UTC-2"

# Messages to select based on time range (created date of message) Format: yyyy-MM-ddTHH:mm:ss
START_DATE_TIME="2024-03-01T14:01:00"
END_DATE_TIME="2024-03-01T14:03:00"

# Re-delivery api parameters (uncomment and set value to include optional parameters)

#TENANTS_LIST="9903111000003,9900794000004"
#SERVICE_ID="http://docs.oasis-open.org/ebxml-msg/ebms/v3.0/ns/core/200704/service"
#DIRECTION="outbound"

# -----------START-------------- #

#### oAuth2 login #####

get_keycloak_token() {
  if [ "$USE_OAUTH2" = "y" ]; then
    echo "Request oauth2 Token"
    # Get keycloak access token first
    auth_response=$(curl --include --silent -X POST "$AUTH_SERVER_URL" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      -d "grant_type=password" \
      -d "client_id=$CLIENT_ID" \
      -d "username=$USERNAME" \
      -d "password=$PASSWORD" \
      -w "\n%{http_code}")

    auth_response_code=$(echo "$auth_response" | tail -n 1)
    echo -e "Response code of getting oauth2 access token: $auth_response_code\n"

    access_token=$(echo $auth_response | grep -o '"access_token":"[^"]*' | grep -o '[^"]*$')
    AUTHORIZATION_HEADER="Authorization: Bearer $access_token"

  elif [ "$USE_OAUTH2" = "n" ]; then
    echo -e "Skipping oauth2 token access\n"
    AUTHORIZATION_HEADER=""

  else
    echo "Invalid input for 'USE_OAUTH2'. Please enter 'y' or 'n'."
  fi
}

##### Call Message service #####

if [ -n "$TENANTS_LIST" ]; then
    tenant_list_parameter="\"tenants\": \"$TENANTS_LIST\","
fi

if [ -n "$SERVICE_ID" ]; then
    service_id_parameter="\"service\": \"$SERVICE_ID\","
fi

if [ -n "$DIRECTION" ]; then
    direction_parameter="\"direction\": \"$DIRECTION\","
fi


start_epoch_seconds=$(TZ="$TIMEZONE" date -d "${START_DATE_TIME}" +%s)
end_epoch_seconds=$(TZ="$TIMEZONE" date -d "${END_DATE_TIME}" +%s)

calculate_end_interval_seconds() {
  local start_interval_seconds_local=$1

  local outer_bound=$((end_epoch_seconds + TIME_SLICE))
  local end_interval_seconds=$((start_interval_seconds_local + TIME_SLICE))

  if [ $end_interval_seconds -gt $end_epoch_seconds ] && [ $end_interval_seconds -lt $outer_bound ]; then
    end_interval_seconds=$end_epoch_seconds
  fi

  # return end interval result
  echo "$end_interval_seconds"
}

current_time=$(date +%s)
next_keycloak_retrieval_time=$((current_time + 300))
get_keycloak_token

start_interval_seconds=$start_epoch_seconds
end_interval_seconds=$(calculate_end_interval_seconds $start_interval_seconds)
delay=0
while [ $end_interval_seconds -le $end_epoch_seconds ]; do

  if [ $delay -gt 0 ]; then
    echo -e "Adding delay of $delay seconds before next time slice\n"
    sleep $delay
  fi

  echo "Calling $REDELIVERY_PATH with following time interval:"

  start_interval_seconds_date=$(TZ="$TIMEZONE" date -d "@$start_interval_seconds" "+%Y-%m-%dT%H:%M:%S.%3N%:z")
  echo "Current start interval: $start_interval_seconds_date"

  end_interval_seconds_date=$(TZ="$TIMEZONE" date -d "@$end_interval_seconds" "+%Y-%m-%dT%H:%M:%S.%3N%:z")
  echo "Current end interval: $end_interval_seconds_date"

  # Check if keycloak token needs to be refreshed
  current_time=$(date +%s)
  if [ $current_time -ge $next_keycloak_retrieval_time ]; then
    next_keycloak_retrieval_time=$((current_time + 300))
    get_keycloak_token
  fi

  # Call API
  re_delivery_response=$(curl --silent --location "$AS4_MESSAGE_REDELIVERY_API" \
  --header "$AUTHORIZATION_HEADER" \
  --header "Content-Type: application/json" \
  --data "{
    $tenant_list_parameter
    $service_id_parameter
    $direction_parameter
    \"start\": \"$start_interval_seconds_date\",
    \"end\": \"$end_interval_seconds_date\"
  }" \
  -w " %{http_code}")

  echo -e "API response: $re_delivery_response"

  auth_response_code=$(echo "$re_delivery_response" | awk '{print $NF}')
  echo "HTTP status code: $auth_response_code"

  messages_processed=($(echo $re_delivery_response | grep -o '"redeliveredMessages":"[^"]*' | grep -o '[^"]*$'))
  echo -e "Messages successfully processed: $messages_processed\n"

  # Fraction can be returned from the division (which is in minutes) and it is multiplied by 60 to get the seconds delay
  delay=$(echo "$messages_processed $MAX_MESSAGES" | awk '{printf "%.0f", ($1/$2) * 60}')

  ## Prepare interval range for next loop and api call
  start_interval_seconds=$end_interval_seconds
  end_interval_seconds=$(calculate_end_interval_seconds $start_interval_seconds)

done
