#!/usr/bin/env bash

# Exit immediately if a command exits with a non-zero status
set -e

# Define a cleanup function to be called on script exit
trap cleanup EXIT

# Function to clean up resources
cleanup() {
  # Stop the running app
  process_id=$(ps axu | grep 'node ./bin/script/server.js' | grep -v grep | awk '{print $2}')
  if [ -n "$process_id" ]; then
    kill $process_id
  fi

  # Stop Redis and Postgres
  docker compose down redis postgres

  # Print API logs
  echo "API logs:"
  echo "==================="
  cat nohup.out
  echo "==================="
  rm nohup.out

  rm -rf test/resources/test

  # restore config
  [[ -f ~/.code-push.config.bak ]] && cp ~/.code-push.config.bak ~/.code-push.config
}

# Function to run a command and print it
run_and_print_cmd() {
  echo "==="
  echo "Running: $@"
  eval "$@"
  echo "==="
}

# Print in green and bold
print_green() {
  echo -e "\033[1;32m$1\033[0m"
}

# This script is used to test the API via the CLI

# Ensure Redis and Postgres are running
docker compose down redis postgres localstack && docker compose up -d redis postgres localstack

# ensure code-push-standalone cli uses correct credentials for the tests
[[ -f ~/.code-push.config ]] && cp ~/.code-push.config ~/.code-push.config.bak
echo '{"accessKey":"0c2efff6-8ab9-4361-b113-5d850823eeba","preserveAccessKeyOnLogout":false,"customServerUrl":"http://localhost:3000"}' > ~/.code-push.config


# Assume AWS profile as default
source awsume prod -o prod-mfa
source awsume dev -o default

# Clean the project
npm run clean

# Build the project
npm run build

# Start the app in the background and wait for it to be ready
rm nohup.out || true
nohup npm run start &
while ! curl -s http://localhost:3000/health | grep -q "Healthy"; do
  echo "Waiting for app to be ready..."
  sleep 1
done

# Define the CLI command for CodePush
CODE_PUSH_CLI="code-push-standalone"

echo "Testing API via CLI"

# Set environment variables
unset DEBUG
export NODE_NO_WARNINGS=1

# Run various CodePush CLI commands to test the API
# Check if I'm still logged in
echo "Who am I?"
run_and_print_cmd "$CODE_PUSH_CLI whoami"

# Check access keys
echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"

echo "Create access key 1"
run_and_print_cmd "$CODE_PUSH_CLI access-key add 'test access key 1'"

echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"
print_green "It should return 1 access key"

echo "Create access key 2"
run_and_print_cmd "$CODE_PUSH_CLI access-key add 'test access key 2'"

echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"
print_green "It should return 2 access keys"

echo "Create access key 3"
run_and_print_cmd "$CODE_PUSH_CLI access-key add 'test access key 3'"

echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"
print_green "It should return 3 access keys"

echo "Patch access key 1"
run_and_print_cmd "$CODE_PUSH_CLI access-key patch 'test access key 1' --ttl 1y"

echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"
print_green "It should return 3 access keys, one of them should have TTL 1 year"

echo "Patch access key 2"
run_and_print_cmd "$CODE_PUSH_CLI access-key patch 'test access key 2' --name 'test 2 patched'"

echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"
print_green "It should return 3 access keys, one of them should have name 'test 2 patched'"

echo "Patch non-existing access key"
run_and_print_cmd "$CODE_PUSH_CLI access-key patch 'test access key 4' --name 'test 4 patched' || true"

echo "Remove access key 3"
run_and_print_cmd "yes | $CODE_PUSH_CLI access-key remove 'test access key 3'"

echo "List access keys"
run_and_print_cmd "$CODE_PUSH_CLI access-key list"
print_green "It should return 2 access keys"

echo "Remove non-existing access key"
run_and_print_cmd "yes | $CODE_PUSH_CLI access-key remove 'test access key 4' || true"

# Check apps, deployments, and collaborators
echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"

echo "Create app 1"
run_and_print_cmd "$CODE_PUSH_CLI app add 'test app 1'"

echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"
print_green "It should return 1 app"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 1'"
print_green "It should return 2 deployments: Staging and Production"

echo "Add deployment 1"
run_and_print_cmd "$CODE_PUSH_CLI deployment add 'test app 1' 'QA'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 1'"
print_green "It should return 3 deployments: Staging, Production, and QA"

echo "Add deployment 2"
run_and_print_cmd "$CODE_PUSH_CLI deployment add 'test app 1' 'UAT'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 1'"
print_green "It should return 4 deployments: Staging, Production, QA, and UAT"

echo "List deployments keys"
run_and_print_cmd "$CODE_PUSH_CLI deployment list -k 'test app 1'"
print_green "It should return 4 deployment keys"

echo "Remove deployment"
run_and_print_cmd "yes | $CODE_PUSH_CLI deployment remove 'test app 1' 'QA'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 1'"
print_green "It should return 3 deployments: Staging, Production, and UAT"

echo "Rename deployment"
run_and_print_cmd "$CODE_PUSH_CLI deployment rename 'test app 1' 'UAT' 'UAT renamed'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 1'"
print_green "It should return 3 deployments: Staging, Production, and UAT renamed"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 1'"
print_green "It should return 1 collaborators, the owner"

echo "Add collaborator 1"
run_and_print_cmd "$CODE_PUSH_CLI collaborator add 'test app 1' 'borys.babii+test1@dataart.com'"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 1'"
print_green "It should return 2 collaborators: the owner and the new collaborator"

echo "Add collaborator 2"
run_and_print_cmd "$CODE_PUSH_CLI collaborator add 'test app 1' 'borys.babii+test2@dataart.com'"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 1'"
print_green "It should return 3 collaborators: the owner and the two new collaborators"

echo "Remove collaborator 2"
run_and_print_cmd "yes | $CODE_PUSH_CLI collaborator remove 'test app 1' 'borys.babii+test2@dataart.com'"
print_green "It should return 2 collaborators: the owner and the first collaborator"

echo "Remove non-existing collaborator"
run_and_print_cmd "yes | $CODE_PUSH_CLI collaborator remove 'test app 1' 'non-existing@example.com' || true"

echo "Remove the owner"
run_and_print_cmd "yes | $CODE_PUSH_CLI collaborator remove 'test app 1' 'borys.babii@dataart.com' || true"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 1'"
print_green "It should return 2 collaborators: the owner and the first collaborator"

echo "Remove app 1"
run_and_print_cmd "yes | $CODE_PUSH_CLI app remove 'test app 1'"

echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"
print_green "It should return 0 apps"

echo "Create app 2"
run_and_print_cmd "$CODE_PUSH_CLI app add 'test app 2'"

echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"
print_green "It should return 1 app"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 2'"

echo "Add deployment 1"
run_and_print_cmd "$CODE_PUSH_CLI deployment add 'test app 2' 'QA App 2'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 2'"
print_green "It should return 3 deployments: Staging, Production and QA App 2"

echo "Add deployment 2"
run_and_print_cmd "$CODE_PUSH_CLI deployment add 'test app 2' 'UAT App 2'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 2'"
print_green "It should return 4 deployments: Staging, Production, QA App 2 and UAT App 2"

echo "List deployments keys"
run_and_print_cmd "$CODE_PUSH_CLI deployment list -k 'test app 2'"

echo "Remove deployment"
run_and_print_cmd "yes | $CODE_PUSH_CLI deployment remove 'test app 2' 'QA' || true"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 2'"
print_green "It should return 4 deployments: Staging, Production, QA App 2 and UAT App 2"

echo "Rename deployment"
run_and_print_cmd "$CODE_PUSH_CLI deployment rename 'test app 2' 'UAT' 'UAT renamed' || true"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 2'"
print_green "It should return 4 deployments: Staging, Production, QA App 2 and UAT App 2"

echo "Add collaborator 1"
run_and_print_cmd "$CODE_PUSH_CLI collaborator add 'test app 2' 'borys.babii+test1@dataart.com'"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 2'"
print_green "It should return 1 collaborator and the owner"

echo "Add collaborator 2"
run_and_print_cmd "$CODE_PUSH_CLI collaborator add 'test app 2' 'borys.babii+test2@dataart.com'"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 2'"
print_green "It should return 2 collaborators and the owner"

echo "Create app 3"
run_and_print_cmd "$CODE_PUSH_CLI app add 'test app 3'"

echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"
print_green "It should return 2 apps"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 3'"

echo "Add deployment 1"
run_and_print_cmd "$CODE_PUSH_CLI deployment add 'test app 3' 'QA'"

echo "List deployments"
run_and_print_cmd "$CODE_PUSH_CLI deployment list 'test app 3'"

echo "List deployments keys"
run_and_print_cmd "$CODE_PUSH_CLI deployment list -k 'test app 3'"

echo "Remove non-existing deployment"
run_and_print_cmd "yes | $CODE_PUSH_CLI deployment remove 'test app 3' 'non-existing' || true"

echo "Rename non-existing deployment"
run_and_print_cmd "$CODE_PUSH_CLI deployment rename 'test app 3' 'non-existing' 'non-existing renamed' || true"

echo "Add collaborator 1"
run_and_print_cmd "$CODE_PUSH_CLI collaborator add 'test app 3' 'borys.babii+test1@dataart.com'"

echo "Add collaborator 2"
run_and_print_cmd "$CODE_PUSH_CLI collaborator add 'test app 3' 'borys.babii+test2@dataart.com'"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 3'"

echo "Rename app 2"
run_and_print_cmd "$CODE_PUSH_CLI app rename 'test app 2' 'test app 2 renamed'"

echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"
print_green "It should return 2 apps"

echo "Rename non-existing app"
run_and_print_cmd "$CODE_PUSH_CLI app rename 'test 4' 'test 4 renamed' || true"

echo "Remove non-existing app"
run_and_print_cmd "yes | $CODE_PUSH_CLI app remove 'test 4' || true"

echo "Transfer app 3"
run_and_print_cmd "yes | $CODE_PUSH_CLI app transfer 'test app 3' 'borys.babii+test1@dataart.com'"

echo "List apps"
run_and_print_cmd "$CODE_PUSH_CLI app list"
print_green "It should return 2 app"

echo "List collaborators"
run_and_print_cmd "$CODE_PUSH_CLI collaborator list 'test app 3'"

echo "Transfer non-existing app"
run_and_print_cmd "yes | $CODE_PUSH_CLI app transfer 'test 4' 'borys.babii+test1@dataart.com' || true"

echo "Transfer to non-existing collaborator"
run_and_print_cmd "yes | $CODE_PUSH_CLI app transfer 'test app 2 renamed' 'non-existing@example.com' || true"

echo "Create app"
run_and_print_cmd "$CODE_PUSH_CLI app add 'test app 5'"

echo "Extract files from a zip archive"
run_and_print_cmd "unzip -o test/resources/test.zip -d test/resources/test"

echo "Release a package to a default deployment"
run_and_print_cmd "$CODE_PUSH_CLI release 'test app 5' test/resources/test 1.0.0 --deploymentName 'Staging' --description 'Initial release' -m -r 50%"

echo "Show release history"
run_and_print_cmd "$CODE_PUSH_CLI deployment ls 'test app 5'"

echo "Path release"
run_and_print_cmd "$CODE_PUSH_CLI patch 'test app 5' Staging --description 'Patch release' -m -r 100%"

echo "Show release history"
run_and_print_cmd "$CODE_PUSH_CLI deployment ls 'test app 5'"

echo "Promote release"
run_and_print_cmd "$CODE_PUSH_CLI promote 'test app 5' 'Staging' 'Production'"

echo "Show release history"
run_and_print_cmd "$CODE_PUSH_CLI deployment ls 'test app 5'"

#echo "Rollback release"
#run_and_print_cmd "$CODE_PUSH_CLI rollback 'test app 5' 'Production'" "1.0.0"

echo "Show release history"
run_and_print_cmd "$CODE_PUSH_CLI deployment ls 'test app 5'"

echo "Press any key to continue"
input
