{{- /*
Deployment skip-render gate. The Deployment binds three operator-supplied
Secrets (database DSN, app credentials, optional OIDC client secret); if
any are missing on a default-values render (CI smoke test), the
Deployment is silently skipped. The Service / ServiceAccount / ConfigMap
/ NetworkPolicy still render so `helm template` produces a non-empty
output that proves the chart is structurally sound, while the actual
Pod-rendering deferred until the per-Sovereign overlay sets
`database.existingSecret` and `credentials.existingSecret`.

Keycloak OIDC client secret is required only when
`auth.adminUI.mode=keycloak` AND `auth.adminUI.keycloak.issuer` is set;
the configmap mirrors this gate.
*/ -}}
{{- $kcMode := eq .Values.auth.adminUI.mode "keycloak" -}}
{{- $kcConfigured := and $kcMode .Values.auth.adminUI.keycloak.issuer .Values.auth.adminUI.keycloak.existingSecret -}}
{{- $deployReady := and .Values.newapi.enabled .Values.database.existingSecret .Values.credentials.existingSecret -}}
{{- if and $kcMode (not $kcConfigured) -}}
{{- $deployReady = false -}}
{{- end -}}
{{- if $deployReady }}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "bp-newapi.fullname" . }}
  labels:
    {{- include "bp-newapi.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.newapi.replicas }}
  selector:
    matchLabels:
      {{- include "bp-newapi.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "bp-newapi.selectorLabels" . | nindent 8 }}
      annotations:
        # Roll the pod when channel/policy config changes.
        checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
    spec:
      serviceAccountName: {{ include "bp-newapi.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.newapi.securityContext | nindent 8 }}
      containers:
        - name: newapi
          image: "{{ .Values.newapi.image.repository }}:{{ .Values.newapi.image.tag }}"
          imagePullPolicy: {{ .Values.newapi.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.newapi.port }}
              protocol: TCP
          env:
            # ── Database (Postgres on bp-cnpg) ────────────────────────
            - name: SQL_DSN
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.database.existingSecret }}
                  key: {{ .Values.database.existingSecretKey }}

            # ── Valkey cache ──────────────────────────────────────────
            {{- if .Values.valkey.enabled }}
            {{- if .Values.valkey.existingSecret }}
            - name: REDIS_CONN_STRING
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.valkey.existingSecret }}
                  key: {{ .Values.valkey.existingSecretKey }}
            {{- else }}
            - name: REDIS_CONN_STRING
              value: {{ .Values.valkey.url | quote }}
            {{- end }}
            {{- end }}

            # ── App credentials (NewAPI-internal) ─────────────────────
            - name: SESSION_SECRET
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.credentials.existingSecret }}
                  key: SESSION_SECRET
            - name: CRYPTO_SECRET
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.credentials.existingSecret }}
                  key: CRYPTO_SECRET

            # ── OIDC (admin UI) ───────────────────────────────────────
            {{- if $kcConfigured }}
            - name: OIDC_CLIENT_SECRET
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.auth.adminUI.keycloak.existingSecret }}
                  key: OIDC_CLIENT_SECRET
            {{- end }}

            # ── Bootstrap-only master key (DEV ONLY) ──────────────────
            {{- if .Values.auth.adminUI.masterKeySecret }}
            - name: MASTER_KEY
              valueFrom:
                secretKeyRef:
                  name: {{ .Values.auth.adminUI.masterKeySecret }}
                  key: MASTER_KEY
            {{- end }}

          envFrom:
            - configMapRef:
                name: {{ include "bp-newapi.configMapName" . }}

          volumeMounts:
            - name: channels
              mountPath: /etc/newapi
              readOnly: true

          livenessProbe:
            httpGet:
              path: {{ .Values.newapi.probes.liveness.path }}
              port: {{ .Values.newapi.probes.liveness.port }}
            initialDelaySeconds: {{ .Values.newapi.probes.liveness.initialDelaySeconds }}
            periodSeconds: {{ .Values.newapi.probes.liveness.periodSeconds }}
            timeoutSeconds: {{ .Values.newapi.probes.liveness.timeoutSeconds }}
            failureThreshold: {{ .Values.newapi.probes.liveness.failureThreshold }}
          readinessProbe:
            httpGet:
              path: {{ .Values.newapi.probes.readiness.path }}
              port: {{ .Values.newapi.probes.readiness.port }}
            initialDelaySeconds: {{ .Values.newapi.probes.readiness.initialDelaySeconds }}
            periodSeconds: {{ .Values.newapi.probes.readiness.periodSeconds }}
            timeoutSeconds: {{ .Values.newapi.probes.readiness.timeoutSeconds }}
            failureThreshold: {{ .Values.newapi.probes.readiness.failureThreshold }}

          resources:
            {{- toYaml .Values.newapi.resources | nindent 12 }}

        {{- if .Values.meteringSidecar.enabled }}
        # ── Metering sidecar (#798) ─────────────────────────────
        # Transparent reverse proxy in front of NewAPI. Observes
        # successful /v1/* responses, emits one envelope per
        # completed LLM request on NATS subject
        # `catalyst.usage.recorded`. NewAPI itself is unmodified —
        # see values.yaml `meteringSidecar` for the architecture
        # rationale.
        - name: metering-sidecar
          image: "{{ .Values.meteringSidecar.image.repository }}:{{ .Values.meteringSidecar.image.tag }}"
          imagePullPolicy: {{ .Values.meteringSidecar.image.pullPolicy }}
          ports:
            - name: metering
              containerPort: {{ .Values.meteringSidecar.port }}
              protocol: TCP
          env:
            - name: LISTEN_PORT
              value: {{ .Values.meteringSidecar.port | quote }}
            # NewAPI forwards on the same pod's loopback. NewAPI's
            # `newapi.port` is the upstream container port — use
            # 127.0.0.1 (NOT the Service DNS) so the sidecar's
            # response observation does not loop through the
            # cluster-fronting Service.
            - name: NEWAPI_UPSTREAM_URL
              value: "http://127.0.0.1:{{ .Values.newapi.port }}"
            - name: NATS_URL
              value: {{ .Values.meteringSidecar.natsURL | default "nats://nats-jetstream.nats-system.svc.cluster.local:4222" | quote }}
            - name: NATS_PUBLISH_TIMEOUT
              value: {{ .Values.meteringSidecar.natsPublishTimeout | quote }}
            - name: PRICE_MICRO_OMR_PER_TOKEN
              value: {{ .Values.meteringSidecar.priceMicroOMRPerToken | quote }}
            - name: SPOOL_DIR
              value: {{ .Values.meteringSidecar.spoolDir | quote }}
            - name: CUSTOMER_ID_HEADER
              value: {{ .Values.meteringSidecar.customerIDHeader | quote }}
            - name: TENANT_ID_HEADER
              value: {{ .Values.meteringSidecar.tenantIDHeader | quote }}
          livenessProbe:
            httpGet:
              path: /healthz
              port: {{ .Values.meteringSidecar.port }}
            initialDelaySeconds: 5
            periodSeconds: 10
            timeoutSeconds: 3
            failureThreshold: 3
          readinessProbe:
            httpGet:
              path: /healthz
              port: {{ .Values.meteringSidecar.port }}
            initialDelaySeconds: 2
            periodSeconds: 5
            timeoutSeconds: 3
            failureThreshold: 3
          resources:
            {{- toYaml .Values.meteringSidecar.resources | nindent 12 }}
          securityContext:
            {{- toYaml .Values.meteringSidecar.securityContext | nindent 12 }}
          volumeMounts:
            - name: metering-spool
              mountPath: {{ .Values.meteringSidecar.spoolDir }}
        {{- end }}

      volumes:
        - name: channels
          configMap:
            name: {{ include "bp-newapi.configMapName" . }}
            items:
              - key: channels.yaml
                path: channels.yaml
        {{- if .Values.meteringSidecar.enabled }}
        # emptyDir is intentional: the sidecar's drain loop
        # republishes spooled envelopes once NATS recovers, so
        # persistence across pod restarts is unnecessary.
        - name: metering-spool
          emptyDir:
            sizeLimit: 64Mi
        {{- end }}
{{- end }}
