package devopsmodules

import (
	"fmt"
	"rubric/utils"
)

var KubernetesModule = Module{
	Key:         "kubernetes",
	Aliases:     []string{"k8s", "k", "kube"},
	Title:       "Kubernetes",
	Description: "Архитектура, Pod/Deployment/Service, kubectl, ConfigMap, Ingress, Helm",
	Run:         showKubernetes,
}

func showKubernetes() {
	utils.Header("DevOps — Kubernetes")

	utils.Section("Архитектура кластера")
	utils.Code(`Control Plane (мастер-узлы):
  kube-apiserver    — API-сервер, точка входа для всех запросов
  etcd              — распределённая БД, хранит состояние кластера
  kube-scheduler    — решает на какой узел помещать Pod
  kube-controller-manager — следит за состоянием (ReplicaSet, Node...)
  cloud-controller-manager — интеграция с облаком (AWS, GCP, Azure)

Worker Nodes (рабочие узлы):
  kubelet           — агент, запускает и следит за Pod-ами
  kube-proxy        — сетевые правила (iptables/ipvs)
  Container Runtime — containerd, CRI-O (запуск контейнеров)

Основные объекты:
  Pod         — минимальная единица, 1+ контейнеров с общей сетью
  ReplicaSet  — поддерживает N копий Pod-а
  Deployment  — управляет ReplicaSet, rolling updates
  Service     — стабильный IP/DNS для набора Pod-ов
  Ingress     — HTTP-маршрутизация снаружи в Service
  ConfigMap   — конфигурация (не секреты)
  Secret      — секреты (base64)
  Namespace   — логическое разделение кластера
  PV/PVC      — постоянное хранилище
  StatefulSet — Pod-ы с постоянной идентичностью (БД)
  DaemonSet   — по одному Pod-у на каждый узел
  Job/CronJob — разовые и периодические задачи`)

	utils.Section("kubectl — основные команды")
	utils.Code(`# Контексты и кластеры:
kubectl config get-contexts            # список контекстов
kubectl config use-context prod        # переключить кластер
kubectl config current-context
export KUBECONFIG=~/.kube/config`)

	utils.Println(utils.ColorBold + "Просмотр ресурсов:" + utils.ColorReset)
	utils.Command("kubectl get pods", "Pod-ы в текущем namespace")
	utils.Command("kubectl get pods -n kube-system", "в namespace kube-system")
	utils.Command("kubectl get pods -A", "во всех namespace")
	utils.Command("kubectl get pods -o wide", "с IP и узлом")
	utils.Command("kubectl get all", "все ресурсы namespace")
	utils.Command("kubectl describe pod mypod", "подробная информация")
	utils.Command("kubectl logs mypod", "логи Pod-а")
	utils.Command("kubectl logs -f mypod -c mycontainer", "следить, конкретный контейнер")
	utils.Command("kubectl exec -it mypod -- bash", "shell в Pod-е")
	utils.Command("kubectl top pods", "использование ресурсов")
	utils.Command("kubectl top nodes", "ресурсы узлов")
	fmt.Println()
	utils.Println(utils.ColorBold + "Применение манифестов:" + utils.ColorReset)
	utils.Command("kubectl apply -f deployment.yaml", "применить манифест")
	utils.Command("kubectl apply -f ./manifests/", "применить директорию")
	utils.Command("kubectl delete -f deployment.yaml", "удалить по манифесту")
	utils.Command("kubectl delete pod mypod", "удалить Pod")
	utils.Command("kubectl get pod mypod -o yaml", "экспортировать манифест")
	utils.Command("kubectl edit deployment myapp", "редактировать в редакторе")

	utils.Section("Основные объекты — манифесты")
	utils.Code(`# Pod (редко создаётся напрямую):
apiVersion: v1
kind: Pod
metadata:
  name: mypod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: myapp:1.0
    ports:
    - containerPort: 8000
    resources:
      requests:
        memory: "64Mi"
        cpu: "100m"
      limits:
        memory: "128Mi"
        cpu: "500m"
    env:
    - name: DATABASE_URL
      valueFrom:
        secretKeyRef:
          name: myapp-secret
          key: db-url
    livenessProbe:
      httpGet:
        path: /health
        port: 8000
      initialDelaySeconds: 10
      periodSeconds: 15
    readinessProbe:
      httpGet:
        path: /ready
        port: 8000`)

	utils.Code(`# Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:1.0
        ports:
        - containerPort: 8000`)

	utils.Code(`# Service:
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  selector:
    app: myapp
  ports:
  - port: 80
    targetPort: 8000
  type: ClusterIP   # ClusterIP / NodePort / LoadBalancer

# ClusterIP  — только внутри кластера
# NodePort   — доступен снаружи на порту 30000-32767
# LoadBalancer — облачный балансировщик`)

	utils.Code(`# Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-svc
            port:
              number: 80
  tls:
  - hosts:
    - myapp.example.com
    secretName: myapp-tls`)

	utils.Code(`# ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
  name: myapp-config
data:
  LOG_LEVEL: "info"
  APP_PORT: "8000"
  nginx.conf: |
    server {
      listen 80;
      location / { proxy_pass http://backend; }
    }

# Secret (значения в base64):
apiVersion: v1
kind: Secret
metadata:
  name: myapp-secret
type: Opaque
data:
  db-password: cGFzc3dvcmQ=   # echo -n 'password' | base64
stringData:
  db-url: "postgresql://user:pass@db:5432/mydb"  # автоматически base64`)

	utils.Section("Масштабирование и обновление")
	utils.Command("kubectl scale deployment myapp --replicas=5", "масштабировать")
	utils.Command("kubectl rollout status deployment/myapp", "статус обновления")
	utils.Command("kubectl rollout history deployment/myapp", "история обновлений")
	utils.Command("kubectl rollout undo deployment/myapp", "откатить обновление")
	utils.Command("kubectl rollout undo deployment/myapp --to-revision=2", "к конкретной версии")
	utils.Command("kubectl set image deployment/myapp myapp=myapp:2.0", "обновить образ")

	utils.Section("Namespaces и RBAC")
	utils.Code(`kubectl create namespace staging
kubectl get namespaces

# ResourceQuota — ограничения ресурсов namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
  name: staging-quota
  namespace: staging
spec:
  hard:
    requests.cpu: "4"
    requests.memory: 8Gi
    limits.cpu: "8"
    limits.memory: 16Gi
    pods: "50"

# RBAC — управление доступом:
# Role → namespace, ClusterRole → весь кластер
# RoleBinding / ClusterRoleBinding → привязка к субъекту
kubectl create role developer --verb=get,list,create --resource=pods -n staging
kubectl create rolebinding alice-developer \
  --role=developer --user=alice -n staging`)

	utils.Section("Helm — пакетный менеджер Kubernetes")
	utils.Code(`# Установка: https://helm.sh/docs/intro/install/

helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo bitnami/postgresql

helm install mydb bitnami/postgresql \
  --set auth.postgresPassword=secret \
  --set primary.persistence.size=20Gi \
  --namespace db --create-namespace

helm list -A               # установленные релизы
helm status mydb           # статус релиза
helm upgrade mydb bitnami/postgresql --set auth.postgresPassword=newsecret
helm rollback mydb 1       # откатить
helm uninstall mydb

# Создать свой chart:
helm create mychart
helm template mychart ./mychart/     # рендеринг без установки
helm install myapp ./mychart/ -f values.yaml`)

	utils.Footer()
}
