#!/bin/bash

# ============================================
# WP-CLI Sync Script for WordPress with Docker
# ============================================

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

# ============================================
# НАСТРОЙКИ (ИЗМЕНИТЕ ПОД СЕБЯ)
# ============================================

# Локальные настройки (хост-машина)
LOCAL_PATH="$(pwd)"  # Текущая папка, где лежит скрипт (автоопределение)

# Docker настройки
# Получите имя контейнера командой: docker ps --format "table {{.Names}}\t{{.Image}}" | grep wordpress
WP_CONTAINER="wordpress"  # ИЗМЕНИТЕ: имя вашего WordPress контейнера
WP_CONTAINER_PATH="/var/www/html"  # Путь к WordPress внутри контейнера (обычно /var/www/html)

# Локальный URL (как вы открываете сайт в браузере)
LOCAL_URL="http://localhost:8080"  # ИЗМЕНИТЕ: ваш URL и порт

# Боевые настройки (продакшен)
PROD_SSH="user@your-server.com"  # ИЗМЕНИТЕ: SSH пользователь и сервер
PROD_PATH="/var/www/production"  # ИЗМЕНИТЕ: путь к WordPress на сервере
PROD_URL="https://your-site.com" # ИЗМЕНИТЕ: боевой URL

# Настройки синхронизации
BACKUP_DIR="./sync_backups"       # Папка для бэкапов
EXCLUDE_TABLES="wp_options"       # Таблицы для исключения (через запятую)
                                  # Например: "wp_options,wp_users"

# Команда WP-CLI для Docker
WP_CMD="docker exec -i $WP_CONTAINER wp --path=$WP_CONTAINER_PATH"

# ============================================
# ФУНКЦИИ
# ============================================

# Функция для проверки Docker контейнера
check_docker() {
    info "Проверка Docker контейнера: $WP_CONTAINER"
    
    if ! docker ps --format "table {{.Names}}" | grep -q "^$WP_CONTAINER$"; then
        error "Контейнер $WP_CONTAINER не запущен. Запустите Docker и контейнер WordPress."
    fi
    
    # Проверяем WP-CLI в контейнере
    if ! docker exec $WP_CONTAINER wp --info &> /dev/null; then
        error "WP-CLI не найден в контейнере. Установите WP-CLI в Docker образ."
    fi
    
    success "Docker контейнер готов"
}

# Функция для вывода ошибок
error() {
    echo -e "${RED}[ОШИБКА]${NC} $1"
    exit 1
}

# Функция для вывода успеха
success() {
    echo -e "${GREEN}[УСПЕХ]${NC} $1"
}

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

# Функция для вывода предупреждения
warning() {
    echo -e "${YELLOW}[ПРЕДУПРЕЖДЕНИЕ]${NC} $1"
}

# Функция для запроса подтверждения
confirm() {
    read -p "$(echo -e ${YELLOW}[?]${NC} $1 (y/n): " )" -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        info "Отменено пользователем"
        return 1
    fi
    return 0
}

# Функция для создания бэкапа БД
backup_db() {
    local backup_name="$1"
    local backup_file="${BACKUP_DIR}/${backup_name}_$(date +%Y%m%d_%H%M%S).sql"
    
    mkdir -p "$BACKUP_DIR"
    info "Создание бэкапа БД: $backup_file"
    
    # Выполняем WP-CLI внутри контейнера, сохраняем на хост
    if $WP_CMD db export - 2>/dev/null > "$backup_file"; then
        success "Бэкап создан: $backup_file"
        echo "$backup_file"
    else
        error "Не удалось создать бэкап БД"
    fi
}

# Функция для импорта БД из файла
import_db() {
    local backup_file="$1"
    
    if [ ! -f "$backup_file" ]; then
        error "Файл бэкапа не найден: $backup_file"
    fi
    
    info "Импорт БД из $backup_file"
    
    # Читаем файл с хоста и передаём в контейнер
    if cat "$backup_file" | $WP_CMD db import -; then
        success "БД импортирована успешно"
    else
        error "Не удалось импортировать БД"
    fi
}

# Функция для замены URL
replace_url() {
    local from_url="$1"
    local to_url="$2"
    
    info "Замена URL: $from_url -> $to_url"
    
    # Сначала проверка (dry run)
    info "Проверка замены (dry run)..."
    if ! $WP_CMD search-replace "$from_url" "$to_url" --dry-run; then
        error "Ошибка при проверке замены URL"
    fi
    
    if confirm "Продолжить замену URL?"; then
        if $WP_CMD search-replace "$from_url" "$to_url"; then
            success "URL заменены успешно"
        else
            error "Ошибка при замене URL"
        fi
    fi
}

# Функция для очистки кэша
flush_cache() {
    info "Очистка кэша WordPress..."
    $WP_CMD cache flush
    success "Кэш очищен"
}

# ============================================
# ОСНОВНЫЕ КОМАНДЫ
# ============================================

# Функция: Pull (с боевого на локальный)
do_pull() {
    echo ""
    echo "========================================="
    echo "PULL: Боевой -> Локальный"
    echo "========================================="
    echo ""
    
    # 1. Проверка соединения с боевым сервером
    info "Проверка соединения с боевым сервером..."
    ssh $PROD_SSH "wp core is-installed --path=$PROD_PATH" || error "Не удалось подключиться к боевому серверу"
    success "Соединение с сервером установлено"
    
    # 2. Создание бэкапа боевой БД на сервере
    local timestamp=$(date +%Y%m%d_%H%M%S)
    local prod_backup="prod_backup_${timestamp}.sql"
    
    info "Создание бэкапа боевой БД на сервере..."
    ssh $PROD_SSH "cd $PROD_PATH && wp db export $prod_backup" || error "Не удалось создать бэкап на сервере"
    success "Бэкап создан на сервере: $prod_backup"
    
    # 3. Скачивание бэкапа
    info "Скачивание бэкапа с сервера..."
    scp $PROD_SSH:$PROD_PATH/$prod_backup "$BACKUP_DIR/" || error "Не удалось скачать бэкап"
    
    # 4. Удаление временного файла на сервере
    ssh $PROD_SSH "rm $PROD_PATH/$prod_backup"
    success "Бэкап скачан и временный файл удалён"
    
    # 5. Создание бэкапа локальной БД (на всякий случай)
    backup_db "local_before_pull_${timestamp}"
    
    # 6. Импорт боевой БД в локальную среду
    import_db "$BACKUP_DIR/$prod_backup"
    
    # 7. Замена URL на локальные
    replace_url "$PROD_URL" "$LOCAL_URL"
    
    # 8. Очистка кэша
    flush_cache
    
    success "Pull завершён успешно!"
    info "Локальный сайт теперь полностью соответствует боевому"
}

# Функция: Push (с локального на боевой)
do_push() {
    echo ""
    echo "========================================="
    echo "PUSH: Локальный -> Боевой"
    echo "========================================="
    echo ""
    
    # ПРЕДУПРЕЖДЕНИЕ!
    warning "Эта операция ЗАМЕНИТ боевую базу данных на локальную!"
    echo "Вы потеряете все новые данные на боевом сайте:"
    echo "  • Заказы (если есть интернет-магазин)"
    echo "  • Комментарии пользователей"
    echo "  • Новых зарегистрированных пользователей"
    echo "  • Изменения в настройках"
    echo ""
    
    if ! confirm "Вы уверены, что хотите продолжить?"; then
        exit 0
    fi
    
    local timestamp=$(date +%Y%m%d_%H%M%S)
    
    # 1. Создание бэкапа боевой БД
    info "Создание бэкапа боевой БД перед обновлением..."
    ssh $PROD_SSH "cd $PROD_PATH && wp db export backup_before_push_${timestamp}.sql" || error "Не удалось создать бэкап боевой БД"
    success "Бэкап боевой БД сохранён на сервере"
    
    # 2. Создание бэкапа локальной БД
    backup_db "local_before_push_${timestamp}"
    
    # 3. Экспорт локальной БД с заменой URL
    info "Подготовка локальной БД для боевого сервера..."
    local temp_backup="${BACKUP_DIR}/temp_for_prod_${timestamp}.sql"
    
    # Экспортируем БД из контейнера
    $WP_CMD db export - > "$temp_backup" || error "Не удалось экспортировать локальную БД"
    
    # 4. Замена URL в дампе (локальный -> боевой)
    info "Замена URL в дампе: $LOCAL_URL -> $PROD_URL"
    sed -i "s|$LOCAL_URL|$PROD_URL|g" "$temp_backup"
    
    # 5. Исключение некоторых таблиц (если нужно)
    if [ -n "$EXCLUDE_TABLES" ] && [ "$EXCLUDE_TABLES" != "none" ]; then
        info "Исключение таблиц: $EXCLUDE_TABLES"
        local filtered_backup="${BACKUP_DIR}/filtered_${timestamp}.sql"
        
        # Создаём временный файл без исключённых таблиц
        local exclude_pattern=$(echo "$EXCLUDE_TABLES" | sed 's/,/\\|/g')
        grep -v "CREATE TABLE \`\(${exclude_pattern}\)\`" "$temp_backup" > "$filtered_backup"
        grep -v "INSERT INTO \`\(${exclude_pattern}\)\`" "$filtered_backup" > "${filtered_backup}.tmp"
        mv "${filtered_backup}.tmp" "$filtered_backup"
        mv "$filtered_backup" "$temp_backup"
        success "Таблицы исключены"
    fi
    
    # 6. Отправка дампа на сервер
    info "Отправка дампа на боевой сервер..."
    scp "$temp_backup" $PROD_SSH:$PROD_PATH/ || error "Не удалось отправить дамп на сервер"
    
    # 7. Импорт на боевом сервере
    info "Импорт на боевом сервере..."
    ssh $PROD_SSH "cd $PROD_PATH && wp db import $(basename $temp_backup) && rm $(basename $temp_backup)" || error "Не удалось импортировать БД на сервере"
    
    # 8. Очистка кэша на сервере
    info "Очистка кэша на боевом сервере..."
    ssh $PROD_SSH "cd $PROD_PATH && wp cache flush"
    
    # 9. Удаление временных файлов
    rm "$temp_backup"
    
    success "Push завершён успешно!"
    info "Боевой сайт обновлён. Бэкап старой версии сохранён на сервере"
}

# Функция: Синхронизация файлов (Uploads через rsync)
do_sync_files() {
    echo ""
    echo "========================================="
    echo "СИНХРОНИЗАЦИЯ ФАЙЛОВ (Uploads)"
    echo "========================================="
    echo ""
    
    # Проверка наличия rsync
    if ! command -v rsync &> /dev/null; then
        warning "rsync не установлен. Установите rsync: brew install rsync (macOS) или apt-get install rsync (Linux)"
        return 1
    fi
    
    # Пути к папкам uploads
    LOCAL_UPLOADS="${LOCAL_PATH}/wp-content/uploads"
    REMOTE_UPLOADS="$PROD_SSH:$PROD_PATH/wp-content/uploads"
    
    # Проверка существования локальной папки
    if [ ! -d "$LOCAL_UPLOADS" ]; then
        warning "Локальная папка uploads не найдена: $LOCAL_UPLOADS"
        info "Создаю папку..."
        mkdir -p "$LOCAL_UPLOADS"
    fi
    
    echo "Выберите направление синхронизации:"
    echo "  1) Локальный -> Боевой (отправить новые файлы на сервер)"
    echo "  2) Боевой -> Локальный (скачать новые файлы с сервера)"
    echo ""
    read -p "Ваш выбор (1/2): " direction
    
    case $direction in
        1)
            info "Синхронизация локальных файлов на боевой сервер..."
            rsync -avz --progress \
                --exclude="*.tmp" \
                --exclude=".DS_Store" \
                "$LOCAL_UPLOADS/" "$REMOTE_UPLOADS/"
            success "Файлы отправлены на сервер"
            ;;
        2)
            info "Скачивание файлов с боевого сервера..."
            rsync -avz --progress \
                --exclude="*.tmp" \
                --exclude=".DS_Store" \
                "$REMOTE_UPLOADS/" "$LOCAL_UPLOADS/"
            success "Файлы скачаны с сервера"
            ;;
        *)
            error "Неверный выбор"
            ;;
    esac
}

# Функция: Показать статус
do_status() {
    echo ""
    echo "========================================="
    echo "СТАТУС СИСТЕМЫ"
    echo "========================================="
    echo ""
    
    # Docker контейнер
    info "Docker контейнер:"
    if docker ps --format "table {{.Names}}\t{{.Status}}" | grep -q "^$WP_CONTAINER"; then
        docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" | grep "$WP_CONTAINER"
    else
        warning "Контейнер $WP_CONTAINER не запущен"
    fi
    echo ""
    
    # Локальный WordPress
    info "Локальный WordPress:"
    if $WP_CMD core version &> /dev/null; then
        echo "  Версия: $($WP_CMD core version)"
        echo "  URL: $LOCAL_URL"
        echo "  Путь в контейнере: $WP_CONTAINER_PATH"
    else
        warning "WordPress не доступен в контейнере"
    fi
    echo ""
    
    # Боевой сервер
    info "Боевой сервер:"
    if ssh $PROD_SSH "wp core version --path=$PROD_PATH" &> /dev/null; then
        echo "  Версия: $(ssh $PROD_SSH "wp core version --path=$PROD_PATH")"
        echo "  URL: $PROD_URL"
        echo "  Путь: $PROD_PATH"
    else
        warning "Не удалось подключиться к боевому серверу"
    fi
}

# ============================================
# ГЛАВНОЕ МЕНЮ
# ============================================

# Очистка экрана
clear

# Приветствие
echo ""
echo "========================================="
echo "   WP-CLI Sync Script for WordPress"
echo "   Docker + Production Sync"
echo "========================================="
echo ""

# Проверка Docker
check_docker

# Создание папки для бэкапов
mkdir -p "$BACKUP_DIR"

# Основной цикл меню
while true; do
    echo ""
    echo "========================================="
    echo "ГЛАВНОЕ МЕНЮ"
    echo "========================================="
    echo ""
    echo "Текущие настройки:"
    echo "  📦 Docker контейнер: $WP_CONTAINER"
    echo "  🏠 Локальный URL: $LOCAL_URL"
    echo "  ☁️  Боевой URL: $PROD_URL"
    echo "  📁 Бэкапы: $BACKUP_DIR"
    echo ""
    echo "Доступные действия:"
    echo "  📥 1) Pull  (Боевой -> Локальный) - забрать данные с сервера"
    echo "  📤 2) Push  (Локальный -> Боевой) - отправить данные на сервер"
    echo "  📁 3) Sync Files - синхронизировать только файлы (uploads)"
    echo "  ℹ️  4) Status - показать статус системы"
    echo "  🗑️  5) Backup - создать бэкап локальной БД"
    echo "  🚪 6) Exit - выход"
    echo ""
    read -p "Выберите действие (1-6): " action
    
    case $action in
        1)
            do_pull
            ;;
        2)
            do_push
            ;;
        3)
            do_sync_files
            ;;
        4)
            do_status
            ;;
        5)
            backup_db "manual_backup"
            ;;
        6)
            info "Выход из программы"
            exit 0
            ;;
        *)
            error "Неверный выбор. Пожалуйста, выберите 1-6"
            ;;
    esac
    
    echo ""
    read -p "Нажмите Enter, чтобы продолжить..."
    clear
done