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

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT"

PROJECT_ID="${RAILWAY_PROJECT_ID:-a6bc4ea7-e89c-42da-819a-8879fb022a0d}"
ENVIRONMENT="${RAILWAY_ENVIRONMENT:-production}"
ENV_FILE="${RAILWAY_ENV_FILE:-$ROOT/.env}"

SERVICE_SELECTOR="all"
SKIP_DEPLOYS=true
DRY_RUN=false

usage() {
  cat <<'USAGE'
Sync selected environment variables from a local .env file to Railway services.

Usage:
  scripts/railway-sync-env.sh [all|platform|extraction] [options]

Options:
  --project <id>         Railway project ID (default: $RAILWAY_PROJECT_ID or script default)
  --env <name>           Railway environment name (default: $RAILWAY_ENVIRONMENT or production)
  --env-file <path>      Local env file to read (default: ./.env)
  --trigger-deploys      Trigger deploys while setting vars (default is --skip-deploys)
  --dry-run              Print variables that would be synced (no changes)
  -h, --help             Show help

Notes:
  - Missing optional vars are skipped.
  - Required vars (COSMOS_ENDPOINT, COSMOS_KEY, JWT_SECRET) must exist unless AZURE_KEYVAULT_URL is set.
USAGE
}

if [[ $# -gt 0 && "${1#-}" == "$1" ]]; then
  SERVICE_SELECTOR="$1"
  shift
fi

while [[ $# -gt 0 ]]; do
  case "$1" in
    --project)
      PROJECT_ID="${2:-}"
      shift 2
      ;;
    --env)
      ENVIRONMENT="${2:-}"
      shift 2
      ;;
    --env-file)
      ENV_FILE="${2:-}"
      shift 2
      ;;
    --trigger-deploys)
      SKIP_DEPLOYS=false
      shift
      ;;
    --dry-run)
      DRY_RUN=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Unknown arg: $1" >&2
      usage
      exit 2
      ;;
  esac
done

SERVICES=()
case "$SERVICE_SELECTOR" in
  all)
    SERVICES=("platform-service" "extraction-service")
    ;;
  platform|platform-service)
    SERVICES=("platform-service")
    ;;
  extraction|extraction-service)
    SERVICES=("extraction-service")
    ;;
  *)
    echo "Unknown service selector: $SERVICE_SELECTOR" >&2
    usage
    exit 2
    ;;
esac

if [[ -z "$PROJECT_ID" ]]; then
  echo "Missing Railway project ID. Use --project or set RAILWAY_PROJECT_ID." >&2
  exit 2
fi

if [[ -z "$ENVIRONMENT" ]]; then
  echo "Missing Railway environment. Use --env or set RAILWAY_ENVIRONMENT." >&2
  exit 2
fi

if [[ ! -f "$ENV_FILE" ]]; then
  echo "Env file not found: $ENV_FILE" >&2
  exit 2
fi

if ! command -v railway >/dev/null 2>&1; then
  echo "railway CLI not found. Install with: npm i -g @railway/cli" >&2
  exit 1
fi

if [[ "$DRY_RUN" == false ]]; then
  if ! railway whoami >/dev/null 2>&1; then
    echo "Railway CLI is not authenticated. Run: railway login" >&2
    exit 1
  fi
fi

# Load .env values into current shell for lookup.
# shellcheck disable=SC1090
set -a
source "$ENV_FILE"
set +a

get_value() {
  local key="$1"
  printf '%s' "${!key-}"
}

has_value() {
  local key="$1"
  [[ -n "${!key-}" ]]
}

COMMON_REQUIRED=(
  COSMOS_ENDPOINT
  COSMOS_KEY
  JWT_SECRET
)

COMMON_OPTIONAL=(
  AZURE_KEYVAULT_URL
  COSMOS_DATABASE
  DEFAULT_PRODUCT_ID
  CORS_ORIGIN
  PRODUCT_ID
  NODE_ENV
  HOST
)

PLATFORM_OPTIONAL=(
  AZURE_BLOB_CONNECTION_STRING
  AZURE_BLOB_ACCOUNT_NAME
  AZURE_BLOB_ACCOUNT_KEY
  STRIPE_SECRET_KEY
  STRIPE_WEBHOOK_SECRET
  STRIPE_PRICE_PRO
  STRIPE_PRICE_ENTERPRISE
  BILLING_INTERNAL_KEY
  WEBHOOK_INVITATION_REDEEMED_URL
  WEBHOOK_REFERRAL_STATUS_URL
  BACKEND_URL
  PLAN_LIMITS_JSON
  USAGE_WARN_THRESHOLD
  RATE_LIMIT_CONFIG_JSON
  LICENSE_ACTIVATE_LOCKOUT_WINDOW_MS
  LICENSE_ACTIVATE_MAX_FAILED_ATTEMPTS
  COSMOS_AUTO_INIT
)

EXTRACTION_OPTIONAL=(
  GEMINI_API_KEY
  DEFAULT_MODEL_ID
  PYTHON_SIDECAR_URL
  EXTRACTION_CACHE_TTL_MS
  EXTRACTION_CACHE_MAX
  EXTRACTION_CACHE_TTL
  EXTRACTION_CACHE_MAX_SIZE
  USE_MOCK_EXTRACTOR
  SIDECAR_PORT
  SIDECAR_HOST
  AZURE_OPENAI_KEY
  AZURE_OPENAI_ENDPOINT
)

missing_required=()
for key in "${COMMON_REQUIRED[@]}"; do
  if ! has_value "$key"; then
    missing_required+=("$key")
  fi
done

if [[ ${#missing_required[@]} -gt 0 && -z "$(get_value AZURE_KEYVAULT_URL)" ]]; then
  echo "Missing required variables in $ENV_FILE: ${missing_required[*]}" >&2
  echo "Either set them in the env file, or set AZURE_KEYVAULT_URL and ensure Railway can access Key Vault." >&2
  exit 2
fi

if [[ ${#missing_required[@]} -gt 0 ]]; then
  echo "Warning: missing ${missing_required[*]} in $ENV_FILE; relying on Key Vault resolution at runtime."
fi

LINK_DIR=""
cleanup() {
  if [[ -n "$LINK_DIR" && -d "$LINK_DIR" ]]; then
    rm -rf "$LINK_DIR"
  fi
}
trap cleanup EXIT

run_railway() {
  if [[ "$DRY_RUN" == true ]]; then
    return 0
  fi
  (
    cd "$LINK_DIR"
    railway "$@"
  )
}

if [[ "$DRY_RUN" == false ]]; then
  LINK_DIR="$(mktemp -d)"
  (
    cd "$LINK_DIR"
    railway link --project "$PROJECT_ID" --environment "$ENVIRONMENT" >/dev/null
  )
fi

ensure_service_exists() {
  local svc="$1"
  if [[ "$DRY_RUN" == true ]]; then
    return 0
  fi

  if ! run_railway variable list --service "$svc" --environment "$ENVIRONMENT" --json >/dev/null 2>&1; then
    echo "Unable to access Railway service '$svc' in env '$ENVIRONMENT' (project '$PROJECT_ID')." >&2
    echo "Check project/environment IDs and service names." >&2
    exit 1
  fi
}

set_variable() {
  local svc="$1"
  local key="$2"
  local value="$3"
  local -a cmd

  if [[ "$DRY_RUN" == true ]]; then
    echo "  - would set $key"
    return 0
  fi

  cmd=(variable set --service "$svc" --environment "$ENVIRONMENT")
  if [[ "$SKIP_DEPLOYS" == true ]]; then
    cmd+=(--skip-deploys)
  fi
  cmd+=("${key}=${value}")

  run_railway "${cmd[@]}" >/dev/null
  echo "  - set $key"
}

sync_service() {
  local svc="$1"
  shift
  local keys=("$@")
  local value

  local seen="|"
  local synced=0
  local skipped=0

  echo "Syncing variables for $svc..."

  for key in "${keys[@]}"; do
    if [[ "$seen" == *"|$key|"* ]]; then
      continue
    fi
    seen+="$key|"

    value="$(get_value "$key")"
    if [[ -z "$value" ]]; then
      skipped=$((skipped + 1))
      continue
    fi

    set_variable "$svc" "$key" "$value"
    synced=$((synced + 1))
  done

  echo "Synced $synced variables to $svc (skipped $skipped unset keys)."
}

for svc in "${SERVICES[@]}"; do
  ensure_service_exists "$svc"

  if [[ "$svc" == "platform-service" ]]; then
    sync_service "$svc" \
      "${COMMON_REQUIRED[@]}" \
      "${COMMON_OPTIONAL[@]}" \
      "${PLATFORM_OPTIONAL[@]}"
  else
    sync_service "$svc" \
      "${COMMON_REQUIRED[@]}" \
      "${COMMON_OPTIONAL[@]}" \
      "${EXTRACTION_OPTIONAL[@]}"
  fi
done

if [[ "$SKIP_DEPLOYS" == true ]]; then
  echo "Variable sync complete (deploys were skipped)."
  echo "Run scripts/railway-deploy.sh to publish new code/config."
else
  echo "Variable sync complete (deploys were triggered while setting vars)."
fi
