#!/bin/bash
#==============================================================================
# MontaLoja - Rollback Script
# Autor: DevOps Automation
# Versão: 1.0.0
# Descrição: Reverte para a versão anterior em caso de problemas
#==============================================================================

set -e

#------------------------------------------------------------------------------
# CONFIGURAÇÕES
#------------------------------------------------------------------------------
APP_USER="socialar"
BASE_DIR="/home/${APP_USER}/montaloja.com"
RELEASES_DIR="${BASE_DIR}/releases"
SHARED_DIR="${BASE_DIR}/shared"
BACKUPS_DIR="${BASE_DIR}/backups"
CURRENT_LINK="${BASE_DIR}/current"

# Cores
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'

#------------------------------------------------------------------------------
# FUNÇÕES
#------------------------------------------------------------------------------

log_info() {
    echo -e "${BLUE}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_success() {
    echo -e "${GREEN}[SUCCESS]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

log_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

#------------------------------------------------------------------------------
# LISTAR RELEASES DISPONÍVEIS
#------------------------------------------------------------------------------

list_releases() {
    echo ""
    echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║  📦 RELEASES DISPONÍVEIS PARA ROLLBACK                       ║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════════════════╣${NC}"
    
    local CURRENT_RELEASE=""
    if [ -L "$CURRENT_LINK" ]; then
        CURRENT_RELEASE=$(readlink -f "$CURRENT_LINK")
    fi
    
    local i=1
    cd "$RELEASES_DIR"
    for release in $(ls -dt release_* 2>/dev/null); do
        local release_path="${RELEASES_DIR}/${release}"
        local marker=""
        
        if [ "$release_path" == "$CURRENT_RELEASE" ]; then
            marker="${GREEN}[ATIVA]${NC}"
        fi
        
        echo -e "${CYAN}║  ${i}. ${release} ${marker}${NC}"
        ((i++))
    done
    
    echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
}

#------------------------------------------------------------------------------
# ROLLBACK PARA VERSÃO ANTERIOR
#------------------------------------------------------------------------------

rollback_previous() {
    echo ""
    echo -e "${YELLOW}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${YELLOW}║  🔄 INICIANDO ROLLBACK                                        ║${NC}"
    echo -e "${YELLOW}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    
    # Verificar se existe arquivo com versão anterior
    if [ -f "${SHARED_DIR}/.previous_release" ]; then
        PREVIOUS_RELEASE=$(cat "${SHARED_DIR}/.previous_release")
        
        if [ -d "$PREVIOUS_RELEASE" ]; then
            log_info "Versão anterior encontrada: ${PREVIOUS_RELEASE}"
        else
            log_error "Pasta da versão anterior não existe mais: ${PREVIOUS_RELEASE}"
            return 1
        fi
    else
        # Se não tiver arquivo, pegar a segunda release mais recente
        log_warning "Arquivo .previous_release não encontrado. Buscando segunda release mais recente..."
        
        cd "$RELEASES_DIR"
        RELEASES=($(ls -dt release_* 2>/dev/null))
        
        if [ ${#RELEASES[@]} -lt 2 ]; then
            log_error "Não há releases suficientes para rollback!"
            return 1
        fi
        
        PREVIOUS_RELEASE="${RELEASES_DIR}/${RELEASES[1]}"
        log_info "Usando: ${PREVIOUS_RELEASE}"
    fi
    
    # Mostrar versão atual
    if [ -L "$CURRENT_LINK" ]; then
        CURRENT_RELEASE=$(readlink -f "$CURRENT_LINK")
        log_info "Versão atual: ${CURRENT_RELEASE}"
    fi
    
    # Confirmar
    echo ""
    read -p "$(echo -e ${YELLOW}'Confirma rollback para a versão anterior?'${NC} ' [s/N]: ')" response
    
    case "$response" in
        [sS][iI][mM]|[sS]|[yY][eE][sS]|[yY])
            ;;
        *)
            log_info "Rollback cancelado."
            return 0
            ;;
    esac
    
    # Executar rollback (atomic swap)
    log_info "Executando atomic symlink swap..."
    
    ln -sfn "$PREVIOUS_RELEASE" "${CURRENT_LINK}.new"
    mv -Tf "${CURRENT_LINK}.new" "$CURRENT_LINK"
    
    # Salvar a versão que era atual como "próxima anterior"
    echo "$CURRENT_RELEASE" > "${SHARED_DIR}/.previous_release"
    
    log_success "Rollback concluído!"
    log_success "Versão ativa agora: ${PREVIOUS_RELEASE}"
    
    # Limpar cache
    log_info "Limpando cache PHP..."
    if command -v systemctl &> /dev/null; then
        sudo systemctl reload php-fpm 2>/dev/null ; true
    fi
    
    echo ""
    echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${GREEN}║  ✅ ROLLBACK CONCLUÍDO COM SUCESSO                            ║${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}║  Verifique se o site está funcionando corretamente.          ║${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}║  Para voltar para a versão mais nova, execute novamente      ║${NC}"
    echo -e "${GREEN}║  este script ou faça um novo deploy.                         ║${NC}"
    echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
}

#------------------------------------------------------------------------------
# ROLLBACK PARA VERSÃO ESPECÍFICA
#------------------------------------------------------------------------------

rollback_specific() {
    list_releases
    
    echo ""
    read -p "Digite o número da release para ativar (ou 'q' para sair): " choice
    
    if [ "$choice" == "q" ] || [ "$choice" == "Q" ]; then
        log_info "Operação cancelada."
        return 0
    fi
    
    # Validar entrada
    if ! [[ "$choice" =~ ^[0-9]+$ ]]; then
        log_error "Entrada inválida!"
        return 1
    fi
    
    # Obter release selecionada
    cd "$RELEASES_DIR"
    RELEASES=($(ls -dt release_* 2>/dev/null))
    
    local index=$((choice - 1))
    
    if [ $index -lt 0 ] || [ $index -ge ${#RELEASES[@]} ]; then
        log_error "Número de release inválido!"
        return 1
    fi
    
    local SELECTED_RELEASE="${RELEASES_DIR}/${RELEASES[$index]}"
    
    log_info "Release selecionada: ${SELECTED_RELEASE}"
    
    # Confirmar
    echo ""
    read -p "$(echo -e ${YELLOW}'Confirma ativação desta release?'${NC} ' [s/N]: ')" response
    
    case "$response" in
        [sS][iI][mM]|[sS]|[yY][eE][sS]|[yY])
            ;;
        *)
            log_info "Operação cancelada."
            return 0
            ;;
    esac
    
    # Salvar versão atual como anterior
    if [ -L "$CURRENT_LINK" ]; then
        CURRENT_RELEASE=$(readlink -f "$CURRENT_LINK")
        echo "$CURRENT_RELEASE" > "${SHARED_DIR}/.previous_release"
    fi
    
    # Executar swap
    log_info "Ativando release..."
    
    ln -sfn "$SELECTED_RELEASE" "${CURRENT_LINK}.new"
    mv -Tf "${CURRENT_LINK}.new" "$CURRENT_LINK"
    
    log_success "Release ativada: ${SELECTED_RELEASE}"
    
    # Limpar cache
    if command -v systemctl &> /dev/null; then
        sudo systemctl reload php-fpm 2>/dev/null ; true
    fi
}

#------------------------------------------------------------------------------
# RESTAURAR BACKUP DO BANCO
#------------------------------------------------------------------------------

restore_database() {
    echo ""
    echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║  💾 BACKUPS DE BANCO DISPONÍVEIS                             ║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════════════════╣${NC}"
    
    local i=1
    cd "$BACKUPS_DIR"
    BACKUPS=($(ls -t db_backup_*.sql.gz 2>/dev/null))
    
    for backup in "${BACKUPS[@]}"; do
        local size=$(du -h "$backup" | cut -f1)
        echo -e "${CYAN}║  ${i}. ${backup} (${size})${NC}"
        ((i++))
    done
    
    echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    
    if [ ${#BACKUPS[@]} -eq 0 ]; then
        log_error "Nenhum backup encontrado!"
        return 1
    fi
    
    read -p "Digite o número do backup para restaurar (ou 'q' para sair): " choice
    
    if [ "$choice" == "q" ] || [ "$choice" == "Q" ]; then
        log_info "Operação cancelada."
        return 0
    fi
    
    local index=$((choice - 1))
    
    if [ $index -lt 0 ] || [ $index -ge ${#BACKUPS[@]} ]; then
        log_error "Número de backup inválido!"
        return 1
    fi
    
    local SELECTED_BACKUP="${BACKUPS_DIR}/${BACKUPS[$index]}"
    
    echo ""
    echo -e "${RED}⚠️  ATENÇÃO: Esta operação irá SOBRESCREVER o banco de dados atual!${NC}"
    echo -e "${RED}   Todos os dados atuais serão perdidos e substituídos pelo backup.${NC}"
    echo ""
    
    read -p "$(echo -e ${RED}'Tem certeza que deseja restaurar este backup?'${NC} ' [sim/NÃO]: ')" response
    
    if [ "$response" != "sim" ]; then
        log_info "Restauração cancelada."
        return 0
    fi
    
    # Carregar credenciais
    source "${SHARED_DIR}/config.php" 2>/dev/null ; true
    
    # Se não conseguiu carregar, usar padrões
    DB_HOST="${DB_HOST:-localhost}"
    DB_NAME="${DB_NAME:-socialar_socialar_commerce}"
    DB_USER="${DB_USER:-socialar}"
    DB_PASS="${DB_PASS:-y557t55n7rt6}"
    
    log_info "Restaurando backup: ${SELECTED_BACKUP}"
    
    # Descompactar e restaurar
    gunzip -c "$SELECTED_BACKUP" | mysql -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME"
    
    if [ $? -eq 0 ]; then
        log_success "Banco de dados restaurado com sucesso!"
    else
        log_error "Falha na restauração do banco de dados!"
        return 1
    fi
}

#------------------------------------------------------------------------------
# MENU PRINCIPAL
#------------------------------------------------------------------------------

show_menu() {
    echo ""
    echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║  🔄 MontaLoja - Sistema de Rollback                          ║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════════════════╣${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}║  1. Rollback rápido (versão anterior)                        ║${NC}"
    echo -e "${CYAN}║  2. Escolher versão específica                               ║${NC}"
    echo -e "${CYAN}║  3. Restaurar backup do banco de dados                       ║${NC}"
    echo -e "${CYAN}║  4. Listar releases disponíveis                              ║${NC}"
    echo -e "${CYAN}║  5. Sair                                                     ║${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
}

#------------------------------------------------------------------------------
# MAIN
#------------------------------------------------------------------------------

main() {
    # Se passou argumento --quick, fazer rollback rápido sem menu
    if [ "$1" == "--quick" ] || [ "$1" == "-q" ]; then
        rollback_previous
        exit $?
    fi
    
    while true; do
        show_menu
        read -p "Escolha uma opção: " option
        
        case $option in
            1)
                rollback_previous
                ;;
            2)
                rollback_specific
                ;;
            3)
                restore_database
                ;;
            4)
                list_releases
                ;;
            5|q|Q)
                log_info "Saindo..."
                exit 0
                ;;
            *)
                log_error "Opção inválida!"
                ;;
        esac
        
        echo ""
        read -p "Pressione ENTER para continuar..."
    done
}

main "$@"
