system/config/project-paths.sh
#!/bin/bash
# ═══════════════════════════════════════════════════════════════════════════════
# ПЕРЕМЕННЫЕ ОКРУЖЕНИЯ ПРОЕКТОВ
# Единый источник правды для путей
# ═══════════════════════════════════════════════════════════════════════════════
#
# Версия: 1.0.0
# Дата: 2026-02-14
#
# ПРОБЛЕМА (до этого файла):
# - Хардкод путей в стандартах (projects/org/, /mnt/beget-s3/projects/)
# - Разные структуры: workspace с org/, dataspace без org/
# - Нет валидации соответствия
#
# РЕШЕНИЕ:
# - Единый источник переменных
# - Функции для получения путей
# - Автоматическая валидация
# - Миграция структуры
#
# ═══════════════════════════════════════════════════════════════════════════════

# ═══════════════════════════════════════════════════════════════════════════════
# БАЗОВЫЕ ПРОСТРАНСТВА
# ═══════════════════════════════════════════════════════════════════════════════

export WORKSPACE=${WORKSPACE:-/opt/claude-workspace}
export DATASPACE=${DATASPACE:-/mnt/beget-s3}
export INFRA=${INFRA:-/mnt/beget-infra}

# ═══════════════════════════════════════════════════════════════════════════════
# СТРУКТУРА ПРОЕКТОВ
# ═══════════════════════════════════════════════════════════════════════════════

# КРИТИЧНО: Одинаковая структура в workspace и dataspace!
export PROJECTS_NAMESPACE="projects/org"

# ═══════════════════════════════════════════════════════════════════════════════
# ФУНКЦИИ ПОЛУЧЕНИЯ ПУТЕЙ
# ═══════════════════════════════════════════════════════════════════════════════

# Получить путь проекта в workspace (КОД)
# Использование: project_ws lideravto
# Результат: /opt/claude-workspace/projects/org/lideravto
project_ws() {
  echo "$WORKSPACE/$PROJECTS_NAMESPACE/$1"
}

# Получить путь проекта в dataspace (ДАННЫЕ)
# Использование: project_data lideravto
# Результат: /mnt/beget-s3/projects/org/lideravto
project_data() {
  echo "$DATASPACE/$PROJECTS_NAMESPACE/$1"
}

# Получить путь проекта в infra (ИНФРАСТРУКТУРА)
# Использование: project_infra lideravto
# Результат: /mnt/beget-infra/projects/org/lideravto
project_infra() {
  echo "$INFRA/$PROJECTS_NAMESPACE/$1"
}

# Экспортировать переменные для текущего проекта
# Использование: set_project lideravto
set_project() {
  export PROJECT_NAME=$1
  export PROJECT_WS=$(project_ws $1)
  export PROJECT_DATA=$(project_data $1)
  export PROJECT_INFRA=$(project_infra $1)

  echo "Проект: $PROJECT_NAME"
  echo "  Workspace: $PROJECT_WS"
  echo "  Dataspace: $PROJECT_DATA"
  echo "  Infra:     $PROJECT_INFRA"
}

# ═══════════════════════════════════════════════════════════════════════════════
# ВАЛИДАЦИЯ СТРУКТУРЫ
# ═══════════════════════════════════════════════════════════════════════════════

# Проверить соответствие структуры проекта
# Использование: validate_project lideravto
validate_project() {
  local name=$1
  local ws=$(project_ws $name)
  local data=$(project_data $name)
  local errors=0

  # Проверка workspace
  if [ ! -d "$ws" ]; then
    echo "⚠️  WARNING: Workspace не существует: $ws"
    ((errors++))
  fi

  # Проверка dataspace
  if [ ! -d "$data" ]; then
    echo "❌ ERROR: Dataspace не существует: $data"
    ((errors++))
  fi

  # Проверка соответствия
  if [ -d "$ws" ] && [ ! -d "$data" ]; then
    echo "❌ ERROR: Нарушение стандарта!"
    echo "   Workspace: $ws (exists)"
    echo "   Dataspace: $data (MISSING)"
    echo "   → Пути должны быть ОДИНАКОВЫЕ!"
    ((errors++))
  fi

  if [ $errors -eq 0 ]; then
    echo "✅ OK: $name"
    return 0
  else
    return 1
  fi
}

# Проверить все проекты
# Использование: validate_all_projects
validate_all_projects() {
  echo "═══════════════════════════════════════════════════════════"
  echo "Проверка соответствия workspace ↔ dataspace"
  echo "═══════════════════════════════════════════════════════════"

  local total=0
  local errors=0

  if [ ! -d "$WORKSPACE/$PROJECTS_NAMESPACE" ]; then
    echo "❌ ERROR: $WORKSPACE/$PROJECTS_NAMESPACE не существует!"
    return 1
  fi

  for project in $(ls $WORKSPACE/$PROJECTS_NAMESPACE/ 2>/dev/null); do
    ((total++))
    echo ""
    if ! validate_project $project; then
      ((errors++))
    fi
  done

  echo ""
  echo "═══════════════════════════════════════════════════════════"
  echo "Проверено проектов: $total"
  echo "Ошибок: $errors"

  if [ $errors -eq 0 ]; then
    echo "✅ Все проекты соответствуют стандарту"
    return 0
  else
    echo "❌ Найдены нарушения стандарта"
    return 1
  fi
}

# ═══════════════════════════════════════════════════════════════════════════════
# МИГРАЦИЯ СТРУКТУРЫ
# ═══════════════════════════════════════════════════════════════════════════════

# Исправить структуру dataspace для проекта
# Переместить из projects/{name} в projects/org/{name}
# Использование: fix_dataspace_structure lideravto
fix_dataspace_structure() {
  local name=$1
  local old_path="$DATASPACE/projects/$name"
  local new_path="$DATASPACE/$PROJECTS_NAMESPACE/$name"

  if [ ! -d "$old_path" ]; then
    echo "⚠️  Проект не найден в старом пути: $old_path"
    return 1
  fi

  if [ -d "$new_path" ]; then
    echo "⚠️  Новый путь уже существует: $new_path"
    return 1
  fi

  echo "Исправляю структуру: $name"
  echo "  Из: $old_path"
  echo "  В:  $new_path"

  # Создать родительскую папку
  mkdir -p "$(dirname $new_path)"

  # Переместить
  mv "$old_path" "$new_path"

  if [ $? -eq 0 ]; then
    echo "✅ Успешно перемещено"
    return 0
  else
    echo "❌ Ошибка перемещения"
    return 1
  fi
}

# Исправить все проекты в dataspace
# Использование: fix_all_dataspace
fix_all_dataspace() {
  echo "═══════════════════════════════════════════════════════════"
  echo "Миграция структуры dataspace: projects/{name} → projects/org/{name}"
  echo "═══════════════════════════════════════════════════════════"

  local total=0
  local fixed=0

  # Найти проекты которые есть в workspace
  for project in $(ls $WORKSPACE/$PROJECTS_NAMESPACE/ 2>/dev/null); do
    local old_path="$DATASPACE/projects/$project"

    if [ -d "$old_path" ]; then
      ((total++))
      echo ""
      if fix_dataspace_structure $project; then
        ((fixed++))
      fi
    fi
  done

  echo ""
  echo "═══════════════════════════════════════════════════════════"
  echo "Найдено для миграции: $total"
  echo "Успешно перемещено: $fixed"

  return 0
}

# ═══════════════════════════════════════════════════════════════════════════════
# HELP
# ═══════════════════════════════════════════════════════════════════════════════

# Показать справку
project_paths_help() {
  cat << 'EOF'
═══════════════════════════════════════════════════════════════════════════════
СИСТЕМА ПЕРЕМЕННЫХ ПРОЕКТОВ
═══════════════════════════════════════════════════════════════════════════════

ИСПОЛЬЗОВАНИЕ:
  source system/config/project-paths.sh

ПЕРЕМЕННЫЕ:
  $WORKSPACE         /opt/claude-workspace
  $DATASPACE         /mnt/beget-s3
  $INFRA             /mnt/beget-infra
  $PROJECTS_NAMESPACE  projects/org

ФУНКЦИИ:
  project_ws NAME         Путь в workspace
  project_data NAME       Путь в dataspace
  project_infra NAME      Путь в infra
  set_project NAME        Экспортировать переменные проекта

ВАЛИДАЦИЯ:
  validate_project NAME   Проверить один проект
  validate_all_projects   Проверить все проекты

МИГРАЦИЯ:
  fix_dataspace_structure NAME  Исправить структуру одного проекта
  fix_all_dataspace             Исправить все проекты

ПРИМЕРЫ:
  # Получить пути
  project_ws lideravto
  # → /opt/claude-workspace/projects/org/lideravto

  # Установить проект
  set_project lideravto
  cd $PROJECT_WS

  # Проверить
  validate_all_projects

  # Исправить структуру
  fix_all_dataspace

═══════════════════════════════════════════════════════════════════════════════
EOF
}

# ═══════════════════════════════════════════════════════════════════════════════
# INIT
# ═══════════════════════════════════════════════════════════════════════════════

# Если вызван как скрипт (не source)
if [ "${BASH_SOURCE[0]}" = "${0}" ]; then
  case "${1:-help}" in
    help)
      project_paths_help
      ;;
    validate)
      validate_all_projects
      ;;
    fix)
      fix_all_dataspace
      ;;
    *)
      echo "Использование: $0 {help|validate|fix}"
      exit 1
      ;;
  esac
fi