package linuxmodules

import (
	"fmt"
	"rubric/utils"
)

var ProcessesModule = Module{
	Key:         "processes",
	Aliases:     []string{"proc", "ps", "процессы"},
	Title:       "Процессы",
	Description: "Темы 14–16: информация о процессах, сигналы, управление процессами",
	Run:         showProcesses,
}

func showProcesses() {
	utils.Header("Linux — Процессы")

	// ─── 14. Процессы №1: информация ─────────────────────────────
	utils.Section("14. Процессы №1: информация о процессах")

	utils.Println("Процесс — выполняющаяся программа. Каждый процесс имеет уникальный PID.")
	fmt.Println()
	utils.Println(utils.ColorBold + "ps — информация о процессах:" + utils.ColorReset)
	utils.Command("ps", "процессы текущего терминала")
	utils.Command("ps aux", "все процессы всех пользователей (BSD стиль)")
	utils.Command("ps -ef", "все процессы (UNIX стиль)")
	utils.Command("ps aux | grep nginx", "найти процессы nginx")
	utils.Command("ps -u alice", "процессы пользователя alice")
	utils.Command("ps --forest", "дерево процессов (родитель → потомок)")
	fmt.Println()
	utils.Code(`# Вывод ps aux:
USER  PID  %CPU %MEM    VSZ   RSS TTY  STAT START TIME COMMAND
root    1   0.0  0.1 168384 13312 ?    Ss   Jan01 0:05 /sbin/init
alice 1234  2.1  1.5 567890 61234 pts/0 Sl  10:30 0:12 firefox

Поля:
USER   — владелец процесса
PID    — Process ID (уникальный номер)
PPID   — Parent PID (родительский процесс)
%CPU   — использование процессора
%MEM   — использование памяти
VSZ    — виртуальная память (КБ)
RSS    — реальная память (КБ)
TTY    — терминал (? = нет терминала, демон)
STAT   — состояние процесса
START  — время запуска
TIME   — суммарное CPU-время
COMMAND — команда

Коды состояния (STAT):
R — Running (работает)
S — Sleeping (ожидает, прерываемый)
D — Sleeping (ожидает, непрерываемый, I/O)
Z — Zombie (завершён, ждёт родителя)
T — Stopped (остановлен сигналом)
s — лидер сессии
+ — процесс переднего плана
l — многопоточный`)

	utils.Println(utils.ColorBold + "pstree — дерево процессов:" + utils.ColorReset)
	utils.Command("pstree", "дерево всех процессов")
	utils.Command("pstree -p", "с PID")
	utils.Command("pstree alice", "только процессы пользователя alice")
	fmt.Println()
	utils.Println(utils.ColorBold + "/proc — виртуальная файловая система:" + utils.ColorReset)
	utils.Code(`/proc               — информация о процессах и ядре
/proc/PID/          — директория конкретного процесса
/proc/PID/cmdline   — командная строка запуска
/proc/PID/status    — статус процесса (память, UID...)
/proc/PID/fd/       — открытые файловые дескрипторы
/proc/PID/maps      — карта памяти процесса
/proc/cpuinfo       — информация о CPU
/proc/meminfo       — информация о памяти
/proc/loadavg       — средняя загрузка

# Примеры:
cat /proc/1/cmdline           # команда процесса PID=1
cat /proc/cpuinfo | grep "model name"
cat /proc/meminfo | grep MemAvail`)

	// ─── 15. Процессы №2: информация ─────────────────────────────
	utils.Section("15. Процессы №2: мониторинг в реальном времени")

	utils.Println(utils.ColorBold + "top — динамический мониторинг:" + utils.ColorReset)
	utils.Command("top", "интерактивный мониторинг (обновляется каждые 3 сек)")
	utils.Command("top -u alice", "только процессы пользователя alice")
	utils.Command("top -p 1234,5678", "только указанные PID")
	utils.Command("top -b -n 1", "пакетный режим (для скриптов/логирования)")
	fmt.Println()
	utils.Code(`Клавиши в top:
  q        — выйти
  h        — справка
  k        — убить процесс (ввести PID)
  r        — изменить nice (приоритет)
  M        — сортировать по памяти
  P        — сортировать по CPU
  T        — сортировать по времени
  1        — показать каждый CPU отдельно
  f        — настройка столбцов
  u        — фильтр по пользователю`)

	utils.Println(utils.ColorBold + "htop — улучшенный top (нужно установить):" + utils.ColorReset)
	utils.Command("htop", "цветной интерактивный мониторинг")
	utils.Code(`# Установка:
apt install htop    # Debian/Ubuntu
dnf install htop    # RHEL/Fedora`)

	utils.Println(utils.ColorBold + "Мониторинг ресурсов:" + utils.ColorReset)
	utils.Command("free -h", "использование памяти (human-readable)")
	utils.Command("free -m", "в мегабайтах")
	utils.Command("vmstat 2 5", "статистика памяти, CPU каждые 2 сек, 5 раз")
	utils.Command("uptime", "время работы системы и средняя загрузка")
	utils.Command("w", "кто залогинен и что делает")
	utils.Command("who", "список залогиненных пользователей")
	utils.Command("last", "история входов в систему")
	fmt.Println()
	utils.Code(`# Средняя загрузка (load average):
uptime
# 10:30:00 up 5 days,  2:15,  2 users,  load average: 0.52, 0.41, 0.35
#                                                       1min  5min  15min

# Значение = количество процессов ждущих CPU
# На однопроцессорной системе:
#   < 1.0  — нормально
#   = 1.0  — 100% загрузка
#   > 1.0  — перегрузка (очередь)
# На N ядрах перегрузка начинается при load > N`)

	utils.Println(utils.ColorBold + "lsof — открытые файлы и соединения:" + utils.ColorReset)
	utils.Command("lsof", "все открытые файлы (очень много)")
	utils.Command("lsof -p 1234", "открытые файлы процесса 1234")
	utils.Command("lsof -u alice", "файлы пользователя alice")
	utils.Command("lsof -i :80", "что использует порт 80")
	utils.Command("lsof -i TCP", "все TCP соединения")
	utils.Command("lsof /var/log/syslog", "какие процессы используют этот файл")

	// ─── 16. Процессы №3: управление ─────────────────────────────
	utils.Section("16. Процессы №3: управление процессами")

	utils.Println(utils.ColorBold + "Сигналы:" + utils.ColorReset)
	utils.Code(`Сигнал — асинхронное уведомление процессу.

Номер  Имя      Действие по умолчанию
──────────────────────────────────────────────────────
1      SIGHUP   Завершить (или перечитать конфиг для демонов)
2      SIGINT   Прервать (Ctrl+C)
3      SIGQUIT  Завершить с core dump (Ctrl+\)
9      SIGKILL  Убить немедленно (нельзя перехватить/игнорировать)
15     SIGTERM  Завершить корректно (по умолчанию для kill)
17     SIGCHLD  Дочерний процесс изменил состояние
18     SIGCONT  Продолжить остановленный процесс
19     SIGSTOP  Остановить (нельзя перехватить/игнорировать)
20     SIGTSTP  Остановить (Ctrl+Z, можно перехватить)`)

	utils.Println(utils.ColorBold + "kill — отправить сигнал процессу:" + utils.ColorReset)
	utils.Command("kill 1234", "SIGTERM (15) процессу 1234 — корректное завершение")
	utils.Command("kill -9 1234", "SIGKILL — принудительное убийство")
	utils.Command("kill -15 1234", "SIGTERM явно")
	utils.Command("kill -HUP 1234", "SIGHUP (перечитать конфиг)")
	utils.Command("kill -l", "список всех сигналов")
	utils.Command("killall nginx", "SIGTERM всем процессам с именем nginx")
	utils.Command("killall -9 nginx", "SIGKILL всем nginx")
	utils.Command("pkill nginx", "SIGTERM по имени (поддерживает regex)")
	utils.Command("pkill -u alice", "завершить все процессы пользователя alice")
	fmt.Println()
	utils.Note("Сначала используйте kill (SIGTERM) — даёт процессу завершиться корректно. SIGKILL только если SIGTERM не помог.")

	utils.Println(utils.ColorBold + "Приоритет процессов (nice):" + utils.ColorReset)
	utils.Code(`Nice значение: от -20 (максимальный приоритет) до 19 (минимальный)
По умолчанию: 0

# Запустить с пониженным приоритетом:
nice -n 10 make -j4

# Изменить приоритет запущенного процесса:
renice -n 5 -p 1234      # PID
renice -n 5 -u alice     # для пользователя
# renice на отрицательное значение требует root`)

	utils.Println(utils.ColorBold + "Фоновые процессы и задания (job control):" + utils.ColorReset)
	utils.Code(`# Запустить в фоне:
command &              # & в конце
long_task.sh &

# Управление заданиями:
jobs                   # список фоновых заданий текущего терминала
jobs -l                # с PID
fg                     # вернуть последнее задание на передний план
fg %2                  # вернуть задание №2
bg                     # продолжить остановленное в фоне
bg %1                  # продолжить задание №1 в фоне

# Ctrl+Z — приостановить текущий процесс (SIGTSTP)
# Затем bg — продолжить в фоне

# Процесс продолжит работу после выхода из терминала:
nohup command &        # игнорировать SIGHUP при выходе
disown %1              # отвязать задание от терминала`)

	utils.Println(utils.ColorBold + "watch — периодически выполнять команду:" + utils.ColorReset)
	utils.Command("watch -n 2 'ps aux | grep nginx'", "каждые 2 сек смотреть процессы nginx")
	utils.Command("watch -d free -h", "следить за памятью, выделять изменения")
	utils.Command("watch -n 1 uptime", "загрузка каждую секунду")

	utils.Footer()
}
