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

SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(cd -- "$SCRIPT_DIR/../.." && pwd)"
COMPOSE_FILE="$ROOT_DIR/docker/compose.local.yml"
STATE_FILE="$ROOT_DIR/.local/dev.generated.env"
ENV_FILE=""

info() { printf '▶ %s\n' "$*"; }
die() { printf 'Error: %s\n' "$*" >&2; exit 1; }

if command -v docker >/dev/null 2>&1; then RUNTIME=docker
elif command -v podman >/dev/null 2>&1; then RUNTIME=podman
else die "Docker or Podman is required."; fi
"$RUNTIME" info >/dev/null 2>&1 || die "$RUNTIME is not usable."

mkdir -p "$ROOT_DIR/.local"
cleanup() { [ -z "$ENV_FILE" ] || rm -f "$ENV_FILE"; }
trap cleanup EXIT

refresh_env() {
  local next
  next="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-local.XXXXXX.env")"
  sh "$ROOT_DIR/scripts/export-env" dev > "$next" || { rm -f "$next"; die "Unable to export Infisical dev."; }
  [ -z "$ENV_FILE" ] || rm -f "$ENV_FILE"
  ENV_FILE="$next"
  set -a
  # shellcheck disable=SC1090
  source "$ENV_FILE"
  set +a
}
dc() { "$RUNTIME" compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" "$@"; }
upsert_state() {
  local key="$1" value="$2" tmp escaped
  tmp="$(mktemp "${TMPDIR:-/tmp}/convex-monorepo-state.XXXXXX.env")"
  [ ! -f "$STATE_FILE" ] || grep -v "^${key}=" "$STATE_FILE" > "$tmp" || true
  escaped="$(printf '%s' "$value" | sed "s/'/'\\\\''/g")"
  printf "%s='%s'\n" "$key" "$escaped" >> "$tmp"
  mv "$tmp" "$STATE_FILE"
}

refresh_env
info "Starting local Payload Postgres, Convex, and dashboard"
dc up -d

info "Waiting for Payload Postgres"
for i in $(seq 1 30); do
  dc exec -T postgres pg_isready -U "${POSTGRES_USER:-convexmonorepo}" >/dev/null 2>&1 && break
  [ "$i" -lt 30 ] || die "Postgres did not become ready."
  sleep 1
done

info "Waiting for Convex at http://localhost:${BACKEND_PORT:-3210}"
for i in $(seq 1 60); do
  curl -fs "http://localhost:${BACKEND_PORT:-3210}/version" >/dev/null 2>&1 && break
  [ "$i" -lt 60 ] || die "Convex did not become ready."
  sleep 2
done

if [ -z "${CONVEX_SELF_HOSTED_ADMIN_KEY:-}" ]; then
  admin_key="$(dc exec -T convex-backend ./generate_admin_key.sh 2>/dev/null | grep -E '.+\|.+' | tail -n1 | tr -d '\r')"
  [ -n "$admin_key" ] || die "Unable to generate the Convex admin key."
  upsert_state CONVEX_SELF_HOSTED_ADMIN_KEY "$admin_key"
  refresh_env
  info "Generated the machine-local Convex admin key"
fi

info "Deploying Convex schema and functions"
(cd "$ROOT_DIR/packages/backend" && bun run setup)

convex_env_names="$(
  sh "$ROOT_DIR/scripts/with-env" dev -- bash -c \
    'cd packages/backend && bunx convex env list' 2>/dev/null \
    | sed -n 's/^\([A-Za-z_][A-Za-z0-9_]*\)=.*/\1/p'
)"
if ! printf '%s\n' "$convex_env_names" | grep -qx 'JWT_PRIVATE_KEY' \
  || ! printf '%s\n' "$convex_env_names" | grep -qx 'JWKS' \
  || ! printf '%s\n' "$convex_env_names" | grep -qx 'SITE_URL'; then
  info "Configuring local Convex Auth keys"
  auth_keys="$(node "$ROOT_DIR/scripts/generate-convex-auth-keys.mjs")"
  jwt="$(printf '%s\n' "$auth_keys" | sed -n 's/^JWT_PRIVATE_KEY="\(.*\)"$/\1/p')"
  jwks="$(printf '%s\n' "$auth_keys" | sed -n 's/^JWKS=//p')"
  JWT_VAL="$jwt" JWKS_VAL="$jwks" sh "$ROOT_DIR/scripts/with-env" dev -- bash -c '
    cd packages/backend
    bunx convex env set "JWT_PRIVATE_KEY=$JWT_VAL" >/dev/null
    bunx convex env set "JWKS=$JWKS_VAL" >/dev/null
    bunx convex env set "SITE_URL=http://localhost:3000" >/dev/null
  '
fi

info "Seeding local Payload from snapshot if needed"
bash "$ROOT_DIR/scripts/db/seed-payload" --yes

printf '\nLocal stack ready:\n  App: http://localhost:3000\n  Convex: http://localhost:%s\n  Dashboard: http://localhost:%s\n  Payload Postgres: localhost:%s\n' "${BACKEND_PORT:-3210}" "${DASHBOARD_PORT:-6791}" "${POSTGRES_PORT:-5432}"
