package c_middle

const CmiiEmqxTemplate = `
---
# ============== Secret - 密码管理 ==============
apiVersion: v1
kind: Secret
metadata:
  name: emqx-credentials
  namespace: {{ .Namespace }}
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: "{{ .TagVersion }}"
type: Opaque
stringData:
  # Dashboard管理员密码
  dashboard-admin-password: "{{ .EmqxPassword }}"
  # MQTT用户密码
  mqtt-admin-password: "{{ .EmqxPassword }}"

---
# ============== ServiceAccount ==============
apiVersion: v1
kind: ServiceAccount
metadata:
  name: helm-emqxs
  namespace: {{ .Namespace }}

---
# ============== Role - RBAC ==============
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: helm-emqxs
  namespace: {{ .Namespace }}
rules:
  - apiGroups: [""]
    resources:
      - endpoints
      - pods
    verbs:
      - get
      - watch
      - list

---
# ============== RoleBinding ==============
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: helm-emqxs
  namespace: {{ .Namespace }}
subjects:
  - kind: ServiceAccount
    name: helm-emqxs
    namespace: {{ .Namespace }}
roleRef:
  kind: Role
  name: helm-emqxs
  apiGroup: rbac.authorization.k8s.io

---
# ============== ConfigMap - Bootstrap配置文件 ==============
apiVersion: v1
kind: ConfigMap
metadata:
  name: emqx-bootstrap-config
  namespace: {{ .Namespace }}
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
data:
  # 主配置文件 - 覆盖默认配置
  emqx.conf: |
    # 节点配置
    node {
      name = "emqx@${POD_NAME}.helm-emqxs-headless.{{ .Namespace }}.svc.cluster.local"
      cookie = "emqx-cluster-cookie-secret"
      data_dir = "/opt/emqx/data"
    }
    
    # 集群配置
    cluster {
      name = emqxcl
      # 单节点 建议为 manual 多节点为k8s
      discovery_strategy = manual
      k8s {
        apiserver = "https://kubernetes.default.svc.cluster.local:443"
        service_name = "helm-emqxs-headless"
        # 这里可以改为 hostname
        address_type = dns
        namespace = "{{ .Namespace }}"
        suffix = "svc.cluster.local"
      }
    }
    
    # 日志配置
    log {
      console {
        enable = true
        level = info
      }
      file {
        enable = true
        level = warning
        path = "/opt/emqx/log"
      }
    }
    
    # Dashboard配置
    dashboard {
      listeners.http {
        bind = "0.0.0.0:18083"
      }
      default_username = "admin"
      default_password = "public"
    }
    
    # 监听器配置
    listeners.tcp.default {
      bind = "0.0.0.0:1883"
      max_connections = 1024000
    }
    
    listeners.ws.default {
      bind = "0.0.0.0:8083"
      max_connections = 1024000
      websocket.mqtt_path = "/mqtt"
    }
    
    listeners.ssl.default {
      bind = "0.0.0.0:8883"
      max_connections = 512000
    }
    
    # 认证配置 - 使用内置数据库
    authentication = [
      {
        mechanism = password_based
        backend = built_in_database
        user_id_type = username
        password_hash_algorithm {
          name = sha256
          salt_position = suffix
        }
        # Bootstrap文件路径 - 用于初始化用户
        bootstrap_file = "/opt/emqx/data/bootstrap_users.json"
        bootstrap_type = plain
      }
    ]
    
    # 授权配置
    authorization {
      no_match = deny
      deny_action = disconnect
    
      sources = [
        {
          type = built_in_database
          enable = true
        }
      ]
    }
    
    # MQTT协议配置
    mqtt {
      max_packet_size = "1MB"
      max_clientid_len = 65535
      max_topic_levels = 128
      max_qos_allowed = 2
      max_topic_alias = 65535
      retain_available = true
      wildcard_subscription = true
      shared_subscription = true
    }

---
# ============== ConfigMap - Users & ACL (严格 JSON 格式) ==============
apiVersion: v1
kind: ConfigMap
metadata:
  name: emqx-bootstrap-users
  namespace: {{ .Namespace }}
data:
  bootstrap_users.json: |
    [
      { "user_id": "admin", "password": "{{ .EmqxPassword }}", "is_superuser": true },
      { "user_id": "cmlc", "password": "{{ .EmqxPassword }}", "is_superuser": false }
    ]

  # 【修改点】既然有jq，这里使用标准的 JSON 数组格式，最不容易出错
  bootstrap_acl.json: |
    [
      {
        "username": "admin",
        "rules": [
          {"action": "all", "permission": "allow", "topic": "#"}
        ]
      },
      {
        "username": "cmlc",
        "rules": [
          {"action": "publish", "permission": "allow", "topic": "#"},
          {"action": "subscribe", "permission": "allow", "topic": "#"}
        ]
      }
    ]

---
# ============== ConfigMap - 初始化脚本 (修正版) ==============
apiVersion: v1
kind: ConfigMap
metadata:
  name: emqx-init-dashboard
  namespace: {{ .Namespace }}
data:
  init-dashboard.sh: |
    #!/bin/bash
    set -e
    
    DASHBOARD_USER="admin"
    DASHBOARD_PASS="${DASHBOARD_ADMIN_PASSWORD}"
    EMQX_API="http://localhost:18083/api/v5"
    ACL_FILE="/bootstrap/bootstrap_acl.json"
    
    # 辅助函数：打印带时间戳的日志
    log() {
      echo "[$(date +'%H:%M:%S')] $1"
    }
    
    log "======================================"
    log "初始化 Dashboard 与 ACL (Debug Version)"
    log "======================================"
    
    # ----------------------------------------------------------------
    # 1. 等待 EMQX API 就绪
    # ----------------------------------------------------------------
    log "[1/4] 等待 EMQX API 就绪..."
    for i in $(seq 1 60); do
      if curl -s -f -m 5 "${EMQX_API}/status" > /dev/null 2>&1; then
        log "✓ EMQX API 已就绪"
        break
      fi
      if [ $i -eq 60 ]; then
        log "✗ EMQX API 启动超时"
        exit 1
      fi
      sleep 5
    done
    
    # ----------------------------------------------------------------
    # 2. 修改 Dashboard 密码
    # ----------------------------------------------------------------
    log "[2/4] 检查/更新 Dashboard 密码..."
    
    # 获取 Token (尝试默认密码)
    LOGIN_RESP=$(curl -s -X POST "${EMQX_API}/login" \
      -H 'Content-Type: application/json' \
      -d "{\"username\":\"${DASHBOARD_USER}\",\"password\":\"public\"}")
    
    TOKEN=$(echo "$LOGIN_RESP" | jq -r '.token // empty')
    
    if [ -n "$TOKEN" ]; then
      log "  检测到默认密码，正在更新..."
      curl -s -f -X POST "${EMQX_API}/users/${DASHBOARD_USER}/change_pwd" \
        -H "Authorization: Bearer ${TOKEN}" \
        -H 'Content-Type: application/json' \
        -d "{\"old_pwd\":\"public\",\"new_pwd\":\"${DASHBOARD_PASS}\"}"
      log "  ✓ Dashboard 密码已更新"
    else
      log "  ℹ 无法使用默认密码登录，跳过更新（可能已修改）"
    fi
    
    # ----------------------------------------------------------------
    # 3. 导入 ACL 规则
    # ----------------------------------------------------------------
    echo "[3/3] 导入ACL规则..."

    # 重新登录获取最新 Token
    LOGIN_RESP=$(curl -sS -X POST "${EMQX_API}/login" \
      -H 'Content-Type: application/json' \
      -d "{\"username\":\"${DASHBOARD_USER}\",\"password\":\"${DASHBOARD_PASS}\"}")

    TOKEN=$(echo "$LOGIN_RESP" | jq -r '.token // empty')

    if [ -z "$TOKEN" ]; then
      echo "  ✗ 无法获取Token，请检查密码设置"
      exit 0
    fi

    if [ -f "$ACL_FILE" ]; then
      echo "  正在解析 ACL 文件: $ACL_FILE"

      if ! jq -e . "$ACL_FILE" >/dev/null 2>&1; then
         echo "  ✗ ACL 文件 JSON 格式错误，跳过处理"
         exit 0
      fi

      jq -c '.[]' "$ACL_FILE" | while read -r user_config; do
        USERNAME=$(echo "$user_config" | jq -r '.username // empty')

        # ✅ PUT/POST 都需要 username + rules（username 是 required）
        REQ_BODY=$(echo "$user_config" | jq -c '{username: .username, rules: .rules}')

        if [ -z "$USERNAME" ]; then
          echo "  ✗ ACL 条目缺少 username，跳过"
          continue
        fi

        echo "  配置用户 ${USERNAME} 的ACL规则..."

        # 1) 优先 PUT（覆盖更新）
        http_code=$(curl -sS -o /tmp/emqx_acl_resp.json -w '%{http_code}' \
          -X PUT "${EMQX_API}/authorization/sources/built_in_database/rules/users/${USERNAME}" \
          -H "Authorization: Bearer ${TOKEN}" \
          -H 'Content-Type: application/json' \
          -d "$REQ_BODY")

        if [ "$http_code" = "204" ]; then
          echo "    ✓ PUT 更新成功"
        elif [ "$http_code" = "404" ]; then
          # 2) 不存在则 POST 创建
          http_code2=$(curl -sS -o /tmp/emqx_acl_resp.json -w '%{http_code}' \
            -X POST "${EMQX_API}/authorization/sources/built_in_database/rules/users" \
            -H "Authorization: Bearer ${TOKEN}" \
            -H 'Content-Type: application/json' \
            -d "$REQ_BODY")

          if [ "$http_code2" = "204" ]; then
            echo "    ✓ POST 创建成功"
          else
            echo "    ✗ POST 失败 (HTTP ${http_code2})：$(cat /tmp/emqx_acl_resp.json 2>/dev/null || true)"
            exit 1
          fi
        else
          echo "    ✗ PUT 失败 (HTTP ${http_code})：$(cat /tmp/emqx_acl_resp.json 2>/dev/null || true)"
          exit 1
        fi

        # 3) 导入后验证（可选但强烈建议保留）
        verify_code=$(curl -sS -o /tmp/emqx_acl_verify.json -w '%{http_code}' \
          -H "Authorization: Bearer ${TOKEN}" \
          "${EMQX_API}/authorization/sources/built_in_database/rules/users/${USERNAME}")

        if [ "$verify_code" = "200" ]; then
          echo "    ✓ 验证成功：$(cat /tmp/emqx_acl_verify.json | jq -c '.')"
        else
          echo "    ✗ 验证失败 (HTTP ${verify_code})：$(cat /tmp/emqx_acl_verify.json 2>/dev/null || true)"
          exit 1
        fi
      done

      echo "  ✓ ACL 规则导入完成"
    else
      echo "  ℹ 未找到 ACL 文件"
    fi

---
# ============== StatefulSet ==============
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: helm-emqxs
  namespace: {{ .Namespace }}
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: "{{ .TagVersion }}"
spec:
  replicas: 1
  serviceName: helm-emqxs-headless
  podManagementPolicy: Parallel
  updateStrategy:
    type: RollingUpdate
  selector:
    matchLabels:
      cmii.type: middleware
      cmii.app: helm-emqxs
      cmii.emqx.architecture: cluster

  template:
    metadata:
      labels:
        cmii.type: middleware
        cmii.app: helm-emqxs
        cmii.emqx.architecture: cluster
        helm.sh/chart: emqx-1.1.0
        app.kubernetes.io/managed-by: octopus-control
        app.kubernetes.io/version: "{{ .TagVersion }}"
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
              - matchExpressions:
                  - key: uavcloud.env
                    operator: In
                    values:
                      {{- if .TenantEnv }}
                      - {{ .TenantEnv }}
                      {{- else }}
                      - {{ .Namespace }}
                      {{- end }}
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: cmii.app
                      operator: In
                      values:
                        - helm-emqxs
                topologyKey: kubernetes.io/hostname

      imagePullSecrets:
        - name: harborsecret

      serviceAccountName: helm-emqxs

      securityContext:
        fsGroup: 1000
        runAsUser: 1000

      # InitContainer - 准备bootstrap文件
      initContainers:
        - name: prepare-bootstrap
          # 动态选择 tools 镜像
          {{- if .HarborPort }}
          image: {{ .HarborIPOrCustomImagePrefix }}:{{ .HarborPort }}/cmii/os-shell:12-debian-12-r51
          {{- else }}
          image: {{ .HarborIPOrCustomImagePrefix }}cmii/os-shell:12-debian-12-r51
          {{- end }}
          imagePullPolicy: IfNotPresent
          # =========================================================
          # 权限: 必须以 root 身份运行才能 chown
          # =========================================================
          securityContext:
            runAsUser: 0
          command:
            - /bin/sh
            - -c
            - |
              echo "准备bootstrap文件..."
              
              # 创建数据目录
              mkdir -p /opt/emqx/data
              
              # 复制bootstrap文件到数据目录
              # 只在文件不存在时复制，避免覆盖已有数据
              if [ ! -f /opt/emqx/data/bootstrap_users.json ]; then
                cp /bootstrap-src/bootstrap_users.json /opt/emqx/data/
                echo "✓ 已复制用户bootstrap文件"
              else
                echo "ℹ 用户bootstrap文件已存在，跳过"
              fi
              
              # 设置权限 (现在有root权限，可以成功)
              chown -R 1000:1000 /opt/emqx/data
              
              echo "✓ Bootstrap准备完成"
          volumeMounts:
            - name: emqx-data
              mountPath: /opt/emqx/data
            - name: bootstrap-users
              mountPath: /bootstrap-src

      containers:
        # 主容器 - EMQX
        - name: emqx
          # 动态选择 emqx 镜像
          {{- if .HarborPort }}
          image: {{ .HarborIPOrCustomImagePrefix }}:{{ .HarborPort }}/cmii/emqx:5.8.8
          {{- else }}
          image: {{ .HarborIPOrCustomImagePrefix }}emqx:5.8.8
          {{- end }}
          imagePullPolicy: IfNotPresent

          env:
            # Pod信息
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: EMQX_DATA_DIR
              value: "/opt/emqx/data"

          ports:
            - name: mqtt
              containerPort: 1883
            - name: mqttssl
              containerPort: 8883
            - name: ws
              containerPort: 8083
            - name: dashboard
              containerPort: 18083
            - name: ekka
              containerPort: 4370

          resources:
            requests:
              cpu: "500m"
              memory: "512Mi"
            limits:
              cpu: "2000m"
              memory: "2Gi"

          livenessProbe:
            httpGet:
              path: /status
              port: 18083
            initialDelaySeconds: 60
            periodSeconds: 30
            timeoutSeconds: 10
            failureThreshold: 3

          readinessProbe:
            httpGet:
              path: /status
              port: 18083
            initialDelaySeconds: 10
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3

          startupProbe:
            httpGet:
              path: /status
              port: 18083
            initialDelaySeconds: 10
            periodSeconds: 5
            failureThreshold: 30

          volumeMounts:
            - name: emqx-data
              mountPath: /opt/emqx/data
            # 使用 subPath 挂载单个配置文件，避免覆盖目录
            - name: bootstrap-config
              mountPath: /opt/emqx/etc/emqx.conf
              subPath: emqx.conf

        # Sidecar - 初始化Dashboard密码和ACL
        - name: init-dashboard
          # 动态选择 tools 镜像
          {{- if .HarborPort }}
          image: {{ .HarborIPOrCustomImagePrefix }}:{{ .HarborPort }}/cmii/os-shell:12-debian-12-r51
          {{- else }}
          image: {{ .HarborIPOrCustomImagePrefix }}cmii/os-shell:12-debian-12-r51
          {{- end }}
          imagePullPolicy: IfNotPresent

          command:
            - /bin/sh
            - -c
            - |
              # 等待主容器启动
              echo "等待EMQX启动..."
              sleep 20
              
              # 执行初始化
              /bin/sh /scripts/init-dashboard.sh
              
              # 保持运行
              echo "初始化完成，进入守护模式..."
              while true; do sleep 3600; done

          env:
            - name: DASHBOARD_ADMIN_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: emqx-credentials
                  key: dashboard-admin-password

          resources:
            requests:
              cpu: "100m"
              memory: "64Mi"
            limits:
              cpu: "200m"
              memory: "128Mi"

          volumeMounts:
            - name: init-script
              mountPath: /scripts
            - name: bootstrap-users
              mountPath: /bootstrap

      volumes:
        - name: bootstrap-config
          configMap:
            name: emqx-bootstrap-config
        - name: bootstrap-users
          configMap:
            name: emqx-bootstrap-users
        - name: init-script
          configMap:
            name: emqx-init-dashboard
            defaultMode: 0755
        - name: emqx-data
          persistentVolumeClaim:
            claimName: helm-emqxs

---
# ============== Service - Headless ==============
apiVersion: v1
kind: Service
metadata:
  name: helm-emqxs-headless
  namespace: {{ .Namespace }}
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: "{{ .TagVersion }}"
spec:
  type: ClusterIP
  clusterIP: None
  publishNotReadyAddresses: true
  selector:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
  ports:
    - name: mqtt
      port: 1883
      targetPort: 1883
    - name: mqttssl
      port: 8883
      targetPort: 8883
    - name: ws
      port: 8083
      targetPort: 8083
    - name: dashboard
      port: 18083
      targetPort: 18083
    - name: ekka
      port: 4370
      targetPort: 4370

---
# ============== Service - NodePort ==============
apiVersion: v1
kind: Service
metadata:
  name: helm-emqxs
  namespace: {{ .Namespace }}
  labels:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
    helm.sh/chart: emqx-1.1.0
    app.kubernetes.io/managed-by: octopus-control
    app.kubernetes.io/version: "{{ .TagVersion }}"
spec:
  type: NodePort
  selector:
    cmii.type: middleware
    cmii.app: helm-emqxs
    cmii.emqx.architecture: cluster
  ports:
    - name: mqtt
      port: 1883
      targetPort: 1883
      nodePort: {{ .EmqxNodePort }}
    - name: dashboard
      port: 18083
      targetPort: 18083
      nodePort: {{ .EmqxDashboardNodePort }}
    - name: ws
      port: 8083
      targetPort: 8083
      nodePort: {{ .EmqxWebSocketNodePort }}
    - name: mqttssl
      port: 8883
      targetPort: 8883
`
