#!/usr/bin/env bash

# Source common variables and functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/layerops-install-common"

# === Load balancer-specific variables ===
REQUIRED_ENVVARS="ENVIRONMENT_GROUP_UUID INSTANCE_UUID INSTANCE_TOKEN LAYEROPS_WORKER_URL LAYEROPS_ORCHESTRATOR_URL SPIRE_URL WIREGUARD_PRIVATE_IP LAYEROPS_API_URL"

function usage {
  cat << EOF
Usage: $(basename "${BASH_SOURCE[0]}") [init|clean]
EOF
  exit 0
}

# Create load balancer-specific Wireguard template
function _create_wireguard_template() {
  cat > $WIREGUARD_TEMPLATE_FILE <<EOF
[Interface]
PrivateKey = $WIREGUARD_PRIVATE_KEY
Address = $WIREGUARD_PRIVATE_IP/32
MTU = $WIREGUARD_MTU
ListenPort = $WIREGUARD_PORT
PostUp = ip -4 route add $WIREGUARD_SUBNET dev $WIREGUARD_INTERFACE
PostDown = ip -4 route del $WIREGUARD_SUBNET dev $WIREGUARD_INTERFACE
Table = off

{{ range .WireguardPeers }}
# {{ .Role }} - {{ or .InstanceUuid "" }}
[Peer]
PublicKey = {{ .WireguardPublicKey }}
AllowedIPs = {{ .PrivateIp }}/32
{{ if ne .PublicIp "" }}PersistentKeepalive = 5{{ end }}
{{ if and (eq .Role "server") (ne .PublicIp "") }}Endpoint = {{ .PublicIp }}:{{ .WireguardPublicPort }}{{ end }}
{{ if and (eq .Role "lb") (ne .PublicIp "") }}Endpoint = {{ .PublicIp }}:$WIREGUARD_PORT{{ end }}

{{ end }}
EOF
}

# Create load balancer-specific config file
function _create_config_file() {
  LAYEROPS_PUBLIC_IPS=$(curl_with_retry -A Nimeops-UA $LAYEROPS_API_URL/v1/config/publicIps | jq -r '.ips[]')
  cat > $LAYEROPS_ETC_DEFAULT_FILE <<EOF
WIREGUARD_RELOAD_PATH=$WIREGUARD_RELOAD_PATH
WIREGUARD_CONFIG_FILE=$WIREGUARD_CONFIG_FILE
WIREGUARD_TEMPLATE_FILE=$WIREGUARD_TEMPLATE_FILE
WIREGUARD_PUBLIC_KEY=$WIREGUARD_PUBLIC_KEY
SPIRE_AGENT_LAUNCH_SCRIPT=$SPIRE_AGENT_LAUNCH_SCRIPT
SPIRE_TRUST_DOMAIN=$SPIRE_TRUST_DOMAIN
LAYEROPS_DATA_DIR=$LAYEROPS_DATA_DIR
LAYEROPS_PUBLIC_IPS=$LAYEROPS_PUBLIC_IPS
LAYEROPS_WORKER_URL=$LAYEROPS_WORKER_URL
LAYEROPS_WORKER_VERSION_CHECK=$LAYEROPS_WORKER_VERSION_CHECK
LAYEROPS_WORKER_SIGNATURE_PUBLIC_KEY=$LAYEROPS_WORKER_SIGNATURE_PUBLIC_KEY
STATS_PORT=$STATS_PORT
STATS_CACHE_TTL=$STATS_CACHE_TTL
ROLE=lb
API_URL=$LAYEROPS_API_URL
API_ORCHESTRATOR=$LAYEROPS_ORCHESTRATOR_URL
ENVIRONMENT_GROUP_UUID=$ENVIRONMENT_GROUP_UUID
INSTANCE_UUID=$INSTANCE_UUID
SIGNATURE=$LB_INSTANCE_SIGNATURE
STATS=true
EOF
}

function _init() {
  # Install required packages
  install_base_packages ca-certificates curl coreutils gnupg iptables jq rsyslog uuid-runtime wireguard wireguard-tools

  # Set instance signature
  LB_INSTANCE_SIGNATURE=$(uuidgen)
  INSTANCE_INIT_REQUEST=$(cat << EOF
{
  "instanceUuid": "${INSTANCE_UUID}",
  "instanceAccessToken": "${INSTANCE_TOKEN}",
  "signature": "${LB_INSTANCE_SIGNATURE}",
  "environmentGroupUuid": "${ENVIRONMENT_GROUP_UUID}"
}
EOF
)
  curl_with_retry --fail-with-body -A $CURL_USER_AGENT -X POST -H "Content-Type: application/json" -d "$INSTANCE_INIT_REQUEST" ${LAYEROPS_ORCHESTRATOR_URL}/instances/init
  [ "$?" -ne "0" ] && exit 1

  # Setup SSH user and configuration
  setup_ssh

  # Create layerops user
  create_layerops_user

  # Create mandatory folders
  create_layerops_directories

  # Install Docker
  install_docker

  # Install Node Exporter
  install_node_exporter

  # Set sudo access to layerops user
  cat > $SUDO_FILE <<EOF
# Group rules for layerops
$LAYEROPS_USER ALL=(ALL) NOPASSWD: /usr/bin/wg-quick, /usr/bin/wg, $WIREGUARD_QUICK_RELOAD_PATH
$LAYEROPS_USER ALL=(ALL) NOPASSWD: $SPIRE_AGENT_LAUNCH_SCRIPT
EOF

  # Create layerops-admin user if in DEV mode
  create_layerops_admin_user

  # Enable ip forwarding (for docker network)
  iptables -P FORWARD ACCEPT
  enable_ip_forwarding

  # Init Wireguard
  init_wireguard_base
  _create_wireguard_template

  # Install and configure Spire agent
  install_spire_agent_binary
  BOOTSTRAP_SETTINGS="insecure_bootstrap = true"
  REBOOSTRAP_MODE_SETTINGS="rebootstrap_mode = \"auto\""

  [[ $SPIRE_TRUST_BUNDLE_URL == https://* ]] && BOOTSTRAP_SETTINGS="trust_bundle_url = \"$SPIRE_TRUST_BUNDLE_URL\"" || REBOOSTRAP_MODE_SETTINGS=""
  configure_spire_agent "$BOOTSTRAP_SETTINGS" "$REBOOSTRAP_MODE_SETTINGS"
  create_spire_agent_systemd

  # Install layerops worker
  install_layerops_worker

  # Setup layerops config
  _create_config_file

  # Create worker systemd services
  create_worker_systemd_services

  # Set ownership for /opt/layerops directory
  set_layerops_ownership

  # Enable and start layerops worker
  systemctl daemon-reload
  systemctl enable --now \
    wg-quick@${WIREGUARD_INTERFACE} \
    layerops-worker@${REMOTE_VERSION} \
    layerops-worker-update.timer \
    node_exporter
  systemctl restart docker
}


function _clean() {
  # Stop services
  systemctl disable --now \
    layerops-worker@${REMOTE_VERSION} \
    layerops-worker-update.timer \
    spire-agent \
    node_exporter \
    wg-quick@${WIREGUARD_INTERFACE}
  rm -f \
    $LAYEROPS_WORKER_SYSTEMD_FILE \
    $SPIRE_AGENT_SYSTEMD_FILE
  systemctl daemon-reload

  # Clean base layerops installation
  clean_layerops_base
}

if [[ "$#" -eq 0 ]]; then
  usage
fi

case "$1" in
  init)
    check_envvars
    _init
    ;;
  clean)
    _clean;;
  *)
    usage;;
esac
