#!/bin/bash

# --- НАСТРОЙКИ ---
# Цвета для вывода
GREEN="\033[1;32m"
YELLOW="\033[1;33m"
RED="\033[1;31m"
NC="\033[0m" # No Color

# Путь к этому скрипту и его папке
SCRIPT_DIR=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)

# Имена файлов с пакетами
PACMAN_PKGS="pkglist.txt"
AUR_PKGS="aurlist.txt"

# --- НАСТРОЙКИ СИМЛИНКОВ (Имена папок в репозитории) ---
CONFIG_DIR_NAME="config"
HOME_DIR_NAME="home"
SYSTEM_DIR_NAME="system"


# --- ХЕЛПЕРЫ ---
msg() {
    echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}
err() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# --- ФУНКЦИИ ---

# 1. Установка YAY (AUR Helper)
install_yay() {
    if ! command -v yay &>/dev/null; then
        msg "YAY не найден. Установка YAY..."
        if ! pacman -Q git &>/dev/null || ! pacman -Q base-devel &>/dev/null; then
             sudo pacman -S --needed git base-devel
        fi
        
        rm -rf /tmp/yay
        git clone https://aur.archlinux.org/yay.git /tmp/yay
        (cd /tmp/yay && makepkg -si --noconfirm)
        rm -rf /tmp/yay
        msg "YAY установлен."
    else
        msg "YAY уже установлен."
    fi
}

# 2. Установка пакетов (Pacman и YAY)
install_packages() {
    msg "Сбор пакетов для установки..."

    # Основные пакеты
    local pacman_args=$(sed 's/#.*//' "$SCRIPT_DIR/$PACMAN_PKGS" | grep -vE '^\s*$' | xargs)
    local aur_args=$(sed 's/#.*//' "$SCRIPT_DIR/$AUR_PKGS" | grep -vE '^\s*$' | xargs)

    # --- Поиск и выбор дополнительных пакетов ---
    local optional_pacman_lists=($(find "$SCRIPT_DIR" -maxdepth 1 -name "pkglist-*.txt" ! -name "$PACMAN_PKGS"))
    local optional_aur_lists=($(find "$SCRIPT_DIR" -maxdepth 1 -name "aurlist-*.txt" ! -name "$AUR_PKGS"))

    if [ ${#optional_pacman_lists[@]} -gt 0 ] || [ ${#optional_aur_lists[@]} -gt 0 ]; then
        warn "Найдены дополнительные списки пакетов:"
        for list in "${optional_pacman_lists[@]}"; do echo "  -> $(basename "$list") (Pacman)"; done
        for list in "${optional_aur_lists[@]}"; do echo "  -> $(basename "$list") (AUR)"; done
        
        read -p "Хотите выбрать пакеты из этих списков для установки? [y/N]: " choice < /dev/tty
        if [[ "$choice" == "y" || "$choice" == "Y" ]]; then
            for list in "${optional_pacman_lists[@]}"; do
                read -p "  -> Установить из '$(basename "$list")'? [y/N]: " list_choice < /dev/tty
                if [[ "$list_choice" == "y" || "$list_choice" == "Y" ]]; then
                    pacman_args+=" $(sed 's/#.*//' "$list" | grep -vE '^\s*$' | xargs)"
                fi
            done
            for list in "${optional_aur_lists[@]}"; do
                read -p "  -> Установить из '$(basename "$list")'? [y/N]: " list_choice < /dev/tty
                if [[ "$list_choice" == "y" || "$list_choice" == "Y" ]]; then
                    aur_args+=" $(sed 's/#.*//' "$list" | grep -vE '^\s*$' | xargs)"
                fi
            done
        fi
    fi

    # --- Установка пакетов Pacman ---
    if [[ ! -z "$pacman_args" ]]; then
        msg "Установка пакетов из Pacman..."
        sudo pacman -S --needed $pacman_args
    else
        msg "Список Pacman для установки пуст."
    fi
    
    # --- Установка пакетов AUR ---
    if [[ ! -z "$aur_args" ]]; then
        msg "Проверка и установка YAY..."
        install_yay
        msg "Установка пакетов из AUR..."
        yay -S --needed $aur_args
    else
        msg "Список AUR для установки пуст."
    fi
    
    msg "Установка пакетов завершена."
}

# 3. (НОВАЯ) Рекурсивная функция линковки
link_item() {
    local src="$1"
    local dest="$2"
    
    # Проверка источника
    if [ ! -e "$src" ]; then
        return
    fi

    # 1. Если цель существует и это директория (и не симлинк)
    #    И источник тоже директория
    #    -> РЕКУРСИЯ (MERGE)
    if [ -d "$dest" ] && [ ! -L "$dest" ] && [ -d "$src" ]; then
        # msg "  [DIR] Вход в $dest"
        for child in "$src"/*; do
            [ -e "$child" ] || continue
            local child_name=$(basename "$child")
            link_item "$child" "$dest/$child_name"
        done
        return
    fi

    # 2. Если цель существует (файл или симлинк)
    if [ -e "$dest" ] || [ -L "$dest" ]; then
        # Если это уже правильный симлинк - пропускаем
        if [ -L "$dest" ]; then
            local current_target=$(readlink -f "$dest")
            local source_absolute=$(readlink -f "$src")
            if [ "$current_target" == "$source_absolute" ]; then
                # msg "    [OK] $dest уже указывает на правильный файл"
                return
            fi
        fi
        
        # Если это файл или неправильный симлинк - бэкап
        warn "    [BACKUP] $dest существует. Бэкап -> $dest.bak"
        mv "$dest" "$dest.bak"
    fi

    # 3. Создаем симлинк
    # Создаем родительскую папку, если её нет (например для ~/.config/foo/bar)
    mkdir -p "$(dirname "$dest")"
    ln -sfn "$src" "$dest"
    msg "    [LINK] $dest -> $src"
}

# 4. Создание символических ссылок (Обновлено)
link_dotfiles() {
    msg "Создание символических ссылок..."

    # ВАЖНО: Предварительно создаем критические системные папки.
    # Это заставит функцию link_item использовать режим MERGE (рекурсию) для них,
    # вместо создания симлинка на всю папку.
    msg "  -> Подготовка структуры папок..."
    mkdir -p "$HOME/.config"
    mkdir -p "$HOME/.local/share"
    mkdir -p "$HOME/.local/state"
    mkdir -p "$HOME/.local/bin"
    # mkdir -p "$HOME/bin" # Если используется

    # --- 1. Линкуем файлы в $HOME (из папки 'home') ---
    msg "  -> Обработка '$HOME_DIR_NAME'..."
    local source_dir="$SCRIPT_DIR/$HOME_DIR_NAME"
    
    if [ -d "$source_dir" ]; then
        for item_path in "$source_dir"/*; do
            [ -e "$item_path" ] || continue # Пропуск, если папка пуста
            local item_name=$(basename "$item_path")
            # Вызываем рекурсивную функцию
            link_item "$item_path" "$HOME/$item_name"
        done
    fi

    # --- 2. Линкуем файлы в $HOME/.config (из папки 'config') ---
    msg "  -> Обработка '$CONFIG_DIR_NAME'..."
    source_dir="$SCRIPT_DIR/$CONFIG_DIR_NAME"
    
    if [ -d "$source_dir" ]; then
        for item_path in "$source_dir"/*; do
            [ -e "$item_path" ] || continue
            local item_name=$(basename "$item_path")
            link_item "$item_path" "$HOME/.config/$item_name"
        done
    fi
    
    msg "Симлинки обработаны."
}

# 5. Проверка текущей конфигурации
check_config() {
    msg "Проверка установленных пакетов Pacman..."
    local missing_pacman=0
    # Ищем pkglist.txt и pkglist-*.txt
    for f in $(find "$SCRIPT_DIR" -maxdepth 1 -name "pkglist*.txt"); do
        while IFS= read -r line || [[ -n "$line" ]]; do
            local pkg=$(echo "$line" | sed 's/#.*//' | xargs)
            if [[ -z "$pkg" ]]; then continue; fi
            if [[ "$pkg" == "xorg" ]]; then continue; fi
            if ! pacman -Q "$pkg" &>/dev/null; then
                warn "  -> Не найден (Pacman, из $(basename "$f")): $pkg"
                missing_pacman=1
            fi
        done < "$f"
    done
    if [ $missing_pacman -eq 0 ]; then msg "Все пакеты Pacman установлены."; fi

    msg "Проверка установленных пакетов AUR..."
    local missing_aur=0
    for f in $(find "$SCRIPT_DIR" -maxdepth 1 -name "aurlist*.txt"); do
        while IFS= read -r line || [[ -n "$line" ]]; do
            local pkg=$(echo "$line" | sed 's/#.*//' | xargs)
            if [[ -z "$pkg" ]]; then continue; fi
            if ! pacman -Q "$pkg" &>/dev/null; then
                warn "  -> Не найден (AUR, из $(basename "$f")): $pkg"
                missing_aur=1
            fi
        done < "$f"
    done
    if [ $missing_aur -eq 0 ]; then msg "Все пакеты AUR установлены."; fi
    
    msg "Проверка симлинков (выборочная)..."
    # Просто проверим наличие ссылок для корневых элементов
    local source_dir="$SCRIPT_DIR/$HOME_DIR_NAME"
    if [ -d "$source_dir" ]; then
        for item_path in "$source_dir"/*; do
            [ -e "$item_path" ] || continue
            local item_name=$(basename "$item_path")
            # Если это папка .local, проверяем глубже
            if [ "$item_name" == ".local" ]; then
                 if [ ! -d "$HOME/.local" ]; then warn "  -> Папка $HOME/.local отсутствует!"; fi
            elif [ ! -e "$HOME/$item_name" ]; then
                warn "  -> Элемент не найден: $HOME/$item_name"
            fi
        done
    fi
    msg "Проверка завершена."
}

# 6. Проверка драйверов
check_drivers() {
    msg "Проверка оборудования и рекомендации по драйверам..."
    
    if ! command -v lspci &>/dev/null; then
        warn "Команда lspci не найдена. Установите пакет 'pciutils'."
        return
    fi
    
    local vga=$(lspci -k | grep -A 2 -E "(VGA|3D)")
    
    if echo "$vga" | grep -iq "NVIDIA"; then
        warn "Найдена карта NVIDIA. Рекомендуемые пакеты:"
        warn "  -> nvidia (или nvidia-lts, nvidia-dkms)"
        warn "  -> lib32-nvidia-utils"
    elif echo "$vga" | grep -iq "Intel"; then
        msg "Найдена карта Intel. Рекомендуемые пакеты:"
        msg "  -> mesa, lib32-mesa, vulkan-intel"
    elif echo "$vga" | grep -iq "AMD"; then
        msg "Найдена карта AMD/ATI. Рекомендуемые пакеты:"
        msg "  -> mesa, lib32-mesa, vulkan-radeon"
    fi
    
    if lspci -k | grep -iq "broadcom"; then
        warn "Найден чип Broadcom. Возможно нужен: broadcom-wl-dkms"
    fi
}

# 7. Применение системных конфигов
apply_system_configs() {
    msg "--- РЕЖИМ: ПРИМЕНЕНИЕ СИСТЕМНЫХ КОНФИГОВ ---"
    local system_source_dir="$SCRIPT_DIR/$SYSTEM_DIR_NAME"
    
    if [ ! -d "$system_source_dir" ]; then
        err "Папка '$system_source_dir' не найдена."
        return 1
    fi
    
    find "$system_source_dir" -type f | while read -r source_file; do
        local rel_path=${source_file#$system_source_dir/}
        local target_file="/$rel_path"
        
        msg "Конфиг: $rel_path"
        
        if [ ! -f "$target_file" ]; then
            warn "  Файл '$target_file' не существует в системе."
            read -p "  Скопировать? [y/N]: " choice < /dev/tty
            if [[ "$choice" =~ ^[yY]$ ]]; then
                sudo mkdir -p "$(dirname "$target_file")"
                sudo cp "$source_file" "$target_file"
                msg "  -> СКОПИРОВАНО."
            fi
            continue
        fi
        
        if command -v diff &>/dev/null; then
            if ! diff -q "$target_file" "$source_file" &>/dev/null; then
                msg "  Найдены различия:"
                diff -u "$target_file" "$source_file" | head -n 20
                
                warn "  Заменить системный файл?"
                read -p "  [y/N/b] (Да / Нет / Бэкап): " choice < /dev/tty
                case "$choice" in
                    y|Y)
                        sudo cp "$source_file" "$target_file"
                        msg "  -> ЗАМЕНЕНО."
                        ;;
                    b|B)
                        sudo mv "$target_file" "$target_file.bak"
                        sudo cp "$source_file" "$target_file"
                        msg "  -> БЭКАП И ЗАМЕНА."
                        ;;
                esac
            else
                msg "  -> Идентичны."
            fi
        else
            warn "  diff не установлен, сравнение невозможно."
        fi
    done
}

# 8. Создание папок пользователя
create_user_dirs() {
    msg "Проверка стандартных папок пользователя..."
    # Если xdg-user-dirs установлен, лучше использовать его
    if command -v xdg-user-dirs-update &>/dev/null; then
        xdg-user-dirs-update
        msg "  -> Выполнен xdg-user-dirs-update"
    else
        mkdir -p "$HOME/Documents" "$HOME/Downloads" "$HOME/Pictures"
        msg "  -> Папки созданы (fallback)."
    fi
}


# --- ГЛАВНЫЙ БЛОК ---

show_help() {
    echo "Dotfiles Manager"
    echo "Команды:"
    echo "  install   - Установить пакеты, создать ссылки."
    echo "  check     - Проверка статуса."
    echo "  update    - git pull + install."
    echo "  drivers   - Рекомендации по драйверам."
    echo "  system    - Системные конфиги (/etc)."
}

if [ "$EUID" -eq 0 ]; then
  err "Запускайте от пользователя, не от root!"
  exit 1
fi

if [ $# -eq 0 ]; then show_help; exit 0; fi

case "$1" in
    install)
        msg "--- УСТАНОВКА ---"
        install_packages
        link_dotfiles
        create_user_dirs
        msg "Готово."
        ;;
    check)
        check_config
        ;;
    update)
        msg "--- ОБНОВЛЕНИЕ ---"
        if git pull; then
            install_packages
            link_dotfiles
            create_user_dirs
            msg "Обновлено."
        else
            err "Ошибка git pull."
        fi
        ;;
    drivers)
        check_drivers
        ;;
    system)
        apply_system_configs
        ;;
    help|*)
        show_help
        ;;
esac