#!/usr/bin/env bash

set -o nounset -o errexit

# Text color for gum style output
export FOREGROUND=212
PROJECT=$1
echo $PROJECT
BASE_DIR=$(basename -s .git $(git remote get-url origin))
REPO=$(basename $BASE_DIR)

if ! command -v gum &> /dev/null; then
  echo  "Installing gum..."
  brew install gum
fi

if ! command -v yq &> /dev/null; then
  gum style "Installing yq..."
  brew install python-yq
fi

if ! command -v gh &> /dev/null; then
  gum style  "Installing Github cli..."
  brew install gh
fi

# Repo to copy the GitHub actions from
PROJECT_TYPE=$(gum choose --limit 1 --header "Choose your project type: " "api-starter-kit" "isomorphic-starter-kit")

if [[ "$PROJECT_TYPE" == "api-starter-kit" ]]; then
  GHA_REPO=dx-api-starter-kit
elif [[ "$PROJECT_TYPE" == "isomorphic-starter-kit" ]]; then
  GHA_REPO=dx-isomorphic-starter-kit
fi

function copy_github_actions_workflows() {
  # Clone git repo into /tmp folder
  mkdir -p /tmp/$GHA_REPO
  git clone --depth 1 https://github.com/telus/$GHA_REPO /tmp/$GHA_REPO
  # Create the necessary folders in the target repo
  mkdir -p ./.github/workflows
  # Copy the necessary files
  cp /tmp/$GHA_REPO/.github/gha.env ./.github/
  cp /tmp/$GHA_REPO/Dockerfile ./
  cp /tmp/$GHA_REPO/.npmpackagejsonlintrc ./
  cp /tmp/$GHA_REPO/docker-compose-local.sh ./
  if [ ! -f ./src/config/review.js ]; then
    if [ -f ./src/config/test.js ]; then
      cp ./src/config/test.js ./src/config/review.js
    else
      cp ./src/config/staging.js ./src/config/review.js
    fi
  fi
  # Copy list of github actions workflows
  filelist="check_npm_token check_npmdev_token cicd cleanup idle rollback stale"
  for f in ${filelist}; do cp /tmp/$GHA_REPO/.github/workflows/${f}.yml ./.github/workflows; done;
  # Delete the temporary source repo folder
  rm -rf /tmp/$GHA_REPO
  # Update OpenShift namespace in environment variables file
  sed -i '' "s/OPENSHIFT_NAMESPACE=.*/OPENSHIFT_NAMESPACE=${PROJECT:-$ORIGINAL_OPENSHIFT_NAMESPACE}/g" ./.github/gha.env
}

function make_openshift_template_changes() {
  if [ -f ./openshift/openshift-template.yml ]; then
    # Add environment metadata labels
    yq -yi '(.items[] | select(.kind == "Template") | .objects[] | select(has("metadata")) | select(.kind != "BuildConfig") | .metadata.labels.environment) = "${ENVIRONMENT}"' ./openshift/openshift-template.yml
    # Add environment category variable
    ENVIRONMENT_CATEGORY=$(yq -y --arg REPO $REPO '.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters | .[] | select(.name=="ENVIRONMENT_CATEGORY") | .name == "ENVIRONMENT_CATEGORY"' ./openshift/openshift-template.yml 2>&1 | head -n1)
    if [[ $ENVIRONMENT_CATEGORY != "true" ]]; then
      yq -yi --arg REPO ${REPO} '(.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters) |= . + [{"name": "ENVIRONMENT_CATEGORY", "description": "The environment category (production, staging, test)", "value": "test"}]' ./openshift/openshift-template.yml
    fi
    # Add route timeout variable
    ROUTE_TIMEOUT=$(yq -y --arg REPO $REPO '.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters | .[] | select(.name=="ROUTE_TIMEOUT") | .name == "ROUTE_TIMEOUT"' ./openshift/openshift-template.yml 2>&1 | head -n1)
    if [[ $ROUTE_TIMEOUT != "true" ]]; then
      yq -yi --arg REPO ${REPO} '(.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters) |= . + [{"name": "ROUTE_TIMEOUT", "description": "Timeout on the application route", "value": "30s"}]' ./openshift/openshift-template.yml
    fi
    # Add route timeout annotation
    yq -yi '(.items[] | select(.kind == "Template") | .objects[] | select(.kind == "Route") | .metadata.annotations["haproxy.router.openshift.io/timeout"]) = "${ROUTE_TIMEOUT}"' ./openshift/openshift-template.yml
    # Update api versions
    yq -yi '(.items[] | select(.kind == "Template") | .apiVersion) = "template.openshift.io/v1"' ./openshift/openshift-template.yml
    yq -yi '(.items[] | select(.kind == "ImageStream") | .apiVersion) = "image.openshift.io/v1"' ./openshift/openshift-template.yml
    # Use ENVIRONMENT_CATEGORY instead of ENVIRONMENT for secrets
    yq -yi '(.items[] | select(.kind == "Template") | .objects[]? | select(.kind == "DeploymentConfig") | .spec.template.spec.containers | .[]?.envFrom | .[]? | select(.secretRef) | .secretRef.name | select(endswith("${ENVIRONMENT}"))) |= sub("{ENVIRONMENT}";"{ENVIRONMENT_CATEGORY}")' ./openshift/openshift-template.yml
  fi
}

function update_npm_package_commands() {
  # Add npm lint commands
  npm list npm-package-json-lint || npm install npm-package-json-lint --save-dev
  npm pkg set scripts.package-json-lint="npx npm-package-json-lint -c .npmpackagejsonlintrc ."
  npm pkg set scripts.license="npm run license-checker"
  npm pkg set scripts.license-checker="LICENSE_CHECKER_ALLOW_LIST=\$(grep -e 'LICENSE_CHECKER_ALLOW_LIST=.*' ./.github/gha.env | cut -d'=' -f2) npm exec license-checker --onlyAllow \$LICENSE_CHECKER_ALLOW_LIST --production"
  # Setting $APP_ENV to "review" for numbered environments (which comes from github PR numbers)
  START_COMMAND=$(cat package.json | jq -r .scripts.start)
  if [[ "$START_COMMAND" != *"APP_ENV=review"* ]]; then
    npm pkg set scripts.start="if [[ \$APP_ENV =~ ^[0-9]+$ ]]; then APP_ENV=review; fi; $START_COMMAND"
  fi
}

function update_dockerfile() {
  dockerfile_regex='COPY --chown=node:root .* $HOME/app/$'
  docker_copy_files=$(sed -nr 's/COPY --chown=node:root (.*) \$HOME\/app\/$/\1/p' Dockerfile)
  docker_files_exist=""
  for file in $docker_copy_files; do
    if [[ -f "$file" ]]; then
      docker_files_exist="$docker_files_exist $file"
    fi
  done
  sed -i'.bak' -r 's/COPY --chown=node:root (.*) \$HOME\/app\/$/COPY --chown=node:root'"$docker_files_exist"' \$HOME\/app\//g' Dockerfile
  rm -f Dockerfile.bak
  # Remove integration copy line in Dockerfile if the folder doesn't exist
  if [[ ! -d "integration" ]]; then
    sed -i'.bak' -r '/COPY --chown=node:root integration \$HOME\/app\/integration/d' Dockerfile
    rm -f Dockerfile.bak
  fi
  # Remove swagger-docs copy line in Dockerfile if the folder doesn't exist
  if [[ ! -d "swagger-docs" ]]; then
    sed -i'.bak' -r '/COPY --chown=node:root swagger-docs \$HOME\/app\/swagger-docs/d' Dockerfile
    rm -f Dockerfile.bak
  fi
}

function copy_github_actions_workflows_iso() {
  # Clone git repo into /tmp folder
  mkdir -p /tmp/$GHA_REPO
  git clone --depth 1 https://github.com/telus/$GHA_REPO /tmp/$GHA_REPO
  # Create the necessary folders in the target repo
  mkdir -p ./.github/workflows
  # Copy the necessary files
  cp /tmp/$GHA_REPO/.github/gha.env ./.github/
  cp /tmp/$GHA_REPO/app/Dockerfile ./app/
  cp /tmp/$GHA_REPO/e2e/Dockerfile ./e2e/
  cp /tmp/$GHA_REPO/app/src/config/review.js ./app/src/config/
  # Copy list of github actions workflows
  filelist="cicd cleanup idle rollback stale"
  for f in ${filelist}; do cp /tmp/$GHA_REPO/.github/workflows/${f}.yml ./.github/workflows; done;
  # Delete the temporary source repo folder
  rm -rf /tmp/$GHA_REPO
  # Update OpenShift namespace in environment variables file
  sed -i '' "s/OPENSHIFT_NAMESPACE=.*/OPENSHIFT_NAMESPACE=${PROJECT:-$ORIGINAL_OPENSHIFT_NAMESPACE}/g" ./.github/gha.env
}

function make_openshift_template_changes_iso() {
  if [ -f ./openshift/openshift-template.yml ]; then
    # Add environment metadata labels
    yq -yi '(.items[] | select(.kind == "Template") | .objects[] | select(has("metadata")) | select(.kind != "BuildConfig") | .metadata.labels.environment) = "${ENVIRONMENT}"' ./openshift/openshift-template.yml
    # Add environment category variable
    ENVIRONMENT_CATEGORY=$(yq -y --arg REPO $REPO '.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters | .[] | select(.name=="ENVIRONMENT_CATEGORY") | .name == "ENVIRONMENT_CATEGORY"' ./openshift/openshift-template.yml 2>&1 | head -n1)
    if [[ $ENVIRONMENT_CATEGORY != "true" ]]; then
      yq -yi --arg REPO ${REPO} '(.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters) |= . + [{"name": "ENVIRONMENT_CATEGORY", "description": "The environment category (production, staging, test)", "value": "test"}]' ./openshift/openshift-template.yml
    fi
    # Add route timeout variable
    ROUTE_TIMEOUT=$(yq -y --arg REPO $REPO '.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters | .[] | select(.name=="ROUTE_TIMEOUT") | .name == "ROUTE_TIMEOUT"' ./openshift/openshift-template.yml 2>&1 | head -n1)
    if [[ $ROUTE_TIMEOUT != "true" ]]; then
      yq -yi --arg REPO ${REPO} '(.items[] | select(.kind == "Template") | select(.metadata.name == $REPO) | .parameters) |= . + [{"name": "ROUTE_TIMEOUT", "description": "Timeout on the application route", "value": "30s"}]' ./openshift/openshift-template.yml
    fi
    # Add route timeout annotation
    yq -yi '(.items[] | select(.kind == "Template") | .objects[] | select(.kind == "Route") | .metadata.annotations["haproxy.router.openshift.io/timeout"]) = "${ROUTE_TIMEOUT}"' ./openshift/openshift-template.yml
    # Update api versions
    yq -yi '(.items[] | select(.kind == "Template") | .apiVersion) = "template.openshift.io/v1"' ./openshift/openshift-template.yml
    yq -yi '(.items[] | select(.kind == "ImageStream") | .apiVersion) = "image.openshift.io/v1"' ./openshift/openshift-template.yml
    # Use ENVIRONMENT_CATEGORY instead of ENVIRONMENT for secrets
    yq -yi '(.items[] | select(.kind == "Template") | .objects[]? | select(.kind == "DeploymentConfig") | .spec.template.spec.containers | .[]?.envFrom | .[]? | select(.secretRef) | .secretRef.name | select(endswith("${ENVIRONMENT}"))) |= sub("{ENVIRONMENT}";"{ENVIRONMENT_CATEGORY}")' ./openshift/openshift-template.yml
  fi
}

function update_npm_package_commands_iso() {
  # Add this new build:container job to the app
  cd app
  npm pkg set scripts.build:container="npm-run-all webpack:client webpack:server"
  npm pkg set scripts.license="npm run license-checker"
  npm pkg set scripts.license-checker="LICENSE_CHECKER_ALLOW_LIST=\$(grep -e 'LICENSE_CHECKER_ALLOW_LIST=.*' ./.github/gha.env | cut -d'=' -f2) npm exec license-checker --onlyAllow \$LICENSE_CHECKER_ALLOW_LIST --production"
  # Setting $APP_ENV to "review" for numbered environments (which comes from github PR numbers)
  START_COMMAND=$(cat package.json | jq -r .scripts.start)
  if [[ "$START_COMMAND" != *"APP_ENV=review"* ]]; then
    npm pkg set scripts.start="if [[ \$APP_ENV =~ ^[0-9]+$ ]]; then APP_ENV=review; fi; $START_COMMAND"
  fi
  cd ..
  npm pkg set scripts.license="npm run --prefix app license"
  npm pkg set scripts.license-checker="npm run --prefix app license"
}

function update_dockerfile_iso() {
  dockerfile_regex='COPY --chown=node:root .* $HOME/app/$'
  docker_copy_files=$(sed -nr 's/COPY --chown=node:root (.*) \$HOME\/app\/$/\1/p' app/Dockerfile)
  docker_files_exist=""
  for file in $docker_copy_files; do
    if [[ -f "app/$file" ]]; then
      docker_files_exist="$docker_files_exist $file"
    fi
  done
  sed -i'.bak' -r 's/COPY --chown=node:root (.*) \$HOME\/app\/$/COPY --chown=node:root'"$docker_files_exist"' \$HOME\/app\//g' app/Dockerfile
  rm -f app/Dockerfile.bak
}

if [[ "$PROJECT_TYPE" == 'api-starter-kit' ]]; then
  gum style 'Copying in GitHub Actions Workflows' && copy_github_actions_workflows
  gum style 'Making Openshift Template Changes' && make_openshift_template_changes
  gum style 'Updating Npm scripts' && update_npm_package_commands
  gum style 'Updating Dockerfile' && update_dockerfile
elif [[ "$PROJECT_TYPE" == 'isomorphic-starter-kit' ]]; then
  gum style 'Copying in GitHub Actions Workflows' && copy_github_actions_workflows_iso
  gum style 'Making Openshift Template Changes' && make_openshift_template_changes_iso
  gum style 'Updating Npm scripts' && update_npm_package_commands_iso
  gum style 'Updating Dockerfile' && update_dockerfile_iso
fi
