package devopsmodules

import (
	"fmt"
	"rubric/utils"
)

var DockerModule = Module{
	Key:         "docker",
	Aliases:     []string{"d", "container", "podman"},
	Title:       "Docker и контейнеры",
	Description: "Образы, контейнеры, Dockerfile, Compose, сети, тома, Podman",
	Run:         showDocker,
}

func showDocker() {
	utils.Header("DevOps — Docker и контейнеры")

	utils.Section("Основные понятия")
	utils.Code(`Image (образ)     — неизменяемый шаблон (слои файловой системы)
Container         — запущенный экземпляр образа (изолированный процесс)
Dockerfile        — инструкции для сборки образа
Registry          — хранилище образов (Docker Hub, GHCR, ECR, Harbor)
Volume            — постоянное хранилище данных вне контейнера
Network           — виртуальная сеть между контейнерами

Изоляция через технологии ядра Linux:
- namespaces  (PID, net, mnt, uts, ipc, user)
- cgroups     (ограничение ресурсов)
- Union FS    (слоистая файловая система)`)

	utils.Section("Управление образами")
	utils.Command("docker images", "список образов")
	utils.Command("docker pull nginx:1.25", "скачать образ")
	utils.Command("docker pull nginx:latest", "последняя версия")
	utils.Command("docker push myrepo/myapp:1.0", "отправить в реестр")
	utils.Command("docker build -t myapp:1.0 .", "собрать образ из Dockerfile")
	utils.Command("docker build -t myapp:1.0 -f Dockerfile.prod .", "из другого Dockerfile")
	utils.Command("docker rmi nginx:latest", "удалить образ")
	utils.Command("docker image prune", "удалить неиспользуемые образы")
	utils.Command("docker inspect nginx", "подробная информация об образе")
	utils.Command("docker history nginx", "слои образа")
	utils.Command("docker save myapp:1.0 | gzip > myapp.tar.gz", "экспорт образа")
	utils.Command("docker load < myapp.tar.gz", "импорт образа")

	utils.Section("Управление контейнерами")
	utils.Command("docker run nginx", "запустить контейнер")
	utils.Command("docker run -d nginx", "в фоне (detached)")
	utils.Command("docker run -d -p 8080:80 --name web nginx", "с портом и именем")
	utils.Command("docker run -it ubuntu bash", "интерактивно с терминалом")
	utils.Command("docker run --rm alpine echo 'hello'", "удалить после остановки")
	fmt.Println()
	utils.Code(`# Часто используемые флаги run:
-d              — фоновый режим
-p 8080:80      — проброс порта (host:container)
-P              — автоматический проброс всех портов
--name web      — имя контейнера
-e KEY=value    — переменная окружения
--env-file .env — переменные из файла
-v /host:/cont  — монтирование тома
--network mynet — подключить к сети
--restart=always — автоперезапуск
--rm            — удалить контейнер после остановки
--memory=512m   — ограничение RAM
--cpus=0.5      — ограничение CPU
-u 1000:1000    — пользователь`)

	utils.Println(utils.ColorBold + "Жизненный цикл контейнера:" + utils.ColorReset)
	utils.Command("docker ps", "запущенные контейнеры")
	utils.Command("docker ps -a", "все контейнеры включая остановленные")
	utils.Command("docker stop web", "остановить (SIGTERM)")
	utils.Command("docker kill web", "принудительно (SIGKILL)")
	utils.Command("docker start web", "запустить остановленный")
	utils.Command("docker restart web", "перезапустить")
	utils.Command("docker rm web", "удалить остановленный")
	utils.Command("docker rm -f web", "удалить принудительно")
	utils.Command("docker container prune", "удалить все остановленные")
	fmt.Println()
	utils.Println(utils.ColorBold + "Взаимодействие с контейнером:" + utils.ColorReset)
	utils.Command("docker exec -it web bash", "открыть shell в запущенном")
	utils.Command("docker exec web ls /etc/nginx", "выполнить команду")
	utils.Command("docker logs web", "логи контейнера")
	utils.Command("docker logs -f web", "следить за логами")
	utils.Command("docker logs --tail 100 web", "последние 100 строк")
	utils.Command("docker cp web:/etc/nginx/nginx.conf .", "скопировать файл из контейнера")
	utils.Command("docker cp nginx.conf web:/etc/nginx/", "скопировать в контейнер")
	utils.Command("docker stats", "использование ресурсов")
	utils.Command("docker top web", "процессы в контейнере")

	utils.Section("Dockerfile")
	utils.Code(`# Dockerfile — инструкции сборки образа:
FROM ubuntu:22.04                      # базовый образ
LABEL maintainer="alice@example.com"   # метаданные

# Установка зависимостей:
RUN apt-get update && \
    apt-get install -y python3 python3-pip && \
    rm -rf /var/lib/apt/lists/*        # очищаем кэш в том же слое

WORKDIR /app                           # рабочая директория
COPY requirements.txt .                # копировать файлы
RUN pip install -r requirements.txt   # установить зависимости
COPY . .                               # копировать код

ENV APP_ENV=production                 # переменные окружения
EXPOSE 8000                            # документировать порт
VOLUME ["/app/data"]                   # объявить том

USER 1000:1000                         # непривилегированный пользователь
CMD ["python3", "-m", "uvicorn", "main:app", "--host", "0.0.0.0"]`)

	utils.Code(`# Многоэтапная сборка (multi-stage) — уменьшает итоговый размер:
FROM golang:1.22 AS builder
WORKDIR /build
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o app .

FROM alpine:3.19
RUN apk add --no-cache ca-certificates
WORKDIR /app
COPY --from=builder /build/app .
USER 65534:65534
CMD ["./app"]`)

	utils.Note("COPY requirements.txt и pip install ПЕРЕД COPY . — слои кэшируются, сборка быстрее.")
	utils.Note("Всегда указывай конкретный тег образа (не latest) для воспроизводимости.")

	utils.Section("Тома (Volumes)")
	utils.Code(`Типы хранилища:
Volume    — управляется Docker (/var/lib/docker/volumes/)
Bind mount — директория хоста, монтируется в контейнер
tmpfs     — только в памяти (временное)

# Named volume:
docker volume create mydata
docker run -v mydata:/app/data nginx
docker volume ls
docker volume inspect mydata
docker volume rm mydata
docker volume prune

# Bind mount:
docker run -v /host/path:/container/path nginx
docker run -v $(pwd):/app nginx          # текущая директория

# tmpfs:
docker run --tmpfs /tmp nginx`)

	utils.Section("Сети (Networks)")
	utils.Code(`Типы сетей:
bridge   — виртуальная сеть по умолчанию (контейнеры изолированы от хоста)
host     — контейнер использует сеть хоста напрямую
none     — без сети
overlay  — между несколькими хостами (Docker Swarm)

docker network ls
docker network create mynet
docker network create --subnet=172.20.0.0/16 mynet
docker run --network mynet --name db postgres
docker run --network mynet --name app myapp  # app может обращаться к db по имени!
docker network connect mynet container1
docker network disconnect mynet container1
docker network inspect mynet
docker network rm mynet`)

	utils.Section("Docker Compose")
	utils.Code(`# docker-compose.yml — многоконтейнерное приложение:
version: '3.9'

services:
  web:
    build: .
    ports:
      - "8080:8000"
    environment:
      - DATABASE_URL=postgresql://user:pass@db:5432/mydb
    volumes:
      - ./:/app
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: mydb
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      timeout: 5s
      retries: 5

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redisdata:/data

volumes:
  pgdata:
  redisdata:

networks:
  default:
    name: myapp-network`)

	utils.Println(utils.ColorBold + "Команды Compose:" + utils.ColorReset)
	utils.Command("docker compose up -d", "запустить все сервисы в фоне")
	utils.Command("docker compose up -d --build", "пересобрать образы")
	utils.Command("docker compose down", "остановить и удалить контейнеры")
	utils.Command("docker compose down -v", "удалить и тома")
	utils.Command("docker compose ps", "статус сервисов")
	utils.Command("docker compose logs -f web", "логи сервиса")
	utils.Command("docker compose exec web bash", "shell в сервисе")
	utils.Command("docker compose restart web", "перезапустить сервис")
	utils.Command("docker compose scale web=3", "масштабировать сервис")

	utils.Section("Podman — альтернатива без демона")
	utils.Code(`Podman — daemonless, rootless, совместим с Docker CLI.
Используется в RHEL вместо Docker.

# Команды идентичны Docker:
podman run -d -p 8080:80 nginx
podman build -t myapp .
podman ps
podman images

# Rootless-контейнеры (без root):
podman run --user 1000 nginx

# Podman Compose:
podman-compose up -d

# Генерация systemd-юнита для контейнера:
podman generate systemd --name mycontainer > /etc/systemd/system/mycontainer.service

# Podman Pod (группа контейнеров с общей сетью):
podman pod create --name mypod -p 8080:80
podman run -d --pod mypod nginx
podman pod ps`)

	utils.Footer()
}
