#!/bin/bash

# Exit on error
set -e

echo "Updating projects"
DIR=$(pwd)
COMPOSER_CMD=$(which composer)
NOW=$(date +'%F')
UNIX_TIMESTAMP_MS=$(($(date -d "$NOW" '+%s')*1000))
cd $DIR
source "./vendor/fourkitchens/pots/scripts/security-updates/4k-openai-lib.sh"
BRANCH_NAME="feature/automated-sec-update-$NOW"

# 1. Load the JSON data in a variable.
JSON_DATA=$(jq -r)
# 2. Use jq to parse the JSON and extract the "advisories" object.
ADVISORIES=$(echo "$JSON_DATA" | jq '.advisories')

MESSAGE=""
TEST_STEPS=""
PROJECTS_UPDATED=""

# Helper function to check if branch exist on remote repository.
gh_branch_exist () {

# Check if branch already exists
  if [[ `git ls-remote --head origin $BRANCH_NAME` ]]; then
    echo "true"
    exit 1
  else
    # Branch does not yet exist
    echo "false"
  fi
}

# Creates a Git branch.
create_gh_branch () {
  # Create security update branch for $NOW
  cd $DIR
  git branch $BRANCH_NAME
  git checkout $BRANCH_NAME
  echo "true"
}

# Helper function to check if there are available sec update to apply.
security_updates_available () {
  # 3. Loop through each key-value pair in the "advisories" object.
  AVAILABLE_UPDATE="false"
  for PACKAGE_NAME in $(echo "$ADVISORIES" | jq -r 'keys | @sh'); do
    PROJECT=$(echo $PACKAGE_NAME | tr -d "'")
     if [[ "${PROJECT}" == drupal* ]]; then
       AVAILABLE_UPDATE="true"
       break
     fi
  done
  echo $AVAILABLE_UPDATE
}

 # Checking there pending sec updates.
if [[ $(security_updates_available) == "true" ]]; then
  echo "There are available security updates, starting automatic update process..."
  if [[ $(gh_branch_exist) == "false" ]]
  then
    echo "Creating Git branch for the sec update..."
    create_gh_branch
    echo "Git branch created."
  fi

  # Loop through each key-value pair in the "advisories" object.
  for PACKAGE_NAME in $(echo "$ADVISORIES" | jq -r 'keys | @sh'); do
    PROJECT=$(echo $PACKAGE_NAME | tr -d "'")

    if [[ "${PROJECT}" == drupal* ]]; then
      echo "Updating $PROJECT"
      echo "-----------------"
      cd $DIR
      $COMPOSER_CMD update $PROJECT --with-dependencies
      # Check for any changes
      if [[ `git status --porcelain` ]]; then
        #committing recent changes.
        git add composer.*
        git commit -m "(AUTO-SEC): Updated project $PROJECT (Security update)"

        # Building PR information.
        # Remove prefix "drupal/" from the project name
        AUX=${PROJECT//drupal\//''}
        PROJECTS_UPDATED+="${AUX}, "
        if [ $AUX == 'core' ]; then
          AUX="- Update [${PROJECT}](https://www.drupal.org/project/drupal/releases)."
        else
          AUX="- Update the contrib module: [${PROJECT}](https://www.drupal.org/project/${AUX}/releases)."
        fi
        MESSAGE+="${AUX}\n"
        # IA Genereted Testing steps.
        if [ -n "${OPENAI_API_KEY}" ]; then
          PROMPT_TEXT="I am updating the following drupal project: $PROJECT, because a security update, could you give me functional teststing instructions for it?"
          OPENAI_RESPONSE=$(openai_request "$OPENAI_API_KEY" "$PROMPT_TEXT")
          TEST_STEPS+="### IA testing instructions for the project ${PROJECT}:\n"
          TEST_STEPS+="${OPENAI_RESPONSE}\n"
        fi
        echo "Updated $PROJECT"
        echo "---------------"
      fi
    fi
  done
  echo "Projects updated"
  echo "---------------"

  # Check for any changes
  cd $DIR
  echo "Pushing security update changes to remote repo"
  echo "-------------------------------------------"
  git push --set-upstream origin $BRANCH_NAME

  # Create the PR
  if [ -z "$MESSAGE" ]
  then
    echo "Nothing to update."
  else
    echo "Creating security updates Pull request."
    echo "-------------------------------------------"
    # Preparing variables
    TITLE="(AUTO-SEC): Security updates for $NOW"
    BODY=`cat ./vendor/fourkitchens/pots/scripts/security-updates/PULL_REQUEST_TEMPLATE.md`
    BODY=${BODY//\[UPDATED_MODULES\]/$MESSAGE}
    BODY=${BODY//\[ADDITIONAL_TESTING\]/$TEST_STEPS}
    if [ ! -z "$SITE_NAME" ]; then
      BODY=${BODY//\[PROJECT_NAME\]/$SITE_NAME}
    fi
    PARAMETERS=$(printf '{"title":"%s","body":"%s","head":"%s","base":"%s"}' "$TITLE" "${BODY//$'\n'/\\n}" "$BRANCH_NAME" "$CIRCLE_BRANCH")

    # Running the request
    response=$( \
        curl -sw "%{http_code}" -L \
        -X POST \
        -H "Accept: application/vnd.github+json" \
        -H "Authorization: Bearer $GITHUB_TOKEN" \
        -H "X-GitHub-Api-Version: 2022-11-28" \
        https://api.github.com/repos/$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME/pulls \
        -d "$PARAMETERS" \
    )

    # Extracting the HTTP status code from the response
    http_status="${response: -3}"

    if [ "$http_status" == "200" -o "$http_status" == "201" ]; then
      echo "Pull request: $TITLE successfully created."
      echo "-------------------------------------------"
    else
      echo "Failed to create pull request: $TITLE. HTTP status code: $http_status"
      echo "-------------------------------------------"
      exit 1
    fi

    # Create a ticket for ClickUp.
    if [ -n "${CU_REQUESTER_ID}" -a -n "${CU_TOKEN}" -a -n "${CU_LEAD_EMAIL}" ]; then

      # Creating ClickUp ticket.
      echo "Creating security updates ClickUp Ticket."
      echo "-------------------------------------------"
      CU_API=https://api.clickup.com/api/v2
      # Environment variables; should be defined as CircleCI variables.
      # CU_CLIENT_ID: Look in ClickUp for id. e.g. 16
      # CU_REQUESTER_ID: Look in ClickUp for id. e.g. 54648604
      # CU_LIST_ID: Look in ClickUp for id. e.g. 901300865356
      # CU_TOKEN: Located in 1Pass.
      # CU_LEAD_EMAIL: Find lead in engagements database.

      CU_BODY_MESSAGE=`cat ./vendor/fourkitchens/pots/scripts/security-updates/TICKET_TEMPLATE.md`
      # Replacing placeholders in the template.
      CU_BODY_MESSAGE=${CU_BODY_MESSAGE//\[SITE_NAME\]/$SITE_NAME}
      CU_BODY_MESSAGE=${CU_BODY_MESSAGE//\[PROJECTS\]/$PROJECTS_UPDATED}
      # Scraping new line characters.
      CU_BODY_MESSAGE=${CU_BODY_MESSAGE//$'\n'/\\n}
      CU_TICKET_TITLE="Security Updates Required For Your Website - ${SITE_NAME}"
      CU_JSON_DATA=$(printf '{
                               "name": "%s",
                               "assignees": [
                                 82036728
                               ],
                               "tags": [
                                 "autosec update"
                               ],
                               "status": "in progress",
                               "priority": 2,
                               "start_date": "%s",
                               "start_date_time": false,
                               "notify_all": false,
                               "parent": null,
                               "links_to": null,
                               "check_required_custom_fields": true,
                               "custom_fields": [
                                 {
                                   "id": "b8bbcb75-a7c8-4eb7-9202-e56d227eefbf",
                                   "value": "%s"
                                 }
                               ],
                               "description": "%s"
                             }' "$CU_TICKET_TITLE" "$UNIX_TIMESTAMP_MS" "$CU_CLIENT_ID" "$CU_BODY_MESSAGE")

        # Create the ticket and capture the response.
        RESPONSE=$(
            curl -s ${CU_API}/list/901300865356/task \
              -i -X POST \
              -H "Authorization: ${CU_TOKEN}" \
              -H "Content-Type: application/json" \
              -d "$CU_JSON_DATA"
          )

        # Extract the task id from the response; I could not get jq to work.
        TASK_ID=$(echo "$RESPONSE" | awk -F'"id":' '{print $2}' | awk -F',' '{print $1}' | sed 's/"//g' | tr -d '[:space:]')

        # Use the task id to add the requester to the "Requester" custom field.
        CU_JSON_DATA_REQUESTER=$(printf '{
                                               "value": {
                                                 "add": [
                                                   %s
                                                 ]
                                               }
                                             }' "$CU_REQUESTER_ID")

        curl -s ${CU_API}/task/${TASK_ID}/field/601d8088-a5d6-41c2-ad32-9bec68eac624 \
                  -X POST \
                  -H "Content-Type: application/json" \
                  -H "Authorization: ${CU_TOKEN}" \
                  -d "$CU_JSON_DATA_REQUESTER"

        echo "ClickUp Ticket successfully created."
        echo "-------------------------------------------"
    fi
  fi
else
  echo "Nothing to do! No available security updates."
fi
