#!/bin/bash
set -eo pipefail

#-----------------------------#
# Author: SpotQA 
# Contact: support@spotqa.com, 
# Title: Example script for triggering Virtuoso APIs to execute journeys in a planner
# Requirements: This script requires curl and jq to be installed.
# Last modified: 21/02/2023
#-----------------------------#

if [ $# -eq 0 ]; then
    echo "Usage: ./execute.sh -t VIRTUOSO_TOKEN --plan_id ID_OF_PLAN_TO_EXECUTE [--env_id ENVIRONMENT_ID] [--staging] [--app2] [--max_retry_time MAX_RETRY_TIME] [--retry_delay_time RETRY_DELAY_TIME]"
    exit 1
fi

# Check for support
if ! type "jq" > /dev/null; then
  echo "jq needs to be installed. See: https://stedolan.github.io/jq/download/"
  exit 1
fi

if ! type "curl" > /dev/null; then
  echo "curl needs to be installed."
  exit 1
fi

ENV="api"
UI="app"
MAX_RETRY_TIME=300
RETRY_DELAY_TIME=10

# Set arguments
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"

case $key in
    -u|--user)
    VIRTUOSO_USER="$2"
    shift
    shift
    ;;
    -p|--password)
    VIRTUOSO_PASSWORD="$2"
    shift
    shift
    ;;
    -t|--token)
    VIRTUOSO_TOKEN="$2"
    shift
    shift
    ;;
    -pl|--plan_id)
    PLAN_ID="$2"
    shift
    shift
    ;;
    --env_id)
    ENVIRONMENT_ID="$2"
    shift
    shift
    ;;
    --max_retry_time) # Optional param
    MAX_RETRY_TIME=$2
    shift
    shift
    ;;
    --retry_delay_time) # Optional param
    RETRY_DELAY_TIME=$2
    shift
    shift
    ;;
    --staging) # Optional param
    ENV="api-staging"
    UI="app-staging"
    shift
    ;;
    --app2) # Optional param
    ENV="api-app2"
    UI="app2"
    shift
    ;;
    *)
    POSITIONAL+=("$1")
    shift
    ;;
esac
done

# Login to virtuoso
TOKEN="$VIRTUOSO_TOKEN"
if [ -n "${VIRTUOSO_USER:-}" ]; then
  TOKEN=$(curl -s -X POST -H "Content-Type: application/json" -d '{ "email": "'$VIRTUOSO_USER'", "password":"'$VIRTUOSO_PASSWORD'"}' "https://$ENV.virtuoso.qa/api/auth/login?envelope=false" | jq -r .token)
fi

if [[ "$TOKEN" == "null" ]]; then
  echo "failed to login. Please check credentials and try again"
  exit 1
fi

if [ -z $PLAN_ID ] || [ "$PLAN_ID" == "null" ]; then
  echo "Target plan not found. Please supply that using: --plan_id 123 where 123 is your execution planner id."
  exit 1
fi

if [ -z $ENVIRONMENT_ID ]; then
  echo "Environment ID is required. Please supply that using: --env_id ENVIRONMENT_ID"
  exit 1
fi

# Launch execution
echo "Going to execute plan $PLAN_ID with environment ID $ENVIRONMENT_ID"

# Updated API request to include environmentId in the body
JOBS_INVOKED=($(curl -s --header "Authorization: Bearer $TOKEN" -X POST -H "Content-Type: application/json" -d '{ "environmentId": "'$ENVIRONMENT_ID'" }' "https://$ENV.virtuoso.qa/api/plans/executions/$PLAN_ID/execute?envelope=false" | jq -r .jobs[].id))

# Print all Jobs
echo "Invoked jobs are: "
echo "${JOBS_INVOKED[*]}"

TOTAL_JOBS=0

if [ -n "${JOBS_INVOKED:-}" ]; then
    TOTAL_JOBS=(${#JOBS_INVOKED[@]})
fi

echo "Total Jobs invoked: $TOTAL_JOBS"

# loop for all jobs to check the status and report results

RUNNING_ALL_JOBS=true

while [ $TOTAL_JOBS -gt 0 -a $RUNNING_ALL_JOBS ]; do  # loop AAA- Start

 # fetch JOB_ID from job array
 for i in ${JOBS_INVOKED[@]} 
 do 	 #BBB- Start

 JOB_ID=$i
 echo "-------- Checking Job Status of $JOB_ID --------"

  if [ -z $JOB_ID ] || [ "$JOB_ID" == "null" ]; then
    echo "Failed to execute job."
    continue
  fi

  set +e
  RUNNING_CURRENT_JOB=true
  OUTCOME=""

  while $RUNNING_CURRENT_JOB; do # loop CCC- Start
   ERROR=true
   RETRY_TIME=0;

   # As we poll for the status of the job, we need to ensure that a single API failure would not lead to failure of this entire script
   while $ERROR; do # loop DDD -Start
    JOB=$(curl -s --fail --header "Authorization: Bearer $TOKEN" "https://$ENV.virtuoso.qa/api/executions/$JOB_ID/status?envelope=false")
    if [ "$JOB" == "" ]; then
        if [ $MAX_RETRY_TIME -gt $RETRY_TIME ]; then
          echo "Request failed. Retrying..."
          RETRY_TIME=$(($RETRY_TIME + $RETRY_DELAY_TIME))
          ERROR=true
          sleep $RETRY_DELAY_TIME
        else
          echo "Failed to get job status... Try to re-run the job again."
          exit 2
        fi
    else
      ERROR=false
    fi
   done # loop DDD -Stop

   JOB_STATUS=$(echo $JOB | jq -r .status)
   OUTCOME=$(echo $JOB | jq -r .outcome)

   echo "Job execution status: $JOB_STATUS, outcome: $OUTCOME"

   if [ "$JOB_STATUS" == "FINISHED" ] || [ "$JOB_STATUS" == "CANCELED" ] || [ "$JOB_STATUS" == "FAILED" ]; then
	   RUNNING_CURRENT_JOB=false	
    else	
      sleep 2	
    fi
  done # loop CCC - Stop

  echo "--------"
  echo "Executed job $JOB_ID with outcome: $OUTCOME"
  ((TOTAL_JOBS--))

  set -e

  # Save execution result
  curl -s --header "Authorization: Bearer $TOKEN" "https://$ENV.virtuoso.qa/api/jobs/$JOB_ID/status?envelope=false" | jq -r '.' > "execution_report_$JOB_ID.json"

  echo "Exported tests and the report as tests.json, execution_report_$JOB_ID.json"
  echo "Execution link: https://$UI.virtuoso.qa/#/project/execution/$JOB_ID"

  # Different exit code for when job did not fail/error but status was not finished (cancelled/failed)
  if [ "$JOB_STATUS" != "FINISHED" ]; then
   echo "Job status is not finished..."
   continue
  fi

  # terminate unsuccessfully if job did not pass
  if [ "$OUTCOME" == "FAIL" ] || [ "$OUTCOME" == "ERROR" ]; then
   echo "Job is not passed, outcome is fail or error"
   continue
  fi

 done # loop BBB- Stop

  # check if all jobs are completed 
  if [ "$TOTAL_JOBS" == 0 ]; then
   RUNNING_ALL_JOBS=false
   echo "All jobs are finished..."
  fi

done # loop AAA-Stop

echo "Done!"
