{{- $nifiHome := "/opt/nifi/nifi-current" }}
{{- /* Validate that basic auth is only used with single node */ -}}
{{- if and (not .Values.global.oidc.enabled) (not .Values.global.ldap.enabled) (gt (.Values.global.nifi.nodeCount | int) 1) }}
{{- fail "Basic authentication (Single User Authentication) only supports single-node deployment. Please set global.nifi.nodeCount to 1, or enable OIDC/LDAP authentication for clustering." }}
{{- end }}
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ include "nifi.fullname" . }}
  labels:
    {{- include "nifi.labels" . | nindent 4 }}
spec:
  podManagementPolicy: Parallel
  replicas: {{ .Values.global.nifi.nodeCount }}
  selector:
    matchLabels:
      {{- include "nifi.selectorLabels" . | nindent 6 }}
  serviceName: {{ include "nifi.fullname" . }}
  template:
    metadata:
      labels:
        {{- include "nifi.selectorLabels" . | nindent 8 }}
    spec:
      terminationGracePeriodSeconds: {{ .Values.shutdown.podTerminationGracePeriodSeconds }}
      {{- if or .Values.persistence.takeOwnershipOnStartup .Values.extraTakeOwnershipPaths }}
      initContainers:
        {{- if eq (include "nifi.useZooKeeper" .) "true" }}
        - name: wait-for-zookeeper
          image: {{ .Values.global.busybox.repository }}
          command:
          - sh
          - -c
          - |
            {{- if .Values.zookeeper.enabled }}
            echo "Connecting to embedded ZooKeeper {{ .Release.Name }}-zookeeper"
            until nc -vzw 1 {{ .Release.Name }}-zookeeper {{ .Values.zookeeper.external.port | default 2181 }} ; do
              echo "Waiting for zookeeper to start"
              sleep 3
            done
            {{- else }}
            echo "Connecting to external ZooKeeper {{ .Values.zookeeper.external.url }}"
            {{- if .Values.zookeeper.external.url }}
            {{- range $url := splitList "," .Values.zookeeper.external.url }}
            {{- $hostPort := splitList ":" $url }}
            {{- if gt (len $hostPort) 1 }}
            until nc -vzw 1 {{ index $hostPort 0 }} {{ index $hostPort 1 }} ; do
              echo "Waiting for zookeeper {{ $url }} to start"
              sleep 3
            done
            {{- else }}
            until nc -vzw 1 {{ index $hostPort 0 }} 2181 ; do
              echo "Waiting for zookeeper {{ $url }}:2181 to start"
              sleep 3
            done
            {{- end }}
            {{- end }}
            {{- else }}
            echo "No external ZooKeeper URL configured"
            {{- end }}
            {{- end }}
          resources:
            requests:
              cpu: 20m
              memory: 10Mi
            limits:
              cpu: 20m
              memory: 10Mi
        {{- else }}
        - name: check-kubernetes-permissions
          image: {{ .Values.global.busybox.repository }}
          command:
          - sh
          - -c
          - |
            echo "Using Kubernetes state management for NiFi {{ .Chart.AppVersion }}"
            echo "Checking Kubernetes API permissions..."
            echo "Namespace: {{ include "nifi.stateManagementNamespace" . }}"
            echo "Lease prefix: {{ .Values.stateManagement.kubernetes.leasePrefix }}"
            echo "State prefix: {{ .Values.stateManagement.kubernetes.statePrefix }}"
            echo "✅ Kubernetes state management configured"
          resources:
            requests:
              cpu: 20m
              memory: 10Mi
            limits:
              cpu: 20m
              memory: 10Mi
        {{- end }}
          securityContext:
            allowPrivilegeEscalation: false
            privileged: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
        - name: take-ownership
          image: {{ .Values.global.busybox.repository }}
          command:
            - sh
            - -c
            - |
              {{- if .Values.persistence.takeOwnershipOnStartup }}
              chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/persistent_conf
              chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/state
              chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/logs
              chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/flowfile_repo
              chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/content_repo
              chown {{ .Values.securityContext.runAsUser | int64 }}:{{ .Values.securityContext.runAsGroup | int64 }} {{ $nifiHome }}/provenance_repo
              {{- end }}
              {{- range .Values.extraTakeOwnershipPaths }}
              chown {{ $.Values.securityContext.runAsUser | int64 }}:{{ $.Values.securityContext.runAsGroup | int64 }} {{ . | quote }}
              {{- end }}
          securityContext:
            runAsUser: 0
            runAsNonRoot: false
          volumeMounts:
            - name: config
              mountPath: {{ $nifiHome }}/persistent_conf
            - name: state
              mountPath: {{ $nifiHome }}/state
            - name: logs
              mountPath: {{ $nifiHome }}/logs
            {{- if .Values.persistence.takeOwnershipOnStartup }}
            - name: flowfile
              mountPath: {{ $nifiHome }}/flowfile_repo
            - name: content
              mountPath: {{ $nifiHome }}/content_repo
            - name: provenance
              mountPath: {{ $nifiHome }}/provenance_repo
            {{- end }}
            {{- with .Values.extraVolumeMounts }}
            {{- toYaml . | nindent 12 }}
            {{- end }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: {{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          command: [ "../scripts/k8s/custom-startup.sh" ]
          lifecycle:
            preStop:
              exec:
                command: [ "../scripts/k8s/pre-stop.sh" ]
          env:
            - name: NIFI_SENSITIVE_PROPS_KEY
              valueFrom:
                secretKeyRef:
                  name: {{ default "encryption-sensitive-key" .Values.global.encryption.sensitivePropertiesKey.secretRef.name | quote }}
                  key: {{ default "sensitivekey" .Values.global.encryption.sensitivePropertiesKey.secretRef.key | quote }}
            - name: NIFI_JVM_HEAP_INIT
              value: {{ .Values.jvmHeap.min | quote }}
            - name: NIFI_JVM_HEAP_MAX
              value: {{ .Values.jvmHeap.max | quote }}
            - name: NIFI_WEB_HTTPS_PORT
              value: {{ .Values.ports.https | quote }}
            - name: NIFI_REMOTE_INPUT_SOCKET_PORT
              value: {{ .Values.ports.remoteinput | quote }}
            - name: NIFI_CLUSTER_NODE_PROTOCOL_PORT
              value: {{ .Values.ports.cluster | quote }}
            - name: NIFI_CLUSTER_IS_NODE
              value: "true"
            - name: NIFI_ELECTION_MAX_CANDIDATES
              value: {{ .Values.global.nifi.nodeCount | quote }}
            {{- /* Common cluster environment variables (required for both state management strategies) */}}
            {{- include "nifi.clusterEnvironment" . | nindent 12 }}
            {{- if eq (include "nifi.useZooKeeper" .) "true" }}
            {{- include "nifi.zookeeperStateEnvironment" . | nindent 12 }}
            {{- else }}
            {{- include "nifi.kubernetesStateEnvironment" . | nindent 12 }}
            {{- end }}
            {{- include "nifi.keystoreEnvironment" . | nindent 12 }}
            {{- /* Authentication environment variables with priority: OIDC > LDAP > Basic Auth */}}
            {{- if .Values.global.oidc.enabled }}
            {{- /* OIDC has highest priority */}}
            {{- include "nifi.oidcEnvironment" . | nindent 12 }}
            {{- else if .Values.global.ldap.enabled }}
            {{- /* LDAP is second priority (only if OIDC is disabled) */}}
            {{- include "nifi.ldapEnvironment" . | nindent 12 }}
            {{- else }}
            {{- /* Basic auth is the default fallback (when both OIDC and LDAP are disabled) */}}
            {{- include "nifi.basicAuthEnvironment" . | nindent 12 }}
            {{- end }}
            {{- with .Values.extraEnv }}
            {{ toYaml . | nindent 12 }}
            {{- end }}
          ports:
            {{- range $name, $number := .Values.ports }}
            - name: {{ $name }}
              containerPort: {{ $number }}
              protocol: TCP
            {{- end }}
            {{- if .Values.extraPorts }}
            {{- range $name, $port := .Values.extraPorts }}
            - name: {{ $name }}
              containerPort: {{ $port.containerPort }}
              protocol: {{ $port.protocol | default "TCP" }}
            {{- end }}
            {{- end }}
          volumeMounts:
            - mountPath: {{ include "nifi.certPath" . }}
              name: certs
              readOnly: true
            - mountPath: {{ include "nifi.tlsPath" . }}
              name: tls
            - mountPath: /opt/nifi/scripts/k8s
              name: config-script
              readOnly: true
            - name: config
              mountPath: {{ $nifiHome }}/persistent_conf
            - name: state
              mountPath: {{ $nifiHome }}/state
            - name: logs
              mountPath: {{ $nifiHome }}/logs
            - name: flowfile
              mountPath: {{ $nifiHome }}/flowfile_repo
            - name: content
              mountPath: {{ $nifiHome }}/content_repo
            - name: provenance
              mountPath: {{ $nifiHome }}/provenance_repo
            {{- with .Values.extraVolumeMounts }}
            {{- toYaml . | nindent 12 }}
            {{- end }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          {{- if not .Values.debugStartup }}
          startupProbe:
            tcpSocket:
              port: https
            {{- toYaml .Values.probeTimings.startup | nindent 12 }}
          readinessProbe:
            exec:
              command:
                - sh
                - -c
                - curl -k -s https://${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.ports.https }}/nifi
            {{- toYaml .Values.probeTimings.readiness | nindent 12 }}
          livenessProbe:
            exec:
              command:
                - sh
                - -c
                - curl -k -s https://${HOSTNAME}.{{ include "nifi.fullname" . }}.{{ .Release.Namespace }}:{{ .Values.ports.https }}/nifi
            {{- toYaml .Values.probeTimings.liveness | nindent 12 }}
          {{- end }}
        {{- if .Values.filebeat.enabled }}
        - name: filebeat
          image: {{ .Values.filebeat.image.repository }}:{{ .Values.filebeat.image.tag | default "latest" }}
          args:
            - -e
            - -E
            - http.enabled=true
          volumeMounts:
            - mountPath: /usr/share/filebeat/filebeat.yml
              subPath: filebeat.yml
              name: filebeat-config
              readOnly: true
            - mountPath: /nifi/logs
              {{- with .Values.persistence.logs.volumeMount }}
              name: {{ .name | default "logs" }}
              {{- if .subPath }}
              subPath: {{ .subPath }}
              {{- end }}
              {{- end }}
          {{- with .Values.filebeat.volumeMounts }}
          {{- toYaml . | nindent 12 }}
          {{- end }}
          {{- with .Values.filebeat.securityContext }}
          securityContext:
            {{- toYaml . | nindent 12 }}
          {{- end }}
          startupProbe:
            exec:
              command:
                - sh
                - -c
                - |
                  #!/usr/bin/env bash -e
                  filebeat test input
            {{- toYaml .Values.probeTimings.startup | nindent 12 }}
          readinessProbe:
            exec:
              command:
                - sh
                - -c
                - |
                  #!/usr/bin/env bash -e
                  filebeat test output
            {{- toYaml .Values.probeTimings.readiness | nindent 12 }}
          livenessProbe:
            exec:
              command:
                - sh
                - -c
                - |
                  #!/usr/bin/env bash -e
                  curl --fail 127.0.0.1:5066
            {{- toYaml .Values.probeTimings.liveness | nindent 12 }}
        {{- end }}
      volumes:
        - name: certs
          secret:
            secretName: {{ include "nifi.fullname" . }}-tls     # The secret created by cert-manager
            optional: false                                     # Secret must be present
        - name: tls
          emptyDir: { }
        - name: config-script
          configMap:
            name: {{ include "nifi.fullname" . }}
            defaultMode: 0554
        {{- with .Values.persistence.logs.volumeMount }}
        {{- /* Use an emptyDir volume if no persistence is configured */}}
        {{- if not .name }}
        - name: logs
          emptyDir: { }
        {{- end }}
        {{- end }}
        {{- with .Values.extraVolumes }}
        {{- toYaml . | nindent 8 }}
        {{- end }}
        {{- with .Values.filebeat }}
        {{- if .enabled }}
        - name: filebeat-config
          configMap:
            name: {{ include "nifi.fullname" $ }}-filebeat
        {{- end }}
        {{- end }}
      {{- with .Values.global.serviceAccount }}
      serviceAccountName: {{ .name | default (include "nifi.fullname" $) }}
      {{- end }}
      securityContext:
        {{- toYaml .Values.securityContext | nindent 8 }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      affinity:
        {{- if .Values.affinity }}
        {{- toYaml . | nindent 8 }}
        {{- else }}
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - podAffinityTerm:
                labelSelector:
                  matchLabels:
                    {{- include "nifi.selectorLabels" . | nindent 20 }}
                topologyKey: kubernetes.io/hostname
              weight: 100
        {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.topologySpreadConstraints }}
      topologySpreadConstraints:
        {{- toYaml . | nindent 8 }}
      {{- end }}
  {{- with .Values.volumeClaims }}
  volumeClaimTemplates:
    {{- range $name, $volumeClaim := . }}
    - metadata:
        name: {{ $name }}
      spec:
        accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: {{ $volumeClaim.size }}
        storageClassName: {{ $volumeClaim.storageClass }}
    {{- end }}
  {{- end }}
---
apiVersion: v1
kind: Service
metadata:
  name: {{ include "nifi.fullname" . }}
  labels:
    {{- include "nifi.labels" . | nindent 4 }}
spec:
  type: ClusterIP
  clusterIP: None
  publishNotReadyAddresses: true
  ports:
    {{- range $name, $number := .Values.ports }}
    - name: {{ $name }}
      port: {{ $number }}
      protocol: TCP
    {{- end }}
  selector:
    {{- include "nifi.selectorLabels" . | nindent 4 }}
