#!/bin/bash

[ -z "${ENVIRONMENT_FILE}" ] && ENVIRONMENT_FILE=/etc/layerops/default
[ ! -f $ENVIRONMENT_FILE ] && echo "Missing config file: $ENVIRONMENT_FILE" >&2 && exit 1

############################################
# Get variables from /etc/layerops/default
source $ENVIRONMENT_FILE
#
## Required variables :
# WG_PUBLIC_IP: Public ip that is routed to current VM
#
## Optional variables with defaut values :
# URL of layerops API:
API_URL=${API_URL:-https://api.layerops.com}
# Incus network devices (host bridge and container's ip interface):
INCUS_BRIDGE_DEVICE=${INCUS_BRIDGE_DEVICE:-incusbr0}
INCUS_CONTAINER_NIC=${INCUS_CONTAINER_NIC:-eth0}
# Incus image to fetch:
INSTANCE_IMAGE=${INSTANCE_IMAGE:-images:debian/13/cloud}
# Incus instance default resources:
INSTANCE_CPU=${DEFAULT_INSTANCE_CPU:-1}
INSTANCE_MEMORY=${DEFAULT_INSTANCE_MEMORY:-2GiB}
INSTANCE_ROOT_SIZE=${DEFAULT_INSTANCE_ROOT_SIZE:-5GiB}
# Local timezone of incus containers:
LOCAL_TIMEZONE=${LOCAL_TIMEZONE:-Europe/Paris}
# Wireguard udp port
WG_DEFAULT_PORT=${WG_DEFAULT_PORT:-51820}
############################################

for i in "$@"; do
  case $i in
    --environment-group-uuid=*)
      ENVIRONMENT_GROUP_UUID="${i#*=}"
      shift
      ;;
    --server-instance-token=*)
      SERVER_INSTANCE_TOKEN="${i#*=}"
      shift
      ;;
    --private-ip=*)
      WG_PRIVATE_IP="${i#*=}"
      shift
      ;;
    --orchestrator-url=*)
      ORCHESTRATOR_URL="${i#*=}"
      shift
      ;;
    --worker-url=*)
      WORKER_URL="${i#*=}"
      shift
      ;;
    --layerops-script-url=*)
      LAYEROPS_SCRIPT_URL="${i#*=}"
      shift
      ;;
    --cpu=*)
      INSTANCE_CPU="${i#*=}"
      shift
      ;;
    --memory=*)
      INSTANCE_MEMORY="${i#*=}"
      shift
      ;;
    --root-size=*)
      INSTANCE_ROOT_SIZE="${i#*=}"
      shift
      ;;
    --*)
      echo "Unknown option $i" >&2
      exit 1
      ;;
    *)
      ;;
  esac
done

MISSING=""
[ -z "$ENVIRONMENT_GROUP_UUID" ] && MISSING="${MISSING} environment-group-uuid"
[ -z "$SERVER_INSTANCE_TOKEN" ] && MISSING="${MISSING} server-instance-token"
[ -z "$WG_PRIVATE_IP" ] && MISSING="${MISSING} private-ip"
[ -z "$ORCHESTRATOR_URL" ] && MISSING="${MISSING} orchestrator-url"
[ -z "$WORKER_URL" ] && MISSING="${MISSING} worker-url"
[ -z "$LAYEROPS_SCRIPT_URL" ] && MISSING="${MISSING} layerops-script-url"
[ ! -z "$MISSING" ] && echo "Missing arguments: $MISSING" >&2 && exit 1

[ -z "$WG_PUBLIC_IP" ] && echo "Missing environment variable: $WG_PUBLIC_IP" >&2 && exit 1

# Install required packages
while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do sleep 1; done;
while fuser /var/lib/apt/lists/lock >/dev/null 2>&1; do sleep 1; done;
apt-get update > /dev/null && apt-get install -y jq ipcalc-ng > /dev/null || exit 1

INSTANCE_NAME=layerops-${ENVIRONMENT_GROUP_UUID:0:8}

INSTANCE_INFO=$(incus list $INSTANCE_NAME -f compact,noheader 2>&1 | grep $INSTANCE_NAME)
if echo "$INSTANCE_INFO" | grep -q 'Error'; then
  echo "Error checking instance status: $INSTANCE_INFO" >&2
  exit 1
fi

INSTANCE_STATUS=$(echo "$INSTANCE_INFO" | awk '{print $2}')

if [ -z "$INSTANCE_STATUS" ]
then
  USER_DATA=$(cat <<EOF
#cloud-config
bootcmd:
  -
    - cloud-init-per
    - once
    - stop-apt-daily-services
    - systemctl
    - stop
    - apt-daily.service
    - apt-daily-upgrade.service
    - apt-daily.timer
    - apt-daily-upgrade.timer
  -
    - cloud-init-per
    - once
    - apt-daily-timer
    - sh
    - "-c"
    - |
      cat > /lib/systemd/system/apt-daily.timer <<EOF
      [Unit]
      Description=Daily apt download activities

      [Timer]
      OnBootSec=120min
      OnCalendar=*-*-* 6,18:00
      RandomizedDelaySec=12h
      Persistent=true

      [Install]
      WantedBy=timers.target
      EOF
  -
    - cloud-init-per
    - once
    - apt-daily-upgrade-timer
    - sh
    - "-c"
    - |
      cat > /lib/systemd/system/apt-daily-upgrade.timer <<EOF
      [Unit]
      Description=Daily apt upgrade and clean activities
      After=apt-daily.timer

      [Timer]
      OnBootSec=120min
      OnCalendar=*-*-* 6:00
      RandomizedDelaySec=60m
      Persistent=true

      [Install]
      WantedBy=timers.target
      EOF

runcmd:
  - timedatectl set-timezone $LOCAL_TIMEZONE
  - systemctl daemon-reload
  - systemctl restart apt-daily.timer apt-daily-upgrade.timer
  - export WIREGUARD_PRIVATE_IP=$WG_PRIVATE_IP
  - export LAYEROPS_ORCHESTRATOR_URL=$ORCHESTRATOR_URL
  - export LAYEROPS_API_URL=$API_URL
  - export LAYEROPS_WORKER_URL=$WORKER_URL
  - export MARKETPLACE_REGISTRY=${MARKETPLACE_REGISTRY:-registry.nimeops.net/layerops-public/marketplace}
  - export ENVIRONMENT_GROUP_UUID=$ENVIRONMENT_GROUP_UUID
  - export SERVER_INSTANCE_TOKEN=$SERVER_INSTANCE_TOKEN
  - export LOCAL_TIMEZONE="$LOCAL_TIMEZONE"
  - apt-get update
  - apt-get install -y --no-install-recommends curl
  - curl -s -N -L -o /usr/local/bin/layerops-worker-update $LAYEROPS_SCRIPT_URL/worker-update.sh
  - chmod 755 /usr/local/bin/layerops-worker-update
  - curl -s -N -L -o /usr/local/bin/layerops-install $LAYEROPS_SCRIPT_URL/server/layerops-install.sh
  - chmod 755 /usr/local/bin/layerops-install
  - curl -s -N -L -o /usr/local/bin/wg-ecmp $LAYEROPS_SCRIPT_URL/wg-ecmp
  - chmod 755 /usr/local/bin/wg-ecmp
  - curl -s -N -L -o /usr/local/bin/layerops-install-common $LAYEROPS_SCRIPT_URL/layerops-install-common.sh
  - chmod 755 /usr/local/bin/layerops-install-common
  - /usr/local/bin/layerops-install init
EOF
)
  err=$(incus launch $INSTANCE_IMAGE $INSTANCE_NAME -c security.nesting=true -c security.syscalls.intercept.mknod=true -c security.syscalls.intercept.setxattr=true -c cloud-init.user-data="$USER_DATA" -c limits.cpu=$INSTANCE_CPU -c limits.memory=$INSTANCE_MEMORY -d root,size=$INSTANCE_ROOT_SIZE 2>&1)
  launch_exit_code=$?

  if [ $launch_exit_code -ne 0 ]; then
    echo "$err" >&2
    exit 1
  fi

elif [ "$INSTANCE_STATUS" != "RUNNING" ]
then
  echo "Instance '$INSTANCE_NAME' found in status '$INSTANCE_STATUS'. Starting it..."
  err=$(incus start $INSTANCE_NAME 2>&1)
  [ $? -ne 0 ] && echo $err >&2 && exit 1
fi

INSTANCE_STATUS=$(incus list $INSTANCE_NAME -f compact,noheader 2>&1 | grep $INSTANCE_NAME | awk '{print $2}')
if [ "$INSTANCE_STATUS" != "RUNNING" ]; then
  echo "Instance '$INSTANCE_NAME' is still not RUNNING. Current status: $INSTANCE_STATUS" >&2
  exit 1
fi
