#!/bin/sh
# calista-manager - Менеджер компонентов Calista OS

# Конфигурация
SYSTEM_DIR="/calista"
REGISTRY_FILE="$SYSTEM_DIR/registry.db"
GPROXY_SCRIPT="/usr/local/bin/gproxy"  # Путь к gproxy скрипту
GPROXY_CACHE=/calista/cache/gproxy/

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

# Логирование
log() {
    echo -e "${GREEN}[+]${NC} $1"
}

error() {
    echo -e "${RED}[!]${NC} $1" >&2
}

warn() {
    echo -e "${YELLOW}[*]${NC} $1"
}

info() {
    echo -e "${BLUE}[i]${NC} $1"
}

# Запись в лог реестра
log_to_registry() {
    TYPE="$1"
    USER="${SUDO_USER:-$USER}"
    DETAILS="$2"
    
    sqlite3 "$REGISTRY_FILE" "INSERT INTO calista_log (type, user, details) VALUES ('$TYPE', '$USER', '$DETAILS');" 2>/dev/null
}

# Проверка инициализации реестра
check_init() {
    if [ ! -f "$REGISTRY_FILE" ]; then
        error "Реестр не найден: $REGISTRY_FILE"
        error "Сначала инициализируйте реестр Calista"
        exit 1
    fi

    if [ ! -x "$GPROXY_SCRIPT" ]; then
        error "Не найден gproxy скрипт: $GPROXY_SCRIPT"
        error "Поместите calista-proxy.sh в текущий каталог"
        exit 1
    fi
}

# Проверка наличия компонента в реестре
is_installed() {
    COMP_ID="$1"
    RESULT=$(sqlite3 "$REGISTRY_FILE" "SELECT COUNT(*) FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
    [ "$RESULT" -gt 0 ] 2>/dev/null
}

# Добавление компонента в реестр
add_to_registry() {
    COMP_ID="$1"
    VERSION="$2"
    SOURCE="$3"
    DESCRIPTION="$4"
    INSTALLED_AT=$(date '+%Y-%m-%d %H:%M:%S')
    
    # Проверяем, существует ли уже компонент
    EXISTS=$(sqlite3 "$REGISTRY_FILE" "SELECT COUNT(*) FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
    
    if [ "$EXISTS" -gt 0 ] 2>/dev/null; then
        # Обновляем существующий компонент
        sqlite3 "$REGISTRY_FILE" "UPDATE components SET 
            version = '$VERSION',
            source = '$SOURCE',
            description = '$DESCRIPTION',
            installed_at = '$INSTALLED_AT'
            WHERE name = '$COMP_ID';" 2>/dev/null
        
        log_to_registry "info" "Компонент $COMP_ID обновлен до версии $VERSION"
        info "Компонент '$COMP_ID' обновлен в реестре"
    else
        # Добавляем новый компонент
        sqlite3 "$REGISTRY_FILE" "INSERT INTO components (name, version, source, description, installed_at) 
            VALUES ('$COMP_ID', '$VERSION', '$SOURCE', '$DESCRIPTION', '$INSTALLED_AT');" 2>/dev/null
        
        log_to_registry "info" "Компонент $COMP_ID версии $VERSION установлен"
        info "Компонент '$COMP_ID' добавлен в реестр"
    fi
}

# Удаление компонента из реестра
remove_from_registry() {
    COMP_ID="$1"
    
    sqlite3 "$REGISTRY_FILE" "DELETE FROM components WHERE name = '$COMP_ID';" 2>/dev/null
    log_to_registry "info" "Компонент $COMP_ID удален из реестра"
}

# Получение информации о компоненте из gproxy
get_component_info() {
    COMP_ID="$1"
    VERSION="$2"

    # Получаем компонент через gproxy
    if [ "$VERSION" = "latest" ]; then
        "$GPROXY_SCRIPT" get "$COMP_ID"
    else
        "$GPROXY_SCRIPT" get "$COMP_ID" "$VERSION"
    fi
}

# Установка из Git
install_from_git() {
    COMP_ID="$1"
    VERSION="$2"

    log "Установка компонента '$COMP_ID' версии '$VERSION' из Git"

    # Проверяем не установлен ли уже
    if is_installed "$COMP_ID"; then
        warn "Компонент '$COMP_ID' уже установлен"
        # Получаем текущую версию
        CURRENT_VERSION=$(sqlite3 "$REGISTRY_FILE" "SELECT version FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
        info "Текущая версия: $CURRENT_VERSION"
        echo "Переустановить? (y/N): "
        read -r answer
        if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
            echo "Установка отменена"
            return 1
        fi
    fi

    # Получаем компонент через gproxy
    info "Загрузка компонента через gproxy..."
    gproxy set-repo ssh://git@gitlab.svsptech.ru:5598/svsptech/calista-components.git
    OUTPUT=$(get_component_info "$COMP_ID" "$VERSION")

    if echo "$OUTPUT" | grep -q "склонирован в:"; then
        # Извлекаем путь из вывода gproxy
        REPO_PATH="$GPROXY_CACHE$COMP_ID"

        if [ -d "$REPO_PATH" ]; then
            log "Компонент загружен в: $REPO_PATH"

            # Ищем файл build
            if [ -x "$REPO_PATH/build" ]; then
                info "Запуск скрипта сборки..."
                cd "$REPO_PATH"
                if ./build; then
                    log "Сборка завершена успешно"

                    # Получаем описание компонента
                    DESC="Компонент $COMP_ID"
                    if [ -f "README.md" ]; then
                        DESC=$(head -1 "README.md" 2>/dev/null | cut -c -100)
                    elif [ -f "description.txt" ]; then
                        DESC=$(head -1 "description.txt" 2>/dev/null | cut -c -100)
                    fi
                    
                    # Экранируем кавычки для SQL
                    DESC=$(echo "$DESC" | sed "s/'/''/g")

                    # Добавляем в реестр
                    add_to_registry "$COMP_ID" "$VERSION" "git" "$DESC"

                    # Очищаем кэш gproxy
                    info "Очистка кэша gproxy..."
                    "$GPROXY_SCRIPT" clean

                    log "Компонент '$COMP_ID' успешно установлен"
                else
                    error "Ошибка сборки компонента"
                    log_to_registry "error" "Ошибка сборки компонента $COMP_ID"
                    cd - >/dev/null
                    return 1
                fi
                cd - >/dev/null
            else
                warn "Файл build не найден или не исполняемый"
                info "Попытка найти альтернативные скрипты..."

                # Проверяем другие возможные скрипты
                INSTALLED=false
                for script in install.sh setup.sh configure.sh; do
                    if [ -x "$REPO_PATH/$script" ]; then
                        info "Найден скрипт: $script"
                        cd "$REPO_PATH"
                        if ./"$script"; then
                            log "Установка завершена успешно"

                            # Получаем описание
                            DESC="Компонент $COMP_ID"
                            if [ -f "README.md" ]; then
                                DESC=$(head -1 "README.md" 2>/dev/null | cut -c -100)
                            fi
                            
                            # Экранируем кавычки для SQL
                            DESC=$(echo "$DESC" | sed "s/'/''/g")

                            add_to_registry "$COMP_ID" "$VERSION" "git" "$DESC"
                            "$GPROXY_SCRIPT" clean
                            log "Компонент '$COMP_ID' успешно установлен"
                            INSTALLED=true
                            cd - >/dev/null
                            break
                        fi
                        cd - >/dev/null
                    fi
                done

                if [ "$INSTALLED" = false ]; then
                    error "Не найден скрипт установки"
                    return 1
                fi
            fi
        else
            error "Не удалось определить путь к загруженному компоненту"
            log_to_registry "error" "Не удалось определить путь к компоненту $COMP_ID"
            return 1
        fi
    else
        error "Не удалось загрузить компонент через gproxy"
        echo "Вывод gproxy: $OUTPUT"
        log_to_registry "error" "Не удалось загрузить компонент $COMP_ID через gproxy"
        return 1
    fi
}

# Установка локального компонента (заглушка)
install_local() {
    COMP_ID="$1"
    VERSION="$2"

    warn "Локальная установка компонентов пока не реализована"
    echo "Идентификатор: $COMP_ID"
    echo "Версия: $VERSION"
    echo "Функционал в разработке..."
    return 1
}

# Команда установки
cmd_install() {
    if [ -z "$1" ]; then
        echo "Использование: $0 install <component-id> [version] [source]" >&2
        echo "  source: git (по умолчанию) или local" >&2
        echo "  version: номер версии или 'latest' (по умолчанию)" >&2
        exit 1
    fi

    check_init

    COMP_ID="$1"
    VERSION="${2:-latest}"
    SOURCE="${3:-git}"

    case "$SOURCE" in
        git)
            install_from_git "$COMP_ID" "$VERSION"
            ;;
        local)
            install_local "$COMP_ID" "$VERSION"
            ;;
        *)
            error "Неизвестный источник: $SOURCE"
            echo "Допустимые значения: git, local" >&2
            exit 1
            ;;
    esac
}

# Команда списка установленных компонентов
cmd_list() {
    check_init

    # Проверяем количество компонентов
    COUNT=$(sqlite3 "$REGISTRY_FILE" "SELECT COUNT(*) FROM components;" 2>/dev/null)
    
    if [ "$COUNT" -eq 0 ] 2>/dev/null; then
        echo "Нет установленных компонентов"
        return 0
    fi

    echo "Установленные компоненты:"
    echo "========================="
    echo ""

    # Получаем и выводим список компонентов
    sqlite3 "$REGISTRY_FILE" "SELECT name, version, source, description, installed_at FROM components ORDER BY name;" 2>/dev/null | while IFS='|' read -r id version source desc installed; do
        if [ -n "$id" ]; then
            echo "Компонент: $id"
            echo "  Версия: ${version:-не указана}"
            echo "  Описание: ${desc:-нет описания}"
            echo "  Источник: ${source:-не указан}"
            echo "  Установлен: ${installed:-неизвестно}"
            echo ""
        fi
    done
    
    echo "Всего компонентов: $COUNT"
}

# Команда информации о компоненте
cmd_info() {
    if [ -z "$1" ]; then
        echo "Использование: $0 info <component-id>" >&2
        exit 1
    fi

    check_init
    COMP_ID="$1"

    if is_installed "$COMP_ID"; then
        echo "Информация о компоненте: $COMP_ID"
        echo "================================"

        # Получаем информацию из реестра
        sqlite3 "$REGISTRY_FILE" "SELECT name, version, source, description, installed_at FROM components WHERE name = '$COMP_ID';" 2>/dev/null | while IFS='|' read -r id version source desc installed; do
            echo "Идентификатор: $id"
            echo "Версия: ${version:-не указана}"
            echo "Описание: ${desc:-нет описания}"
            echo "Источник: ${source:-не указан}"
            echo "Дата установки: ${installed:-неизвестно}"
        done
    else
        echo "Компонент '$COMP_ID' не установлен"
        
        # Предлагаем установить
        echo ""
        info "Для установки компонента используйте:"
        echo "  $0 install $COMP_ID"
    fi
}

# Команда обновления списка компонентов
cmd_update() {
    check_init
    log "Обновление списка компонентов через gproxy..."
    "$GPROXY_SCRIPT" update
    log_to_registry "info" "Список компонентов обновлен через gproxy"
}

# Команда показа версий компонента из репозитория
cmd_versions() {
    if [ -z "$1" ]; then
        echo "Использование: $0 versions <component-id>" >&2
        exit 1
    fi

    check_init
    COMP_ID="$1"

    # Проверяем, установлен ли компонент
    if is_installed "$COMP_ID"; then
        CURRENT_VERSION=$(sqlite3 "$REGISTRY_FILE" "SELECT version FROM components WHERE name = '$COMP_ID';" 2>/dev/null)
        info "Текущая установленная версия: $CURRENT_VERSION"
    fi

    echo ""
    warn "Получение доступных версий для $COMP_ID..."
    info "Для просмотра доступных версий используйте gproxy напрямую:"
    echo "  $GPROXY_SCRIPT list"
    echo ""
    info "Или установите последнюю версию:"
    echo "  $0 install $COMP_ID latest"
}

# Команда удаления компонента
cmd_remove() {
    if [ -z "$1" ]; then
        echo "Использование: $0 remove <component-id>" >&2
        exit 1
    fi

    check_init
    COMP_ID="$1"

    if is_installed "$COMP_ID"; then
        # Получаем информацию о компоненте
        info "Информация о компоненте:"
        cmd_info "$COMP_ID"
        echo ""
        
        warn "Вы уверены, что хотите удалить компонент '$COMP_ID'?"
        echo "Это действие удалит запись из реестра (файлы компонента останутся)"
        echo "Продолжить? (y/N): "
        read -r answer
        
        if [ "$answer" = "y" ] || [ "$answer" = "Y" ]; then
            remove_from_registry "$COMP_ID"
            log "Компонент '$COMP_ID' удален из реестра"
            warn "Файлы компонента не были удалены"
        else
            echo "Удаление отменено"
        fi
    else
        echo "Компонент '$COMP_ID' не установлен"
    fi
}

# Команда очистки логов
cmd_clean_logs() {
    check_init
    
    DAYS="${1:-30}"
    info "Очистка логов старше $DAYS дней..."
    
    sqlite3 "$REGISTRY_FILE" "DELETE FROM calista_log WHERE timestamp < datetime('now', '-$DAYS days');" 2>/dev/null
    
    DELETED=$(sqlite3 "$REGISTRY_FILE" "SELECT changes();" 2>/dev/null)
    log "Удалено $DELETED записей из лога"
    log_to_registry "info" "Очищены логи старше $DAYS дней"
}

# Команда просмотра логов
cmd_logs() {
    check_init
    
    LIMIT="${1:-20}"
    
    echo "Последние $LIMIT записей лога:"
    echo "==============================="
    echo ""
    
    sqlite3 "$REGISTRY_FILE" "SELECT timestamp, type, user, details FROM calista_log ORDER BY timestamp DESC LIMIT $LIMIT;" 2>/dev/null | while IFS='|' read -r timestamp type user details; do
        case "$type" in
            "error")
                echo -e "${RED}[$timestamp]${NC} [$type] $user: $details"
                ;;
            "info")
                echo -e "${GREEN}[$timestamp]${NC} [$type] $user: $details"
                ;;
            *)
                echo "[$timestamp] [$type] $user: $details"
                ;;
        esac
    done
}

# Команда помощи
cmd_help() {
    echo "Calista Component Manager"
    echo "========================="
    echo "Команды:"
    echo "  install <id> [version] [source] - Установить компонент"
    echo "                                   (source: git или local, по умолчанию git)"
    echo "  list                           - Показать установленные компоненты"
    echo "  info <id>                      - Информация об установленном компоненте"
    echo "  remove <id>                    - Удалить компонент из реестра"
    echo "  update                         - Обновить список компонентов из репозитория"
    echo "  versions <id>                  - Показать доступные версии компонента"
    echo "  logs [limit]                   - Показать последние записи лога (по умолчанию 20)"
    echo "  clean-logs [days]              - Очистить старые логи (по умолчанию старше 30 дней)"
    echo "  help                           - Показать эту справку"
    echo ""
    echo "Примеры:"
    echo "  $0 install cpm v1.0.0 git"
    echo "  $0 install calista-graphics-legacy latest"
    echo "  $0 list"
    echo "  $0 info cpm"
    echo "  $0 remove cpm"
    echo "  $0 logs 50"
    echo "  $0 clean-logs 60"
    echo ""
    echo "Путь к реестру: $REGISTRY_FILE"
    echo ""
    echo "Для работы с репозиторием компонентов сначала настройте gproxy:"
    echo "  $GPROXY_SCRIPT set-repo <ваш-git-репозиторий>"
    echo "  $0 update"
}

# Главная функция
main() {
    case "$1" in
        install)
            cmd_install "$2" "$3" "$4"
            ;;
        list)
            cmd_list
            ;;
        info)
            cmd_info "$2"
            ;;
        remove)
            cmd_remove "$2"
            ;;
        update)
            cmd_update
            ;;
        versions)
            cmd_versions "$2"
            ;;
        logs)
            cmd_logs "$2"
            ;;
        clean-logs)
            cmd_clean_logs "$2"
            ;;
        help|--help|-h)
            cmd_help
            ;;
        *)
            if [ -z "$1" ]; then
                cmd_help
            else
                error "Неизвестная команда: $1"
                echo "Используйте: $0 help" >&2
                exit 1
            fi
            ;;
    esac
}

# Проверка root прав для установки
if [ "$(id -u)" -ne 0 ] && [ "$1" = "install" ]; then
    warn "Для установки компонентов рекомендуется запускать от root"
    echo "Продолжить? (y/N): "
    read -r answer
    if [ "$answer" != "y" ] && [ "$answer" != "Y" ]; then
        exit 1
    fi
fi

# Запуск
main "$@"
