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

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

if [[ -z "$env_file" || ! -f "$env_file" ]]; then
  echo "Usage: $0 EDGE_ENV_FILE" >&2
  exit 1
fi

if [[ "$(stat -c '%a' "$env_file")" != 600 ]]; then
  echo "Edge environment must have mode 0600: $env_file" >&2
  exit 1
fi

if [[ "$(stat -c '%u' "$env_file")" != "$(id -u)" ]]; then
  echo "Edge environment must be owned by the current operator." >&2
  exit 1
fi

read_value() {
  local key=$1

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

require_value() {
  local key=$1
  local value

  if ! value=$(read_value "$key") || [[ -z "$value" ]]; then
    echo "$key is missing or empty in $env_file." >&2
    exit 1
  fi

  printf '%s' "$value"
}

validate_hostname() {
  local key=$1
  local value=$2

  if [[ ! "$value" =~ ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?(\.[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?)+$ ]]; then
    echo "$key must be a lowercase ASCII DNS hostname." >&2
    exit 1
  fi
}

validate_upstream() {
  local key=$1
  local value=$2

  if [[ ! "$value" =~ ^[a-z0-9]([a-z0-9.-]*[a-z0-9])?:[0-9]+$ ]]; then
    echo "$key must be a lowercase host and numeric port." >&2
    exit 1
  fi
}

compose_project_name=$(require_value COMPOSE_PROJECT_NAME)
public_edge_network=$(require_value PUBLIC_EDGE_NETWORK)
edge_bind_address=$(require_value EDGE_BIND_ADDRESS)
edge_http_port=$(require_value EDGE_HTTP_PORT)
edge_https_port=$(require_value EDGE_HTTPS_PORT)
primary_domain=$(require_value PRIMARY_DOMAIN)
primary_upstream=$(require_value PRIMARY_UPSTREAM)
staging_domain=$(require_value STAGING_DOMAIN)
staging_upstream=$(require_value STAGING_UPSTREAM)

[[ "$compose_project_name" =~ ^[a-zA-Z0-9_-]+$ ]] || {
  echo "COMPOSE_PROJECT_NAME contains unsupported characters." >&2
  exit 1
}
[[ "$public_edge_network" =~ ^[a-zA-Z0-9_-]+$ ]] || {
  echo "PUBLIC_EDGE_NETWORK contains unsupported characters." >&2
  exit 1
}
[[ "$edge_bind_address" == "0.0.0.0" || "$edge_bind_address" == "127.0.0.1" ]] || {
  echo "EDGE_BIND_ADDRESS must be 0.0.0.0 or 127.0.0.1." >&2
  exit 1
}
for port_name in edge_http_port edge_https_port; do
  port=${!port_name}
  if [[ ! "$port" =~ ^[0-9]+$ ]] || ((port < 1 || port > 65535)); then
    echo "${port_name^^} must be between 1 and 65535." >&2
    exit 1
  fi
done
[[ "$edge_http_port" != "$edge_https_port" ]] || {
  echo "EDGE_HTTP_PORT and EDGE_HTTPS_PORT must be different." >&2
  exit 1
}

validate_hostname PRIMARY_DOMAIN "$primary_domain"
validate_hostname STAGING_DOMAIN "$staging_domain"
validate_upstream PRIMARY_UPSTREAM "$primary_upstream"
validate_upstream STAGING_UPSTREAM "$staging_upstream"

[[ "$primary_domain" != "$staging_domain" ]] || {
  echo "PRIMARY_DOMAIN and STAGING_DOMAIN must be different." >&2
  exit 1
}
[[ "$primary_upstream" != "$staging_upstream" ]] || {
  echo "PRIMARY_UPSTREAM and STAGING_UPSTREAM must be different." >&2
  exit 1
}

docker compose \
  --project-directory "$ROOT" \
  --env-file "$env_file" \
  --file "$ROOT/compose.edge.yaml" \
  config --quiet

echo "Public edge environment passed structural validation."
