#! /bin/bash
#
# If anyone spots any bugs or flaws or has an improvement to suggest, please email details to robinj@learningtree.com. Thanks.
# I realize layout is not optimal, but bash scripting is not one of my strong points! This is just a case of what works goes.
#
# REQUIRES CURL, ZENITY AND JQ TO BE INSTALLED
# sudo apt install curl zenity jq -f
#
# This tool tries to pull the Class-ID from metadata and the make an API call to retrieve Class Info an then ultimately the OpenAI key
# Basic operation
# 1. Pull class-id from the metadata
# 2. Try and connect to API
# 3. Get class info that contains class name - not available in metadata on students!!!
# 4. Use class name to find training data and pull OPENAI_API_KEY from there
# 5. Verify key
# 6. Replace/Insert key in appropriate files
# 7. Quit

# OPTIONAL ITEMS
# Scroll down and some optional items you can comment in or out with #
# Option to disable info popups for silent operation
if [[ "$1" == *"-s"* || "$1" == *"/s"* ]]; then
    SETPOPUPS=
else
    SETPOPUPS=YES
fi

logfile=$(dirname "$0")"/OpenAI_Import.log"
log() {
  echo "$1"
  echo "$1">>$logfile
}
echo Starting OpenAI_Import V2.0 -- $(date)>$logfile

# Check to see if what we need is installed

# Check if curl is installed
if ! command -v curl >/dev/null 2>&1; then
    log "curl is not installed. Please install it first."
    exit 1
fi

# Check if jq is installed
if ! command -v jq >/dev/null 2>&1; then
    log "jq is not installed. Please install it first."
    exit 1
fi

# Check if zenity is installed
if ! command -v zenity &> /dev/null; then
    log "zenity is not installed. Please install it first."
    exit 1
fi

# Pull the course-sequence combo from the freely available metadata
# ENVNAME=$(/usr/bin/curl -s -X GET "https://metadata.cloudshare.com/api/v3/unauthenticated/metadata" | jq -r '."env-name"')
# ENV=$(echo $ENVNAME| grep -oE '\b[A-Za-z0-9]{3,4}-[A-Za-z0-9]{8}\b')
CLASSID=$(/usr/bin/curl -s -X GET "https://metadata.cloudshare.com/api/v3/unauthenticated/metadata" | jq -r '."class-id"')
STATUS=$?
if [ $STATUS -ne 0 ]; then
  log "Error: metadata unavailable (exit code $STATUS). Likely a timeout or network issue."
  exit 1
fi

log;log "Debug values extracted from Cloudshare Metadata";log
# log ": The course-sequence number pulled is: $ENV"
log ": The class-id pulled is: $CLASSID"

if [ -z "$CLASSID" ] || [ "$CLASSID" == "null" ]; then
  log;log "Error: No classid found in metadata, exiting."
  # SHOULD PROBABLY WAIT HERE INCASE IT IS NOT INSTANTLY THERE
  exit 1
fi

OPENAI=$(/usr/bin/curl -s -X GET "https://metadata.cloudshare.com/api/v3/unauthenticated/metadata" | jq -r '.["custom-properties"].openAIKey')
if [ -z "$OPENAI" ] || [ "$OPENAI" == "null" ]; then
  # --- Basic Auth and OAuth2 Configuration - No easy way to hide key so will compile ---
  OAUTH2_TOKEN_URL="https://api.accelerate.cloudshare.com/v4/oauth/token"
  CLIENT_ID="538GACRZ9FABA07E"
  CLIENT_SECRET="bkAyYSB3dL8GREF87zfqhjkUcW5xNSVyj0HDpQBqheX5vcHpbLE8WXqYjGmGMORt"
  API_URL1="https://use.cloudshare.com/api/v3/class/${CLASSID}"
  API_URL2="https://api.accelerate.cloudshare.com/v4/trainings?name=contains"
  URL="https://use.cloudshare.com/api/v3/envs"

  # --- First basic auth request to V3 API to get class info

  TIMESTAMP=$(date +%s)
  TOKEN=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 10 ; echo '')

  HMAC_INPUT_RAW="${CLIENT_SECRET}${API_URL1}${TIMESTAMP}${TOKEN}" # Concatenate without newlines
  HMAC=$(echo -n "${HMAC_INPUT_RAW}" | sha1sum | awk '{print $1}')
  AUTH_PARAM="userapiid:${CLIENT_ID};timestamp:${TIMESTAMP};token:${TOKEN};hmac:${HMAC}"

  RESPONSE=$(curl -s -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: cs_sha1 ${AUTH_PARAM}" -X GET "${API_URL1}")

  ENV=$(echo "$RESPONSE" | jq -r '.name')
  log ": Class name pulled from API is: ${ENV}"

  # Requesting OAuth2 Access Token
  # Prepare the request body for the token endpoint
  POST_DATA="grant_type=client_credentials&client_id=${CLIENT_ID}&client_secret=${CLIENT_SECRET}"

  TOKEN_RESPONSE=$(curl -s -X POST \
    -H "Content-Type: application/x-www-form-urlencoded" \
    -d "${POST_DATA}" \
    "${OAUTH2_TOKEN_URL}")

  # Check if the token request was successful and extract the access token
  ACCESS_TOKEN=$(echo "${TOKEN_RESPONSE}" | jq -r '.access_token')
  TOKEN_TYPE=$(echo "${TOKEN_RESPONSE}" | jq -r '.token_type')
  EXPIRES_IN=$(echo "${TOKEN_RESPONSE}" | jq -r '.expires_in')

  if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" == "null" ]; then
    log;log "Error: Failed to obtain OAuth2 Access Token."
    # SHOWING TOKEN COULD ALLOW SOMEONE TO ACCESS CLOUDSHARE
    # log "Full Response: ${TOKEN_RESPONSE}"
    CLIENT_ID=""
    CLIENT_SECRET=""
    exit 1
  fi

  log ": Cloudshare API access token obtained successfully!"
  # SHOWING TOKEN COULD ALLOW SOMEONE TO ACCESS CLOUDSHARE
  # log ": Token Response: ${TOKEN_RESPONSE}"
  log ": Token Type: ${TOKEN_TYPE}"
  log ": Expires In: ${EXPIRES_IN} seconds"
  # log "Access Token (for debug, but be careful logging sensitive info): ${ACCESS_TOKEN}"

  # Making API call with Access Token
  # Make the actual API call using the obtained Access Token
  RESPONSE=$(curl -s -H "Accept: application/json" \
      -H "Content-Type: application/json" \
      -H "Authorization: ${TOKEN_TYPE} ${ACCESS_TOKEN}" \
      -X GET "${API_URL2}(${ENV})")

  # echo ${RESPONSE} | jq

  DESCRIPTION=$(echo "${RESPONSE}" | jq -r '.items[0].description')
  OPENAI=$(echo "$DESCRIPTION" |cut -f2 -d'=')
  CLIENT_ID=""
  CLIENT_SECRET=""

  # echo "${RESPONSE}"
  # echo ""
  log ": Description field pulled is: ${DESCRIPTION}"
  log ": Pulled value to use is: ${OPENAI}"
else
  log ": OpenAI key pulled from metadata custom-properties: ${OPENAI}"
fi

# Check we have an OpenAI key first
if [ -z "$OPENAI" ]; then
  log "No key provided in VM metadata"
  exit 1
fi

# OPTIONAL CODE THAT PUTS UP GUI WHEN RUN ON BOOT
if ! [ -z ${SETPOPUPS} ]; then 
  zenity --question --title="OpenAI Key" --text="Do you wish to install the course OpenAI key?\n\n    (times out to YES after 120 seconds)" --timeout=120
  case $? in
      1)
      	log;log "Exited without installing the key"
        exit
      ;;
  esac
fi

# Should have the params we need from skytap now, lets find the correct file and add the Key

#1216		/home/student/.config/shell_gpt/.sgptrc					Boleslav Sykora
#*1258		/home/.bashsrc (hidden file) - Replace API Key in the last line.	Imran Ahmad - *Anup tested and confirmed that NO API KEY IS REQUIRED for 1258!
#1293		/home/student/keys/key.txt	WAS - /home/.bashsrc (hidden file) - Replace API Key in the last line.	Imran Ahmad
#1296		/home/student/keys/key.txt							Alastair Brown, Imran Ahmad
#1297		/home/student/Keys/Key.txt (copied from 1296)					Alastair Brown, Anup Kumar
#4703		/home/.bashsrc (hidden file) - Replace API Key in the last line.	Imran Ahmad
#526A (1293)	/home/student/keys/key.txt	WAS - /home/.bashsrc (hidden file) - Replace API Key in the last line.	Joshua Sigal
#536R (1293)	/home/student/keys/key.txt	WAS - /home/.bashsrc (hidden file) - Replace API Key in the last line.	Imran Ahmad

#List of files that will be looked for and edited if found...
#Search and replace line with OPENAI_API_KEY= in it with new version
FILES="/home/student/.config/shell_gpt/.sgptrc"
for f in $FILES
do
# Check if "$f" FILE exists and is a regular file and then edit it
  if [ -f "$f" ]
  then
    sed -i 's/OPENAI_API_KEY=.*/OPENAI_API_KEY='$OPENAI'/' "$f"
    log ": Edited OpenAI key into file $f"
    EDITED=TRUE
  else
    log ": Did not locate file $f"
  fi
done

FILES="/home/.bashsrc
/home/student/.bashrc"
for f in $FILES
do
# Check if "$f" FILE exists and is a regular file and then edit it
  if [ -f "$f" ]
  then
    sed -i 's/OPENAI_API_KEY=.*/OPENAI_API_KEY="'$OPENAI'"/' "$f"
    log ": Edited OpenAI key into file $f"
    EDITED=TRUE
  else
    log ": Did not locate file $f"
  fi
done

#Recreate these files so they just contain the key
FILES="/home/student/keys/key.txt
/home/student/Keys/Key.txt
/home/keys/key.txt"
for f in $FILES
do
# Check if "$f" FILE exists and is a regular file and then replace it
  if [ -f "$f" ]
  then
    echo $OPENAI > "$f"
    log ": Inserted OpenAI key into file $f"
    EDITED=TRUE
  else
    log ": Did not locate file $f"
  fi
done

# OPTIONAL CODE THAT PUTS UP GUI WHEN RUN ON BOOT
#if [ ! [ -z ${SETPOPUPS} ] &&  ! [ -z ${EDITED}] ]
if [[ -n "$SETPOPUPS" && -n $EDITED ]]
then 
  zenity --info --title="OpenAI Key" --text="The OpenAI key has been updated" --timeout=120
fi

log;log "All listed files have been edited if found, Exiting"

exit


