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

scope=all
case ${1:-} in
  --api-only)
    scope=api
    api_image=${2:?Runtime API image is required}
    worker_image=
    expected_version=${3:?image release version is required}
    expected_source_revision=${4:-$expected_version}
    ;;
  --worker-only)
    scope=worker
    api_image=
    worker_image=${2:?Runtime Worker image is required}
    expected_version=${3:?image release version is required}
    expected_source_revision=${4:-$expected_version}
    ;;
  *)
    api_image=${1:-nexuscrm-runtime-api-ci}
    worker_image=${2:-nexuscrm-runtime-worker-ci}
    expected_version=${3:?image release version is required}
    expected_source_revision=${4:-$expected_version}
    ;;
esac
root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
run_id="${GITHUB_RUN_ID:-local}-$$"
api_container="nexuscrm-runtime-api-smoke-$run_id"
bootstrap_container="nexuscrm-runtime-bootstrap-smoke-$run_id"
worker_container="nexuscrm-runtime-worker-smoke-$run_id"
token_file=$(mktemp)
secret_source=$(mktemp -d)

cleanup() {
  docker rm -f "$api_container" "$bootstrap_container" "$worker_container" \
    "runtime-api-contract-$run_id" "runtime-worker-contract-$run_id" \
    "l0-controlplane-contract-$run_id" >/dev/null 2>&1 || true
  rm -f "$token_file"
  sudo rm -rf "$secret_source"
}
trap cleanup EXIT

printf 'untrusted-p3a-smoke-token\n' > "$token_file"
# The production loader deliberately rejects world-accessible workload
# credentials. A bind mount preserves the host file mode, so the image smoke
# must exercise the same owner-only invariant instead of failing earlier for a
# test-fixture permission bug.
chmod 0400 "$token_file"

prepare_startup_contracts() {
  cp "$token_file" "$secret_source/token"
  openssl req -x509 -newkey rsa:2048 -nodes -days 1 -subj '/CN=localhost' \
    -keyout "$secret_source/tls.key" -out "$secret_source/tls.crt" >/dev/null 2>&1
  # Generate a deterministic smoke-only key with the Go stdlib. It is mounted
  # from a disposable volume and never enters the image or serving deployment.
  cat > "$secret_source/generate_signing_key.go" <<'EOF'
package main

import (
  "crypto/ed25519"
  "encoding/base64"
  "encoding/json"
  "os"
)

func main() {
  privateKey := ed25519.NewKeyFromSeed(make([]byte, ed25519.SeedSize))
  _ = json.NewEncoder(os.Stdout).Encode(map[string]any{
    "schema": "nexuscrm.runtime-signing-keys/v1",
    "active": map[string]string{
      "signing_key_id": "runtime-image-smoke",
      "private_key_base64": base64.StdEncoding.EncodeToString(privateKey),
    },
    "overlap": []any{},
  })
}
EOF
  go run "$secret_source/generate_signing_key.go" > "$secret_source/signing.json"
  jq -n '{
    schema: "nexuscrm.runtime-api-serving/v2",
    replica_id: "runtime-image-smoke",
    authorized_workload_id: "runtime-image-smoke-workload",
    org_id: "00D000000000001",
    app_installation_id: "runtime-image-smoke-installation",
    catalog_snapshot_store_root: "/var/lib/nexuscrm/catalog",
    expected_service_release_digest: ("sha256:" + ("1" * 64)),
    schema_generation: 1,
    engine_generation: 1,
    identity_attempt_cap: "1s",
    session_scope_capabilities: {
      api: [
        "runtime.records.evaluate-access.v1",
        "runtime.records.query.v1"
      ]
    },
    capabilities: [
      {
        app_capability_id: "io.nexuscrm.sfcrm.ui.record-access.v1",
        runtime_capability_id: "runtime.records.evaluate-access.v1",
        expected_ownership_epoch: 1,
        expected_compatibility_receipt_digest: ("sha256:" + ("2" * 64)),
        admission_lease: "2s"
      },
      {
        app_capability_id: "io.nexuscrm.sfcrm.query.v1",
        runtime_capability_id: "runtime.records.query.v1",
        expected_ownership_epoch: 1,
        expected_compatibility_receipt_digest: ("sha256:" + ("3" * 64)),
        admission_lease: "2s"
      }
    ]
  }' > "$secret_source/serving.json"
  jq -n --arg source_revision "$expected_source_revision" '{
    schema: "nexuscrm.runtime-worker-role/v1",
    work_family: "runtime.audit-history-fanout.v1",
    deployment_id: "runtime-worker-image-smoke",
    worker_release_digest: ("sha256:" + ("4" * 64)),
    worker_source_revision: $source_revision,
    ownership_epoch: 1,
    batch_size: 10,
    poll_interval: "100ms",
    lease_duration: "30s",
    retry_jitter_max: "10ms",
    max_attempts: 5,
    db_max_open_conns: 4,
    db_max_idle_conns: 2,
    shutdown_timeout: "10s"
  }' > "$secret_source/worker.json"
  # The distroless Runtime image deliberately has no shell. Prepare the
  # read-only secret mount on the CI host for the image's declared non-root
  # UID instead of adding a helper image or overriding the container user.
  chmod 0640 "$secret_source"/*
  sudo chown -R 10001:10001 "$secret_source"
}

assert_image_contract() {
  local image=$1 role=$2 schema=$3
  local created binary
  test "$(docker image inspect "$image" --format '{{ index .Config.Labels "dev.nexuscrm.runtime.role" }}')" = "$role"
  test "$(docker image inspect "$image" --format '{{ index .Config.Labels "org.opencontainers.image.version" }}')" = "$expected_version"
  test "$(docker image inspect "$image" --format '{{.Config.User}}')" = "10001:10001"
  test "$(docker image inspect "$image" --format '{{if .Config.Healthcheck}}configured{{end}}')" = "configured"
  docker run --rm --entrypoint /bin/cat "$image" /etc/nexuscrm/config-schema.json > "/tmp/$role-schema-$run_id.json"
  cmp "$root/backend/internal/runtimeconfig/schema/$schema" "/tmp/$role-schema-$run_id.json"
  created=$(docker create --name "$role-contract-$run_id" "$image")
  binary="/tmp/$role-binary-$run_id"
  docker cp "$created:/usr/local/bin/$role" "$binary"
  docker rm "$created" >/dev/null
  for forbidden in nexuscrm-app-packs backend/distributions dialect-sf-crm issue-tracker; do
    if go version -m "$binary" | grep -Fq "$forbidden"; then
      echo "$role image binary contains forbidden owner: $forbidden" >&2
      exit 1
    fi
  done
  rm -f "$binary"
  rm -f "/tmp/$role-schema-$run_id.json"
}

assert_embedded_l0_controlplane() {
  local image=$1 created binary
  created=$(docker create --name "l0-controlplane-contract-$run_id" "$image")
  binary="/tmp/l0-controlplane-binary-$run_id"
  docker cp "$created:/usr/local/bin/l0-controlplane" "$binary"
  docker rm "$created" >/dev/null
  for forbidden in nexuscrm-app-packs backend/distributions dialect-sf-crm issue-tracker; do
    if go version -m "$binary" | grep -Fq "$forbidden"; then
      echo "L0 Controlplane binary contains forbidden owner: $forbidden" >&2
      exit 1
    fi
  done
  rm -f "$binary"
}

start_role() {
  local container=$1 image=$2 admin_port=$3
  shift 3
  docker run -d --name "$container" \
    -p "127.0.0.1::$admin_port" \
    --mount "type=bind,src=$secret_source,dst=/var/run/secrets/nexuscrm,readonly" \
    -e NEXUSCRM_RUNTIME_WORKLOAD_IDENTITY_TOKEN_FILE=/var/run/secrets/nexuscrm/token \
    "$@" "$image" >/dev/null
}

assert_api_fails_closed_without_serving_authority() {
  start_role "$api_container" "$api_image" 9091 \
    -e NEXUSCRM_RUNTIME_API_SIGNING_KEY_FILE=/var/run/secrets/nexuscrm/signing.json \
    -e NEXUSCRM_RUNTIME_API_SERVING_CONFIG_FILE=/var/run/secrets/nexuscrm/serving.json \
    -e NEXUSCRM_RUNTIME_API_TLS_CERTIFICATE_FILE=/var/run/secrets/nexuscrm/tls.crt \
    -e NEXUSCRM_RUNTIME_API_TLS_PRIVATE_KEY_FILE=/var/run/secrets/nexuscrm/tls.key \
    -e TIDB_HOST=127.0.0.1 -e TIDB_PORT=1 -e TIDB_USER=smoke -e TIDB_DATABASE=smoke -e TIDB_TLS_DISABLE=1
  for _ in $(seq 1 40); do
    if test "$(docker inspect "$api_container" --format '{{.State.Running}}')" = "false"; then
      break
    fi
    sleep 0.25
  done
  test "$(docker inspect "$api_container" --format '{{.State.Running}}')" = "false"
  test "$(docker inspect "$api_container" --format '{{.State.ExitCode}}')" != "0"
  docker logs "$api_container" 2>&1 | grep -Fq 'failed to ping database'
  if docker logs "$api_container" 2>&1 | grep -Eq 'runtime config:|runtime signing keys:|load gRPC server identity'; then
    echo "runtime-api did not accept its complete startup contract" >&2
    docker logs "$api_container" >&2
    exit 1
  fi
  if docker logs "$api_container" 2>&1 | grep -Fq 'runtime-api started'; then
    echo "runtime-api entered serving lifecycle without D1 authority" >&2
    exit 1
  fi
}

assert_api_bootstrap_is_live_unready_and_metadata_independent() {
  docker run -d --name "$bootstrap_container" \
    --mount "type=bind,src=$secret_source,dst=/var/run/secrets/nexuscrm,readonly" \
    -e NEXUSCRM_RUNTIME_API_TLS_CERTIFICATE_FILE=/var/run/secrets/nexuscrm/tls.crt \
    -e NEXUSCRM_RUNTIME_API_TLS_PRIVATE_KEY_FILE=/var/run/secrets/nexuscrm/tls.key \
    "$api_image" bootstrap >/dev/null
  for _ in $(seq 1 40); do
    if docker exec "$bootstrap_container" wget -qO- http://127.0.0.1:9091/livez >/dev/null 2>&1; then
      break
    fi
    sleep 0.25
  done
  docker exec "$bootstrap_container" wget -qO- http://127.0.0.1:9091/livez >/dev/null
  if docker exec "$bootstrap_container" wget -qO- http://127.0.0.1:9091/readyz >/dev/null 2>&1; then
    echo "runtime-api bootstrap became ready without Catalog serving authority" >&2
    exit 1
  fi
  test "$(docker inspect "$bootstrap_container" --format '{{.State.Running}}')" = "true"
}

assert_worker_fails_closed_without_database_or_ownership() {
  start_role "$worker_container" "$worker_image" 9191 \
    -e NEXUSCRM_RUNTIME_WORKER_CONFIG_FILE=/var/run/secrets/nexuscrm/worker.json \
    -e TIDB_HOST=127.0.0.1 -e TIDB_PORT=1 -e TIDB_USER=smoke -e TIDB_DATABASE=smoke -e TIDB_TLS_DISABLE=1
  for _ in $(seq 1 40); do
    if test "$(docker inspect "$worker_container" --format '{{.State.Running}}')" = "false"; then
      break
    fi
    sleep 0.25
  done
  test "$(docker inspect "$worker_container" --format '{{.State.Running}}')" = "false"
  test "$(docker inspect "$worker_container" --format '{{.State.ExitCode}}')" != "0"
  docker logs "$worker_container" 2>&1 | grep -Fq 'runtime worker: database readiness'
  if docker logs "$worker_container" 2>&1 | grep -Eq 'runtime config:|binary source revision|runtime-worker started'; then
    echo "runtime-worker did not accept and bind its complete startup contract before failing closed" >&2
    docker logs "$worker_container" >&2
    exit 1
  fi
}

prepare_startup_contracts

if [[ "$scope" != worker ]]; then
  assert_image_contract "$api_image" runtime-api runtime-api.schema.json
  assert_embedded_l0_controlplane "$api_image"
  assert_api_bootstrap_is_live_unready_and_metadata_independent

  # The default entrypoint remains the serving composition and must still fail
  # closed without Catalog/TiDB authority. The explicit bootstrap argument is a
  # deployment-only live/unready mode, not a compatibility or business fallback.
  assert_api_fails_closed_without_serving_authority
fi

if [[ "$scope" != api ]]; then
  assert_image_contract "$worker_image" runtime-worker runtime-worker.schema.json
  assert_worker_fails_closed_without_database_or_ownership
fi

echo "runtime image smoke: OK"
