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

APP_ROOT="${AWP_DOGFOOD_ROOT:-/home/user/services/awp-i1}"
CONFIG_DIR="${AWP_DOGFOOD_CONFIG:-/home/user/.config/awp-dogfood}"
UNIT_DIR="${HOME}/.config/systemd/user"
TAILSCALE_IP="${AWP_DOGFOOD_IP:-100.101.104.41}"
TAILSCALE_DNS_NAME="$(tailscale status --json | jq -r '.Self.DNSName' | sed 's/\.$//')"
if [[ -z "$TAILSCALE_DNS_NAME" || "$TAILSCALE_DNS_NAME" == "null" ]]; then
  echo "failed to resolve the dogfood Tailscale DNS name" >&2
  exit 1
fi
WEB_PORT="${AWP_WEB_PORT:-4173}"
CONTROL_PORT="${AWP_CONTROL_PORT:-8787}"
POSTGRES_PORT="${AWP_POSTGRES_PORT:-5433}"
SELF_REPOSITORY_URL="https://github.com/platform-modules/awp.git"

mkdir -p "$APP_ROOT" "$CONFIG_DIR" "$UNIT_DIR"
umask 077

if [[ ! -s "$CONFIG_DIR/operator-password-hash" ]]; then
  echo "AWP operator authentication is not provisioned: create $CONFIG_DIR/operator-password-hash with one Argon2id encoded password hash" >&2
  exit 1
fi
OPERATOR_PASSWORD_HASH="$(tr -d '\r\n' < "$CONFIG_DIR/operator-password-hash")"
if [[ ! "$OPERATOR_PASSWORD_HASH" =~ ^\$argon2id\$ ]]; then
  echo "$CONFIG_DIR/operator-password-hash must contain an Argon2id encoded hash" >&2
  exit 1
fi

mise x node@22 -- pnpm install --frozen-lockfile
mise x node@22 -- pnpm build

AGENT_RUNNER_IMAGE="$(tr -d '\r\n' < infra/dogfood/agent-runner-image.lock)"
MODEL_GATEWAY_IMAGE="$(tr -d '\r\n' < infra/dogfood/model-gateway-image.lock)"
SUBROUTER_IMAGE="$(tr -d '\r\n' < infra/dogfood/subrouter-image.lock)"
FABRO_IMAGE="$(tr -d '\r\n' < infra/dogfood/fabro-image.lock)"
if [[ ! "$AGENT_RUNNER_IMAGE" =~ ^ghcr\.io/platform-modules/awp-agent-runner@sha256:[0-9a-f]{64}$ ]]; then
  echo "infra/dogfood/agent-runner-image.lock must contain the immutable published GHCR digest" >&2
  exit 1
fi
if [[ ! "$MODEL_GATEWAY_IMAGE" =~ ^ghcr\.io/platform-modules/awp-model-gateway@sha256:[0-9a-f]{64}$ ]]; then
  echo "infra/dogfood/model-gateway-image.lock must contain the immutable published GHCR digest" >&2
  exit 1
fi
if [[ ! "$SUBROUTER_IMAGE" =~ ^ghcr\.io/platform-modules/awp-subrouter@sha256:[0-9a-f]{64}$ ]]; then
  echo "infra/dogfood/subrouter-image.lock must contain the immutable published GHCR digest" >&2
  exit 1
fi
if [[ ! "$FABRO_IMAGE" =~ ^ghcr\.io/fabro-sh/fabro@sha256:[0-9a-f]{64}$ ]]; then
  echo "infra/dogfood/fabro-image.lock must contain the verified immutable upstream Fabro digest" >&2
  exit 1
fi

rm -rf "$APP_ROOT/repo.next"
mkdir -p "$APP_ROOT/repo.next"
rsync -a --delete --exclude='.git' ./ "$APP_ROOT/repo.next/"
rm -rf "$APP_ROOT/repo.previous"
if [[ -d "$APP_ROOT/repo" ]]; then mv "$APP_ROOT/repo" "$APP_ROOT/repo.previous"; fi
mv "$APP_ROOT/repo.next" "$APP_ROOT/repo"

if [[ ! -d "$APP_ROOT/source-seed/.git" ]]; then
  git clone "$SELF_REPOSITORY_URL" "$APP_ROOT/source-seed"
else
  git -C "$APP_ROOT/source-seed" fetch origin
fi
git -C "$APP_ROOT/source-seed" checkout main
if git -C "$APP_ROOT/source-seed" diff --quiet && git -C "$APP_ROOT/source-seed" diff --cached --quiet; then
  git -C "$APP_ROOT/source-seed" merge --ff-only origin/main || true
fi

kubectl config view --raw --minify -o jsonpath='{.clusters[0].cluster.certificate-authority-data}' | base64 -d > "$CONFIG_DIR/kube-ca.crt"
KUBE_TOKEN="$(kubectl create token awp-workspace-controller -n awp-system --duration=8760h)"
if [[ -z "$KUBE_TOKEN" ]]; then
  echo "failed to mint AWP workspace-controller token" >&2
  exit 1
fi

if [[ ! -f "$CONFIG_DIR/postgres-password" ]]; then openssl rand -hex 24 > "$CONFIG_DIR/postgres-password"; fi
if [[ ! -f "$CONFIG_DIR/callback-secret" ]]; then openssl rand -hex 32 > "$CONFIG_DIR/callback-secret"; fi
if [[ ! -f "$CONFIG_DIR/subrouter-proxy-token" ]]; then openssl rand -hex 32 > "$CONFIG_DIR/subrouter-proxy-token"; fi
if [[ ! -f "$CONFIG_DIR/subrouter-admin-token" ]]; then openssl rand -hex 32 > "$CONFIG_DIR/subrouter-admin-token"; fi
if [[ ! -f "$CONFIG_DIR/subrouter-account-import-token" ]]; then openssl rand -hex 32 > "$CONFIG_DIR/subrouter-account-import-token"; fi
if [[ ! -f "$CONFIG_DIR/model-gateway-signing-secret" ]]; then openssl rand -hex 32 > "$CONFIG_DIR/model-gateway-signing-secret"; fi
POSTGRES_PASSWORD="$(cat "$CONFIG_DIR/postgres-password")"
CALLBACK_SECRET="$(cat "$CONFIG_DIR/callback-secret")"

kubectl apply -f infra/k8s/execution-base.yaml
# Remove obsolete node-local runner readiness metadata from the pre-registry Slice 1 workaround.
kubectl label nodes --all awp.platform/agent-runner- >/dev/null 2>&1 || true
kubectl annotate nodes --all awp.platform/agent-runner-image- >/dev/null 2>&1 || true
if ! kubectl -n platform-registry get secret overdeck-ghcr-pull >/dev/null 2>&1; then
  echo "AWP registry drift: no system GHCR pull credential is available" >&2
  exit 1
fi
for PULL_NAMESPACE in awp-workspaces awp-system; do
  kubectl -n platform-registry get secret overdeck-ghcr-pull -o json \
    | jq --arg namespace "$PULL_NAMESPACE" 'del(.metadata.uid,.metadata.resourceVersion,.metadata.creationTimestamp,.metadata.managedFields,.metadata.ownerReferences) | .metadata.name="awp-ghcr-pull" | .metadata.namespace=$namespace | .metadata.labels={"app.kubernetes.io/managed-by":"awp","awp.dev/purpose":"registry-pull"}' \
    | kubectl apply -f - >/dev/null
done
kubectl -n awp-system create secret generic awp-subrouter-secrets \
  --from-file=proxy_token="$CONFIG_DIR/subrouter-proxy-token" \
  --from-file=admin_token="$CONFIG_DIR/subrouter-admin-token" \
  --from-file=account_import_token="$CONFIG_DIR/subrouter-account-import-token" \
  --dry-run=client -o yaml | kubectl apply -f -
sed "s#__AWP_SUBROUTER_IMAGE__#$SUBROUTER_IMAGE#g" infra/k8s/subrouter-dogfood.yaml | kubectl apply -f -
kubectl -n awp-system rollout status deployment/awp-subrouter --timeout=180s

kubectl -n awp-system create secret generic awp-model-gateway-secrets \
  --from-file=subrouter_proxy_token="$CONFIG_DIR/subrouter-proxy-token" \
  --from-file=signing_secret="$CONFIG_DIR/model-gateway-signing-secret" \
  --dry-run=client -o yaml | kubectl apply -f -
sed "s#__AWP_MODEL_GATEWAY_IMAGE__#$MODEL_GATEWAY_IMAGE#g" infra/k8s/model-gateway-dogfood.yaml | kubectl apply -f -
kubectl -n awp-system rollout status deployment/awp-model-gateway --timeout=180s

if ! kubectl -n awp-system get secret awp-fabro-secrets >/dev/null 2>&1; then
  FABRO_DEV_TOKEN="fabro_dev_$(openssl rand -hex 32)"
  FABRO_SESSION_SECRET="$(openssl rand -hex 32)"
  kubectl -n awp-system create secret generic awp-fabro-secrets \
    --from-literal=FABRO_DEV_TOKEN="$FABRO_DEV_TOKEN" \
    --from-literal=SESSION_SECRET="$FABRO_SESSION_SECRET"
fi
sed "s#__AWP_FABRO_IMAGE__#$FABRO_IMAGE#g" infra/k8s/fabro-dogfood.yaml | kubectl apply -f -
kubectl -n awp-system rollout status deployment/awp-fabro --timeout=180s
kubectl -n awp-system get secret awp-fabro-secrets \
  -o jsonpath='{.data.FABRO_DEV_TOKEN}' | base64 -d > "$CONFIG_DIR/fabro-dev-token"
printf '\n' >> "$CONFIG_DIR/fabro-dev-token"

SUBROUTER_CLUSTER_IP="$(kubectl -n awp-system get service awp-subrouter -o jsonpath='{.spec.clusterIP}')"
if [[ -z "$SUBROUTER_CLUSTER_IP" || "$SUBROUTER_CLUSTER_IP" == "None" ]]; then
  echo "failed to resolve the K3s Subrouter service address" >&2
  exit 1
fi
FABRO_CLUSTER_IP="$(kubectl -n awp-system get service awp-fabro -o jsonpath='{.spec.clusterIP}')"
if [[ -z "$FABRO_CLUSTER_IP" || "$FABRO_CLUSTER_IP" == "None" ]]; then
  echo "failed to resolve the K3s Fabro service address" >&2
  exit 1
fi

cat > "$CONFIG_DIR/postgres.env" <<EOF
POSTGRES_DB=awp
POSTGRES_USER=awp
POSTGRES_PASSWORD=$POSTGRES_PASSWORD
EOF

cat > "$CONFIG_DIR/control-plane.env" <<EOF
DATABASE_URL=postgresql://awp:$POSTGRES_PASSWORD@127.0.0.1:$POSTGRES_PORT/awp
PORT=$CONTROL_PORT
AWP_CONTROL_HOST=127.0.0.1
AWP_OPERATOR_PASSWORD_HASH=$OPERATOR_PASSWORD_HASH
NODE_EXTRA_CA_CERTS=$CONFIG_DIR/kube-ca.crt
AWP_KUBERNETES_API_BASE=https://127.0.0.1:6443
AWP_KUBERNETES_TOKEN=$KUBE_TOKEN
AWP_EXECUTION_CALLBACK_SECRET=$CALLBACK_SECRET
AWP_EXECUTION_CALLBACK_BASE_URL=https://$TAILSCALE_DNS_NAME/api
AWP_WORKSPACE_NAMESPACE=awp-workspaces
AWP_DEPLOYMENT_MODE=dogfood
AWP_DOGFOOD_NATIVE_ACP_FAIL_AFTER_PROMPT_ON_INITIAL=1
AWP_NATIVE_ACP_ENABLED=1
AWP_WORKSPACE_IMAGE=$AGENT_RUNNER_IMAGE
AWP_WORKSPACE_STORAGE=2Gi
AWP_MODEL_GATEWAY_URL=http://awp-model-gateway.awp-system.svc.cluster.local:32180/v1
AWP_MODEL_GATEWAY_SIGNING_SECRET_FILE=$CONFIG_DIR/model-gateway-signing-secret
AWP_KUBECTL_COMMAND=/usr/local/bin/kubectl
AWP_SUBROUTER_URL=http://$SUBROUTER_CLUSTER_IP:31415
AWP_SUBROUTER_ADMIN_TOKEN_FILE=$CONFIG_DIR/subrouter-admin-token
AWP_SUBROUTER_ACCOUNT_IMPORT_TOKEN_FILE=$CONFIG_DIR/subrouter-account-import-token
AWP_FABRO_URL=http://$FABRO_CLUSTER_IP:32276
AWP_FABRO_TOKEN_FILE=$CONFIG_DIR/fabro-dev-token
AWP_DBOS_EXECUTOR_ID=awp-control-plane-dogfood
AWP_CODEX_COMMAND=/home/user/.claude/bin/codex
AWP_SELF_REPOSITORY_URL=$SELF_REPOSITORY_URL
AWP_SELF_REQUIRED_CHECKS=CI
AWP_VISION_FILE=$APP_ROOT/repo/docs/VISION.md
AWP_SOURCE_REPOSITORY_PATH=$APP_ROOT/source-seed
EOF

if [[ -s "$CONFIG_DIR/github-publication-token" ]]; then
  printf 'AWP_GITHUB_PUBLICATION_TOKEN_FILE=%s\n' "$CONFIG_DIR/github-publication-token" >> "$CONFIG_DIR/control-plane.env"
fi

cat > "$CONFIG_DIR/web.env" <<EOF
AWP_WEB_HOST=127.0.0.1
AWP_WEB_PORT=$WEB_PORT
AWP_CONTROL_PLANE_URL=http://127.0.0.1:$CONTROL_PORT
AWP_SELF_REPOSITORY_URL=$SELF_REPOSITORY_URL
AWP_ACCEPTANCE_STATE_FILE=$APP_ROOT/repo/GOLIVE.md
EOF

chmod 600 "$CONFIG_DIR"/*

cat > "$UNIT_DIR/awp-dogfood-postgres.service" <<EOF
[Unit]
Description=AWP I1 Dogfood PostgreSQL
After=network-online.target
Wants=network-online.target

[Service]
ExecStartPre=-/usr/bin/podman rm -f awp-dogfood-postgres
ExecStart=/usr/bin/podman run --name awp-dogfood-postgres --rm --pull=missing -p 127.0.0.1:$POSTGRES_PORT:5432 -v awp-dogfood-postgres:/var/lib/postgresql/data --env-file $CONFIG_DIR/postgres.env docker.io/library/postgres:16-alpine
ExecStop=/usr/bin/podman stop -t 20 awp-dogfood-postgres
Restart=always
RestartSec=3
TimeoutStartSec=180

[Install]
WantedBy=default.target
EOF

cat > "$UNIT_DIR/awp-dogfood-control-plane.service" <<EOF
[Unit]
Description=AWP I1 Dogfood Control Plane
After=awp-dogfood-postgres.service network-online.target
Requires=awp-dogfood-postgres.service

[Service]
Type=simple
WorkingDirectory=$APP_ROOT/repo
EnvironmentFile=$CONFIG_DIR/control-plane.env
ExecStartPre=/bin/bash -lc 'for i in {1..90}; do /usr/bin/podman exec awp-dogfood-postgres pg_isready -U awp -d awp >/dev/null 2>&1 && exit 0; sleep 1; done; exit 1'
ExecStart=/home/user/.local/bin/mise x node@22 -- node apps/control-plane/dist/server.js
Restart=always
RestartSec=3
TimeoutStartSec=120

[Install]
WantedBy=default.target
EOF

cat > "$UNIT_DIR/awp-dogfood-web.service" <<EOF
[Unit]
Description=AWP I1 Dogfood Web UI
After=awp-dogfood-control-plane.service network-online.target
Requires=awp-dogfood-control-plane.service

[Service]
Type=simple
WorkingDirectory=$APP_ROOT/repo
EnvironmentFile=$CONFIG_DIR/web.env
ExecStart=/home/user/.local/bin/mise x node@22 -- node apps/web/dist/server.js
Restart=always
RestartSec=3

[Install]
WantedBy=default.target
EOF

systemctl --user daemon-reload
systemctl --user enable awp-dogfood-postgres.service awp-dogfood-control-plane.service awp-dogfood-web.service
systemctl --user restart awp-dogfood-postgres.service
systemctl --user restart awp-dogfood-control-plane.service
systemctl --user restart awp-dogfood-web.service
tailscale serve --bg --yes --https=443 "http://127.0.0.1:$WEB_PORT" >/dev/null

for _ in $(seq 1 90); do
  if curl -fsS "http://127.0.0.1:$CONTROL_PORT/health" >/dev/null 2>&1 && curl -fsS "http://127.0.0.1:$WEB_PORT/" >/dev/null 2>&1; then
    printf 'AWP_URL=https://%s/\n' "$TAILSCALE_DNS_NAME"
    exit 0
  fi
  sleep 1
done

systemctl --user --no-pager --full status awp-dogfood-postgres.service awp-dogfood-control-plane.service awp-dogfood-web.service >&2 || true
exit 1
