#!/bin/bash
# -*- coding: utf-8 -*-

###############################################################################
# Скрипт установки Cascad360 из исходников (NFR-013)
# 
# Поддерживаемые дистрибутивы:
#   - Debian / Ubuntu (apt)
#   - CentOS / RHEL / Fedora (yum / dnf)
#   - Alpine Linux (apk)
#
# Опции:
#   --docker          Установка через Docker
#   --kubernetes     Установка через Kubernetes (Helm)
#   --dev            Установка для разработки
#   --help           Показать справку
###############################################################################

set -e  # Выход при ошибке

# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Переменные
INSTALL_DIR="${INSTALL_DIR:-/opt/cascad360}"
PYTHON_VERSION="${PYTHON_VERSION:-3.11}"
VENV_DIR="${VENV_DIR:-$INSTALL_DIR/venv}"
INSTALL_MODE="${INSTALL_MODE:-native}"  # native, docker, kubernetes

# Функции для вывода
info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

success() {
    echo -e "${GREEN}[SUCCESS]${NC} $1"
}

warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# Проверка прав root
check_root() {
    if [ "$EUID" -ne 0 ] && [ "$INSTALL_MODE" != "docker" ] && [ "$INSTALL_MODE" != "kubernetes" ]; then
        warning "Рекомендуется запускать установку с правами root для системной установки"
        warning "Продолжаем установку в пользовательском режиме..."
    fi
}

# Определение дистрибутива и менеджера пакетов
detect_distro() {
    DISTRO="unknown"
    PKG_MANAGER="unknown"

    if [ -f /etc/os-release ]; then
        . /etc/os-release
        DISTRO="${ID:-unknown}"
    elif [ -f /etc/alpine-release ]; then
        DISTRO="alpine"
    elif [ -f /etc/redhat-release ]; then
        DISTRO="rhel"
    fi

    if command -v apk &> /dev/null; then
        PKG_MANAGER="apk"
    elif command -v apt-get &> /dev/null; then
        PKG_MANAGER="apt"
    elif command -v dnf &> /dev/null; then
        PKG_MANAGER="dnf"
    elif command -v yum &> /dev/null; then
        PKG_MANAGER="yum"
    fi

    info "Дистрибутив: $DISTRO, менеджер пакетов: $PKG_MANAGER"
}

# Проверка наличия systemd / init системы
has_systemd() {
    # Проверяем наличие systemctl и работающего systemd (PID 1)
    if command -v systemctl &> /dev/null && [ -d /run/systemd/system ]; then
        return 0
    fi
    return 1
}

has_openrc() {
    if command -v rc-service &> /dev/null; then
        return 0
    fi
    return 1
}

# Универсальная установка системных зависимостей
install_system_package() {
    local pkg_apt="$1"
    local pkg_yum="$2"
    local pkg_apk="$3"

    case "$PKG_MANAGER" in
        apt)
            apt-get update -qq && apt-get install -y -qq "$pkg_apt" ;;
        dnf)
            dnf install -y -q "$pkg_yum" ;;
        yum)
            yum install -y -q "$pkg_yum" ;;
        apk)
            apk add --no-cache "$pkg_apk" ;;
        *)
            warning "Не удалось установить пакет: неизвестный менеджер пакетов"
            return 1 ;;
    esac
}

# Проверка зависимостей системы
check_dependencies() {
    info "Проверка системных зависимостей..."
    
    detect_distro

    local missing_deps=()
    
    # Проверка Python
    if ! command -v python3 &> /dev/null; then
        missing_deps+=("python3")
    else
        local py_version=$(python3 --version | cut -d' ' -f2 | cut -d'.' -f1,2)
        if [ "$(printf '%s\n' "$PYTHON_VERSION" "$py_version" | sort -V | head -n1)" != "$PYTHON_VERSION" ]; then
            warning "Требуется Python $PYTHON_VERSION или выше, найден $py_version"
        fi
    fi
    
    # Проверка pip
    if ! command -v pip3 &> /dev/null; then
        missing_deps+=("pip")
    fi
    
    # Проверка git (для клонирования репозитория)
    if ! command -v git &> /dev/null; then
        missing_deps+=("git")
    fi
    
    if [ ${#missing_deps[@]} -ne 0 ]; then
        error "Отсутствуют необходимые зависимости: ${missing_deps[*]}"
        info "Установите их командой:"
        case "$PKG_MANAGER" in
            apt)
                echo "  sudo apt-get update && sudo apt-get install -y python3 python3-pip python3-venv git" ;;
            dnf)
                echo "  sudo dnf install -y python3 python3-pip git" ;;
            yum)
                echo "  sudo yum install -y python3 python3-pip git" ;;
            apk)
                echo "  apk add python3 py3-pip git" ;;
            *)
                echo "  Установите вручную: python3, pip3, git" ;;
        esac
        exit 1
    fi
    
    success "Все системные зависимости установлены"
}

# Установка Python зависимостей
install_python_dependencies() {
    info "Установка Python зависимостей..."
    
    # Создаем виртуальное окружение, если его нет
    if [ ! -d "$VENV_DIR" ]; then
        info "Создание виртуального окружения Python..."
        python3 -m venv "$VENV_DIR"
    fi
    
    # Активируем виртуальное окружение
    source "$VENV_DIR/bin/activate"
    
    # Обновляем pip
    pip install --upgrade pip setuptools wheel
    
    # Устанавливаем зависимости
    if [ -f "$INSTALL_DIR/requirements.txt" ]; then
        pip install -r "$INSTALL_DIR/requirements.txt"
        success "Python зависимости установлены"
    else
        error "Файл requirements.txt не найден в $INSTALL_DIR"
        exit 1
    fi
}

# Создание конфигурации по умолчанию
create_default_config() {
    info "Создание конфигурации по умолчанию..."
    
    local config_file="$INSTALL_DIR/config.yml"
    
    if [ ! -f "$config_file" ]; then
        cat > "$config_file" << 'EOF'
app:
  name: Cascad360
  setup_completed: false

web:
  host: 0.0.0.0
  port: 5000
  debug: false

database:
  driver: mysql
  host: localhost
  port: 3306
  database: cascad360
  username: cascad360_user
  password: cascad360_password
  charset: utf8mb4
  root:
    username: root
    password: ''

logging:
  level: INFO
  format: json
  console: true
EOF
        success "Конфигурация по умолчанию создана: $config_file"
        warning "Не забудьте настроить параметры подключения к БД!"
    else
        info "Конфигурация уже существует: $config_file"
    fi
}

# Создание системного пользователя (кросс-дистрибутив)
create_service_user() {
    if id "cascad360" &>/dev/null; then
        return
    fi
    if command -v useradd &> /dev/null; then
        useradd -r -s /usr/sbin/nologin -d "$INSTALL_DIR" cascad360
    elif command -v adduser &> /dev/null; then
        # Alpine Linux
        adduser -D -H -S -s /sbin/nologin -h "$INSTALL_DIR" cascad360
    else
        warning "Не удалось создать пользователя cascad360 — создайте вручную"
        return
    fi
    info "Создан системный пользователь: cascad360"
}

# Проверка: текущая директория — готовая сборка (PyInstaller: cascad360 + _internal)
is_bundle_dir() {
    [ -f "$INSTALL_DIR/cascad360" ] && [ -d "$INSTALL_DIR/_internal" ]
}

# Создание сервиса автозапуска (systemd / OpenRC / fallback)
create_service() {
    if [ "$EUID" -ne 0 ]; then
        warning "Пропускаем создание сервиса (требуются права root)"
        if is_bundle_dir; then
            info "Для ручного запуска: cd $INSTALL_DIR && ./cascad360"
        else
            info "Для ручного запуска: cd $INSTALL_DIR && $VENV_DIR/bin/python main.py"
        fi
        return
    fi

    # Создаём пользователя
    create_service_user

    # Устанавливаем права
    chown -R cascad360:cascad360 "$INSTALL_DIR"

    if has_systemd; then
        _create_systemd_service
    elif has_openrc; then
        _create_openrc_service
    else
        warning "Ни systemd, ни OpenRC не обнаружены. Сервис автозапуска не создан."
        if is_bundle_dir; then
            info "Для ручного запуска: cd $INSTALL_DIR && ./cascad360"
        else
            info "Для ручного запуска: cd $INSTALL_DIR && $VENV_DIR/bin/python main.py"
        fi
    fi
}

# systemd unit
_create_systemd_service() {
    info "Создание systemd service..."

    local service_file="/etc/systemd/system/cascad360.service"
    local exec_start
    if is_bundle_dir; then
        exec_start="$INSTALL_DIR/cascad360"
    else
        exec_start="$VENV_DIR/bin/python $INSTALL_DIR/main.py"
    fi

    cat > "$service_file" << EOF
[Unit]
Description=Cascad360 - API Gateway и Service Mesh
After=network.target

[Service]
Type=simple
User=cascad360
Group=cascad360
WorkingDirectory=$INSTALL_DIR
Environment="PATH=$VENV_DIR/bin"
ExecStart=$exec_start
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
EOF

    systemctl daemon-reload
    success "Systemd service создан: $service_file"
    info "Для запуска: sudo systemctl start cascad360"
    info "Для автозапуска: sudo systemctl enable cascad360"
}

# OpenRC init script (Alpine Linux)
_create_openrc_service() {
    info "Создание OpenRC init script..."

    local init_file="/etc/init.d/cascad360"
    local run_cmd run_args
    if is_bundle_dir; then
        run_cmd="$INSTALL_DIR/cascad360"
        run_args=""
    else
        run_cmd="$VENV_DIR/bin/python"
        run_args="$INSTALL_DIR/main.py"
    fi

    cat > "$init_file" << EOF
#!/sbin/openrc-run

name="cascad360"
description="Cascad360 - API Gateway и Service Mesh"
command="$run_cmd"
command_args="$run_args"
command_user="cascad360"
command_background=true
pidfile="/run/\${RC_SVCNAME}.pid"
output_log="/var/log/cascad360.log"
error_log="/var/log/cascad360.err"

directory="$INSTALL_DIR"

depend() {
    need net
    after firewall
}
EOF

    chmod 755 "$init_file"
    success "OpenRC init script создан: $init_file"
    info "Для запуска: rc-service cascad360 start"
    info "Для автозапуска: rc-update add cascad360 default"
}

# Установка через Docker
install_docker() {
    info "Установка через Docker..."
    
    # Проверка Docker
    if ! command -v docker &> /dev/null; then
        error "Docker не установлен. Установите Docker: https://docs.docker.com/get-docker/"
        exit 1
    fi
    
    # Проверка docker-compose
    if ! command -v docker-compose &> /dev/null && ! docker compose version &> /dev/null; then
        error "docker-compose не установлен. Установите docker-compose"
        exit 1
    fi
    
    # Проверяем наличие docker-compose.yml (должен быть за пределами проекта)
    if [ ! -f "docker-compose.yml" ]; then
        warning "docker-compose.yml не найден в текущей директории"
        info "Убедитесь, что docker-compose.yml находится за пределами проекта"
        info "Или создайте его вручную на основе примера из документации"
        exit 1
    fi
    
    info "Запуск контейнеров..."
    if command -v docker-compose &> /dev/null; then
        docker-compose up -d
    else
        docker compose up -d
    fi
    
    success "Cascad360 запущен в Docker контейнерах"
    info "Проверьте статус: docker-compose ps"
    info "Логи: docker-compose logs -f"
}

# Установка через Kubernetes (Helm)
install_kubernetes() {
    info "Установка через Kubernetes (Helm)..."
    
    # Проверка kubectl
    if ! command -v kubectl &> /dev/null; then
        error "kubectl не установлен. Установите kubectl: https://kubernetes.io/docs/tasks/tools/"
        exit 1
    fi
    
    # Проверка Helm
    if ! command -v helm &> /dev/null; then
        error "Helm не установлен. Установите Helm: https://helm.sh/docs/intro/install/"
        exit 1
    fi
    
    # Проверка наличия Helm chart
    if [ ! -d "helm/cascad360" ]; then
        warning "Helm chart не найден. Создаем базовый chart..."
        create_helm_chart
    fi
    
    info "Установка Cascad360 через Helm..."
    helm install cascad360 ./helm/cascad360 \
        --namespace cascad360 \
        --create-namespace \
        --set database.host=mysql \
        --set database.database=cascad360
    
    success "Cascad360 установлен в Kubernetes"
    info "Проверьте статус: kubectl get pods -n cascad360"
}

# Нативная установка (из исходников или из готовой сборки)
install_native() {
    info "Нативная установка Cascad360..."
    
    local from_bundle=0
    local need_copy=0
    
    # Запуск из директории с готовой сборкой (исполняемый файл + _internal)
    if [ -f "cascad360" ] && [ -d "_internal" ]; then
        from_bundle=1
        INSTALL_DIR="$(pwd)"
        VENV_DIR="$INSTALL_DIR/venv"
        info "Обнаружена готовая сборка в $INSTALL_DIR, установка на месте"
    elif [ -f "main.py" ]; then
        need_copy=1
    else
        error "Скрипт должен запускаться из директории проекта (с main.py) или из директории со сборкой (cascad360 + _internal)"
        exit 1
    fi
    
    mkdir -p "$INSTALL_DIR"
    
    if [ "$need_copy" -eq 1 ]; then
        # Установка из исходников: копируем файлы и ставим зависимости
        info "Копирование файлов приложения..."
        if [ "$(pwd)" != "$(realpath "$INSTALL_DIR" 2>/dev/null || echo "$INSTALL_DIR")" ]; then
            cp -r . "$INSTALL_DIR/" 2>/dev/null || {
                if [ -d ".git" ]; then
                    info "Клонирование репозитория..."
                    git clone . "$INSTALL_DIR" || {
                        error "Не удалось скопировать файлы приложения"
                        exit 1
                    }
                else
                    error "Не удалось скопировать файлы приложения"
                    exit 1
                fi
            }
        fi
        install_python_dependencies
    else
        # Готовая сборка: создаём config.yml из примера при необходимости
        if [ ! -f "$INSTALL_DIR/config.yml" ] && [ -f "$INSTALL_DIR/config.yml.example" ]; then
            info "Создание config.yml из config.yml.example..."
            cp "$INSTALL_DIR/config.yml.example" "$INSTALL_DIR/config.yml"
            warning "Настройте параметры в $INSTALL_DIR/config.yml"
        fi
    fi
    
    # Конфигурация: создаём по умолчанию только если её ещё нет
    if [ "$from_bundle" -ne 1 ] || [ ! -f "$INSTALL_DIR/config.yml" ]; then
        create_default_config
    fi
    
    create_service
    
    success "Cascad360 установлен в $INSTALL_DIR"
    if [ "$from_bundle" -eq 1 ]; then
        info "Для запуска: cd $INSTALL_DIR && ./cascad360"
    else
        info "Для запуска: cd $INSTALL_DIR && $VENV_DIR/bin/python main.py"
    fi
    if [ "$EUID" -eq 0 ]; then
        if has_systemd; then
            info "Или через systemd: sudo systemctl start cascad360"
        elif has_openrc; then
            info "Или через OpenRC: rc-service cascad360 start"
        fi
    fi
}

# Примечание: Docker файлы (Dockerfile, docker-compose.yml) должны находиться
# за пределами проекта, так как проект уже работает в контейнере

# Создание базового Helm chart
create_helm_chart() {
    info "Создание Helm chart..."
    
    mkdir -p helm/cascad360/templates
    mkdir -p helm/cascad360/charts
    
    # Chart.yaml
    cat > helm/cascad360/Chart.yaml << 'EOF'
apiVersion: v2
name: cascad360
description: Cascad360 - API Gateway и Service Mesh
type: application
version: 1.0.0
appVersion: "1.0.0"
keywords:
  - api-gateway
  - service-mesh
  - microservices
maintainers:
  - name: Cascad360 Team
EOF
    
    # values.yaml
    cat > helm/cascad360/values.yaml << 'EOF'
replicaCount: 1

image:
  repository: cascad360
  pullPolicy: IfNotPresent
  tag: "latest"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

service:
  type: ClusterIP
  port: 5000

ingress:
  enabled: false
  className: ""
  annotations: {}
  hosts:
    - host: cascad360.local
      paths:
        - path: /
          pathType: Prefix
  tls: []

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

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

database:
  host: mysql
  port: 3306
  database: cascad360
  username: cascad360_user
  password: cascad360_password

config:
  web:
    host: "0.0.0.0"
    port: 5000
    debug: false

nodeSelector: {}
tolerations: []
affinity: {}
EOF
    
    # Deployment template
    cat > helm/cascad360/templates/deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "cascad360.fullname" . }}
  labels:
    {{- include "cascad360.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "cascad360.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "cascad360.selectorLabels" . | nindent 8 }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: {{ .Values.service.port }}
              protocol: TCP
          env:
            - name: DATABASE_HOST
              value: {{ .Values.database.host | quote }}
            - name: DATABASE_PORT
              value: {{ .Values.database.port | quote }}
            - name: DATABASE_NAME
              value: {{ .Values.database.database | quote }}
            - name: DATABASE_USER
              value: {{ .Values.database.username | quote }}
            - name: DATABASE_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: {{ include "cascad360.fullname" . }}-secret
                  key: database-password
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          volumeMounts:
            - name: config
              mountPath: /app/config.yml
              subPath: config.yml
      volumes:
        - name: config
          configMap:
            name: {{ include "cascad360.fullname" . }}-config
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}
EOF
    
    # Service template
    cat > helm/cascad360/templates/service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: {{ include "cascad360.fullname" . }}
  labels:
    {{- include "cascad360.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    {{- include "cascad360.selectorLabels" . | nindent 4 }}
EOF
    
    # ConfigMap template
    cat > helm/cascad360/templates/configmap.yaml << 'EOF'
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "cascad360.fullname" . }}-config
  labels:
    {{- include "cascad360.labels" . | nindent 4 }}
data:
  config.yml: |
    app:
      name: Cascad360
      setup_completed: false
    web:
      host: {{ .Values.config.web.host | quote }}
      port: {{ .Values.config.web.port }}
      debug: {{ .Values.config.web.debug }}
    database:
      driver: mysql
      host: {{ .Values.database.host | quote }}
      port: {{ .Values.database.port }}
      database: {{ .Values.database.database | quote }}
      username: {{ .Values.database.username | quote }}
      password: {{ .Values.database.password | quote }}
EOF
    
    # Secret template
    cat > helm/cascad360/templates/secret.yaml << 'EOF'
apiVersion: v1
kind: Secret
metadata:
  name: {{ include "cascad360.fullname" . }}-secret
  labels:
    {{- include "cascad360.labels" . | nindent 4 }}
type: Opaque
data:
  database-password: {{ .Values.database.password | b64enc | quote }}
EOF
    
    # _helpers.tpl
    cat > helm/cascad360/templates/_helpers.tpl << 'EOF'
{{- define "cascad360.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{- define "cascad360.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{- define "cascad360.labels" -}}
helm.sh/chart: {{ include "cascad360.chart" . }}
{{ include "cascad360.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{- define "cascad360.selectorLabels" -}}
app.kubernetes.io/name: {{ include "cascad360.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{- define "cascad360.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
EOF
    
    success "Helm chart создан в helm/cascad360/"
}

# Показ справки
show_help() {
    cat << EOF
Скрипт установки Cascad360 (NFR-013)

Использование:
    $0 [опции]

Опции:
    --docker          Установка через Docker (docker-compose)
    --kubernetes      Установка через Kubernetes (Helm)
    --dev             Установка для разработки (без systemd)
    --dir DIR         Директория установки (по умолчанию: $INSTALL_DIR)
    --help            Показать эту справку

Переменные окружения:
    INSTALL_DIR       Директория установки (по умолчанию: $INSTALL_DIR)
    PYTHON_VERSION    Требуемая версия Python (по умолчанию: $PYTHON_VERSION)

Примеры:
    # Нативная установка
    $0

    # Установка через Docker
    $0 --docker

    # Установка через Kubernetes
    $0 --kubernetes

    # Установка в пользовательскую директорию
    INSTALL_DIR=~/cascad360 $0

EOF
}

# Главная функция
main() {
    info "=== Установка Cascad360 (NFR-013) ==="
    
    # Парсинг аргументов
    while [[ $# -gt 0 ]]; do
        case $1 in
            --docker)
                INSTALL_MODE="docker"
                shift
                ;;
            --kubernetes)
                INSTALL_MODE="kubernetes"
                shift
                ;;
            --dev)
                INSTALL_MODE="dev"
                shift
                ;;
            --dir)
                INSTALL_DIR="$2"
                shift 2
                ;;
            --help)
                show_help
                exit 0
                ;;
            *)
                error "Неизвестная опция: $1"
                show_help
                exit 1
                ;;
        esac
    done
    
    # Проверка прав
    check_root
    
    # Выбор режима установки
    case $INSTALL_MODE in
        docker)
            install_docker
            ;;
        kubernetes)
            install_kubernetes
            ;;
        *)
            # При установке из готовой сборки (cascad360 + _internal) Python/pip/git не требуются
            if [ ! -f "cascad360" ] || [ ! -d "_internal" ]; then
                check_dependencies
            fi
            install_native
            ;;
    esac
    
    success "=== Установка завершена ==="
    info "Следующие шаги:"
    info "1. Настройте config.yml с параметрами подключения к БД"
    info "2. Запустите приложение для первоначальной настройки"
    info "3. Откройте браузер и перейдите на http://localhost:5000/setup"
}

# Запуск главной функции
main "$@"
