#!/usr/bin/env bash
set -euo pipefail

ROOT=$(CDPATH='' cd -- "$(dirname -- "$0")/.." && pwd)
env_file=${1:-"$ROOT/.env"}
shift || true

if [[ "$env_file" != /* ]]; then
  env_file="$ROOT/$env_file"
fi

if [[ ! -f "$env_file" ]]; then
  echo "Deployment environment does not exist: $env_file" >&2
  exit 1
fi

read_env_value() {
  local key=$1

  if [[ -v "$key" ]]; then
    printf '%s' "${!key}"
    return
  fi

  awk -v key="$key" '
    index($0, key "=") == 1 {
      print substr($0, length(key) + 2)
      found = 1
      exit
    }
    END { if (!found) exit 1 }
  ' "$env_file"
}

deployment_target=$(read_env_value DEPLOYMENT_TARGET 2>/dev/null || printf compose)
deployment_environment=$(read_env_value DEPLOYMENT_ENV 2>/dev/null || printf development)
database_mode=$(read_env_value DATABASE_MODE 2>/dev/null || printf container)
app_topology=$(read_env_value APP_TOPOLOGY 2>/dev/null || printf split)
public_edge_enabled=$(read_env_value PUBLIC_EDGE_ENABLED 2>/dev/null || printf false)
project=$(read_env_value COMPOSE_PROJECT_NAME 2>/dev/null || printf who_need_help)

[[ "$deployment_target" == compose ]] || {
  echo "scripts/compose.sh requires DEPLOYMENT_TARGET=compose." >&2
  exit 1
}

case "$deployment_environment" in
  development | production) ;;
  *) echo "DEPLOYMENT_ENV must be development or production." >&2; exit 1 ;;
esac

case "$database_mode" in
  container | external) ;;
  *) echo "DATABASE_MODE must be container or external." >&2; exit 1 ;;
esac

database_url=$(read_env_value DATABASE_URL 2>/dev/null || true)
: "${database_url:?Set DATABASE_URL in $env_file}"
database_socket_dir=$(read_env_value DATABASE_SOCKET_DIR 2>/dev/null || true)

if [[ "$database_mode" == container ]]; then
  postgres_db=$(read_env_value POSTGRES_DB 2>/dev/null || true)
  postgres_user=$(read_env_value POSTGRES_USER 2>/dev/null || true)
  postgres_password=$(read_env_value POSTGRES_PASSWORD 2>/dev/null || true)
  : "${postgres_db:?Set POSTGRES_DB for DATABASE_MODE=container}"
  : "${postgres_user:?Set POSTGRES_USER for DATABASE_MODE=container}"
  : "${postgres_password:?Set POSTGRES_PASSWORD for DATABASE_MODE=container}"
fi

case "$app_topology" in
  compact | split) ;;
  *) echo "APP_TOPOLOGY must be compact or split." >&2; exit 1 ;;
esac

case "$public_edge_enabled" in
  true | false) ;;
  *) echo "PUBLIC_EDGE_ENABLED must be true or false." >&2; exit 1 ;;
esac

compose=(
  docker compose
  --project-directory "$ROOT"
  --project-name "$project"
  --env-file "$env_file"
  --file "$ROOT/compose.yaml"
)

if [[ "$database_mode" == external ]]; then
  compose+=(--file "$ROOT/compose.external-db.yaml")

  if [[ -n "$database_socket_dir" ]]; then
    compose+=(--file "$ROOT/compose.external-db-socket.yaml")
  fi
fi

if [[ "$app_topology" == compact ]]; then
  compose+=(--file "$ROOT/compose.compact.yaml" --profile compact)
fi

if [[ "$public_edge_enabled" == true ]]; then
  compose+=(--file "$ROOT/compose.public-app.yaml")
fi

if [[ "$deployment_environment" == production ]]; then
  compose+=(--file "$ROOT/compose.production.yaml")
fi

exec "${compose[@]}" "$@"
