#!/bin/bash
#==============================================================================
# MontaLoja - Blue-Green Deployment Script
# Autor: DevOps Automation
# Versão: 1.0.0
# Descrição: Script de deploy com atomic symlinks e modo de teste seguro
#==============================================================================

set -e  # Para execução em caso de erro

#------------------------------------------------------------------------------
# CONFIGURAÇÕES - Ajuste conforme seu ambiente
#------------------------------------------------------------------------------
APP_NAME="montaloja"
APP_USER="socialar"
WEB_USER="nobody"  # Usuário do servidor web (cPanel/CloudLinux usa nobody)

# Diretórios base
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"

# Git
GIT_REPO=""  # Preencha: git@github.com:seu-usuario/montaloja.git
GIT_BRANCH="main"

# Banco de dados
DB_HOST="localhost"
DB_NAME="socialar_socialar_commerce"
DB_USER="socialar"
DB_PASS="y557t55n7rt6"

# Tabelas críticas para backup
CRITICAL_TABLES="orders order_items products stores users customers store_customers"

# Pastas/arquivos que devem persistir entre deploys (serão linkados do shared)
SHARED_PATHS=(
    "uploads"
    "storage"
    "includes/config.php"
)

# Pastas que precisam de permissão de escrita
WRITABLE_PATHS=(
    "storage"
    "templates"
)

# Número máximo de releases antigas mantidas
MAX_RELEASES=5

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

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

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_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1"
}

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

print_header() {
    echo ""
    echo -e "${CYAN}============================================================${NC}"
    echo -e "${CYAN}  MontaLoja - Blue-Green Deployment${NC}"
    echo -e "${CYAN}  $(date '+%Y-%m-%d %H:%M:%S')${NC}"
    echo -e "${CYAN}============================================================${NC}"
    echo ""
}

print_section() {
    echo ""
    echo -e "${YELLOW}────────────────────────────────────────────────────────────${NC}"
    echo -e "${YELLOW}  $1${NC}"
    echo -e "${YELLOW}────────────────────────────────────────────────────────────${NC}"
}

confirm() {
    echo ""
    read -p "$(echo -e ${YELLOW}$1${NC} ' [s/N]: ')" response
    case "$response" in
        [sS][iI][mM]|[sS]|[yY][eE][sS]|[yY]) 
            return 0
            ;;
        *)
            return 1
            ;;
    esac
}

#------------------------------------------------------------------------------
# SETUP INICIAL - Cria estrutura de diretórios
#------------------------------------------------------------------------------

setup_directories() {
    print_section "1. Preparando Estrutura de Diretórios"
    
    # Criar diretórios base
    mkdir -p "$RELEASES_DIR"
    mkdir -p "$SHARED_DIR"
    mkdir -p "$BACKUPS_DIR"
    mkdir -p "${SHARED_DIR}/uploads"
    mkdir -p "${SHARED_DIR}/uploads/products"
    mkdir -p "${SHARED_DIR}/uploads/heroes"
    mkdir -p "${SHARED_DIR}/uploads/logos"
    mkdir -p "${SHARED_DIR}/storage"
    mkdir -p "${SHARED_DIR}/storage/logs"
    mkdir -p "${SHARED_DIR}/storage/cache"
    mkdir -p "${SHARED_DIR}/storage/sessions"
    
    log_success "Diretórios criados/verificados"
    
    # Se for primeira execução, mover uploads existentes para shared
    if [ -d "${BASE_DIR}/uploads" ] && [ ! -L "${BASE_DIR}/uploads" ]; then
        log_info "Movendo uploads existentes para shared..."
        cp -rn "${BASE_DIR}/uploads/"* "${SHARED_DIR}/uploads/" 2>/dev/null ; true
        log_success "Uploads migrados para shared"
    fi
    
    # Copiar config.php para shared se não existir
    if [ ! -f "${SHARED_DIR}/config.php" ]; then
        if [ -f "${BASE_DIR}/includes/config.php" ]; then
            cp "${BASE_DIR}/includes/config.php" "${SHARED_DIR}/config.php"
            log_success "config.php copiado para shared"
        fi
    fi
}

#------------------------------------------------------------------------------
# BACKUP DO BANCO DE DADOS
#------------------------------------------------------------------------------

backup_database() {
    print_section "2. Backup do Banco de Dados"
    
    local TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    local BACKUP_FILE="${BACKUPS_DIR}/db_backup_${TIMESTAMP}.sql"
    local BACKUP_CRITICAL="${BACKUPS_DIR}/db_critical_${TIMESTAMP}.sql"
    
    log_info "Criando backup completo do banco..."
    
    # Backup completo
    mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" \
        --single-transaction \
        --quick \
        --lock-tables=false \
        > "$BACKUP_FILE" 2>/dev/null
    
    if [ $? -eq 0 ]; then
        gzip "$BACKUP_FILE"
        log_success "Backup completo: ${BACKUP_FILE}.gz ($(du -h ${BACKUP_FILE}.gz | cut -f1))"
    else
        log_error "Falha no backup completo!"
        return 1
    fi
    
    # Backup das tabelas críticas (separado para restore rápido)
    log_info "Criando backup das tabelas críticas (orders, products, stores)..."
    
    mysqldump -h "$DB_HOST" -u "$DB_USER" -p"$DB_PASS" "$DB_NAME" \
        $CRITICAL_TABLES \
        --single-transaction \
        --quick \
        > "$BACKUP_CRITICAL" 2>/dev/null
    
    if [ $? -eq 0 ]; then
        gzip "$BACKUP_CRITICAL"
        log_success "Backup crítico: ${BACKUP_CRITICAL}.gz"
    fi
    
    # Limpar backups antigos (manter últimos 10)
    log_info "Limpando backups antigos..."
    ls -t "${BACKUPS_DIR}"/db_backup_*.sql.gz 2>/dev/null | tail -n +11 | xargs rm -f 2>/dev/null ; true
    ls -t "${BACKUPS_DIR}"/db_critical_*.sql.gz 2>/dev/null | tail -n +11 | xargs rm -f 2>/dev/null ; true
    
    log_success "Backup concluído!"
}

#------------------------------------------------------------------------------
# DOWNLOAD DO CÓDIGO (Git ou Cópia Local)
#------------------------------------------------------------------------------

download_release() {
    print_section "3. Preparando Nova Release"
    
    local TIMESTAMP=$(date +%Y%m%d_%H%M%S)
    RELEASE_NAME="release_${TIMESTAMP}"
    RELEASE_PATH="${RELEASES_DIR}/${RELEASE_NAME}"
    
    log_info "Nova release: ${RELEASE_NAME}"
    
    if [ -n "$GIT_REPO" ]; then
        # Clone do Git
        log_info "Clonando repositório Git..."
        git clone --depth 1 --branch "$GIT_BRANCH" "$GIT_REPO" "$RELEASE_PATH"
        
        # Remover pasta .git para economizar espaço
        rm -rf "${RELEASE_PATH}/.git"
        
        log_success "Código baixado do Git"
    else
        # Cópia do código atual (útil para primeiro deploy)
        log_warning "Git não configurado. Copiando código atual..."
        
        # Copiar tudo exceto pastas que serão linkadas
        mkdir -p "$RELEASE_PATH"
        
        # Lista de exclusões
        EXCLUDES="--exclude=releases --exclude=shared --exclude=backups --exclude=deploy --exclude=uploads --exclude=storage --exclude=current --exclude=*.zip --exclude=*.bak"
        
        rsync -a $EXCLUDES "${BASE_DIR}/" "$RELEASE_PATH/"
        
        log_success "Código copiado para ${RELEASE_PATH}"
    fi
}

#------------------------------------------------------------------------------
# CRIAR SYMLINKS PARA SHARED
#------------------------------------------------------------------------------

create_shared_symlinks() {
    print_section "4. Criando Symlinks para Arquivos Compartilhados"
    
    log_info "Linkando uploads..."
    
    # Remover pasta uploads vazia da release (se existir)
    rm -rf "${RELEASE_PATH}/uploads"
    
    # Criar symlink para shared/uploads
    ln -sfn "${SHARED_DIR}/uploads" "${RELEASE_PATH}/uploads"
    log_success "uploads -> ${SHARED_DIR}/uploads"
    
    # Remover pasta storage vazia da release (se existir)
    rm -rf "${RELEASE_PATH}/storage"
    
    # Criar symlink para shared/storage
    ln -sfn "${SHARED_DIR}/storage" "${RELEASE_PATH}/storage"
    log_success "storage -> ${SHARED_DIR}/storage"
    
    # Linkar config.php
    if [ -f "${SHARED_DIR}/config.php" ]; then
        rm -f "${RELEASE_PATH}/includes/config.php"
        ln -sfn "${SHARED_DIR}/config.php" "${RELEASE_PATH}/includes/config.php"
        log_success "includes/config.php -> ${SHARED_DIR}/config.php"
    fi
    
    log_success "Symlinks criados!"
}

#------------------------------------------------------------------------------
# CONFIGURAR PERMISSÕES
#------------------------------------------------------------------------------

set_permissions() {
    print_section "5. Configurando Permissões"
    
    log_info "Ajustando permissões da release..."
    
    # Permissões base (leitura para todos, escrita para owner)
    find "$RELEASE_PATH" -type f -exec chmod 644 {} \;
    find "$RELEASE_PATH" -type d -exec chmod 755 {} \;
    
    # Permissões de escrita para pastas específicas no shared
    chmod -R 775 "${SHARED_DIR}/uploads"
    chmod -R 775 "${SHARED_DIR}/storage"
    
    # Garantir que o usuário web pode escrever
    chown -R ${APP_USER}:${WEB_USER} "${SHARED_DIR}/uploads" 2>/dev/null ; true
    chown -R ${APP_USER}:${WEB_USER} "${SHARED_DIR}/storage" 2>/dev/null ; true
    
    # Templates (se precisar de escrita para cache)
    if [ -d "${RELEASE_PATH}/templates" ]; then
        chmod -R 775 "${RELEASE_PATH}/templates"
    fi
    
    log_success "Permissões configuradas!"
}

#------------------------------------------------------------------------------
# MODO DE TESTE - Permite verificar antes de ativar
#------------------------------------------------------------------------------

test_mode() {
    print_section "6. MODO DE TESTE - Verificação Pré-Deploy"
    
    echo ""
    echo -e "${CYAN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${CYAN}║  🔍 NOVA VERSÃO PREPARADA PARA TESTE                         ║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════════════════╣${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}║  Release: ${RELEASE_NAME}${NC}"
    echo -e "${CYAN}║  Caminho: ${RELEASE_PATH}${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════════════════╣${NC}"
    echo -e "${CYAN}║  COMO TESTAR ANTES DE ATIVAR:                                ║${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}║  OPÇÃO 1 - Criar subdomínio temporário:                      ║${NC}"
    echo -e "${CYAN}║    → No cPanel, crie: staging.montaloja.com                  ║${NC}"
    echo -e "${CYAN}║    → Aponte para: ${RELEASE_PATH}${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}║  OPÇÃO 2 - Acesso direto via pasta (teste rápido):           ║${NC}"
    echo -e "${CYAN}║    → Crie um link: ln -s ${RELEASE_PATH} ${BASE_DIR}/test    ║${NC}"
    echo -e "${CYAN}║    → Acesse: https://montaloja.com/test/                     ║${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}║  OPÇÃO 3 - Verificação via linha de comando:                 ║${NC}"
    echo -e "${CYAN}║    → php -l ${RELEASE_PATH}/pages/pedidos.php                ║${NC}"
    echo -e "${CYAN}║    → php -l ${RELEASE_PATH}/dashboard.php                    ║${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}╠══════════════════════════════════════════════════════════════╣${NC}"
    echo -e "${CYAN}║  📋 CHECKLIST DE VERIFICAÇÃO:                                ║${NC}"
    echo -e "${CYAN}║    [ ] Dashboard carrega sem erros                           ║${NC}"
    echo -e "${CYAN}║    [ ] Página de Pedidos funciona                            ║${NC}"
    echo -e "${CYAN}║    [ ] Storefront abre corretamente                          ║${NC}"
    echo -e "${CYAN}║    [ ] Imagens de produtos aparecem                          ║${NC}"
    echo -e "${CYAN}║    [ ] Hero Banner exibe corretamente                        ║${NC}"
    echo -e "${CYAN}║                                                              ║${NC}"
    echo -e "${CYAN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
    
    # Verificação automática de sintaxe PHP
    log_info "Executando verificação automática de sintaxe PHP..."
    
    local SYNTAX_ERRORS=0
    local CRITICAL_FILES=(
        "dashboard.php"
        "pages/pedidos.php"
        "pages/produtos.php"
        "pages/storefront/templates/retail/modern/home.php"
        "includes/config.php"
    )
    
    for file in "${CRITICAL_FILES[@]}"; do
        if [ -f "${RELEASE_PATH}/${file}" ]; then
            php -l "${RELEASE_PATH}/${file}" > /dev/null 2>&1
            if [ $? -eq 0 ]; then
                echo -e "  ${GREEN}✓${NC} ${file}"
            else
                echo -e "  ${RED}✗${NC} ${file} - ERRO DE SINTAXE!"
                SYNTAX_ERRORS=$((SYNTAX_ERRORS + 1))
            fi
        fi
    done
    
    if [ $SYNTAX_ERRORS -gt 0 ]; then
        log_error "Foram encontrados ${SYNTAX_ERRORS} erro(s) de sintaxe PHP!"
        log_error "Corrija os erros antes de continuar."
        return 1
    fi
    
    log_success "Verificação de sintaxe concluída sem erros!"
    
    echo ""
    if confirm "Deseja ATIVAR a nova versão agora?"; then
        return 0
    else
        log_warning "Deploy cancelado pelo usuário."
        log_info "A release permanece em: ${RELEASE_PATH}"
        log_info "Para ativar manualmente depois, execute:"
        echo ""
        echo "  ln -sfn ${RELEASE_PATH} ${CURRENT_LINK}"
        echo ""
        exit 0
    fi
}

#------------------------------------------------------------------------------
# ATIVAR NOVA VERSÃO (Atomic Symlink Swap)
#------------------------------------------------------------------------------

activate_release() {
    print_section "7. Ativando Nova Versão"
    
    # Salvar versão anterior (se existir)
    if [ -L "$CURRENT_LINK" ]; then
        PREVIOUS_RELEASE=$(readlink -f "$CURRENT_LINK")
        echo "$PREVIOUS_RELEASE" > "${SHARED_DIR}/.previous_release"
        log_info "Versão anterior salva: ${PREVIOUS_RELEASE}"
    fi
    
    # Atomic symlink swap
    # Criamos um link temporário e depois movemos (operação atômica)
    log_info "Executando atomic symlink swap..."
    
    ln -sfn "$RELEASE_PATH" "${CURRENT_LINK}.new"
    mv -Tf "${CURRENT_LINK}.new" "$CURRENT_LINK"
    
    log_success "Link 'current' atualizado para: ${RELEASE_PATH}"
    
    # Atualizar link na raiz (se necessário para compatibilidade)
    # Isso faz com que o site aponte para current
    
    # Limpar cache do PHP (se OPcache estiver ativo)
    log_info "Limpando cache PHP..."
    
    # Tenta reiniciar PHP-FPM ou limpar OPcache
    if command -v systemctl &> /dev/null; then
        sudo systemctl reload php-fpm 2>/dev/null ; true
    fi
    
    # Alternativa: criar arquivo para invalidar OPcache
    if [ -f "${RELEASE_PATH}/opcache_reset.php" ]; then
        curl -s "https://montaloja.com/opcache_reset.php" > /dev/null 2>&1 ; true
    fi
    
    log_success "Nova versão ATIVADA com sucesso!"
}

#------------------------------------------------------------------------------
# LIMPEZA DE RELEASES ANTIGAS
#------------------------------------------------------------------------------

cleanup_old_releases() {
    print_section "8. Limpeza de Releases Antigas"
    
    log_info "Mantendo últimas ${MAX_RELEASES} releases..."
    
    # Listar releases ordenadas por data (mais recentes primeiro)
    cd "$RELEASES_DIR"
    local RELEASES=($(ls -dt release_* 2>/dev/null))
    local COUNT=${#RELEASES[@]}
    
    if [ $COUNT -gt $MAX_RELEASES ]; then
        local TO_DELETE=$((COUNT - MAX_RELEASES))
        log_info "Removendo ${TO_DELETE} release(s) antiga(s)..."
        
        for ((i=$MAX_RELEASES; i<$COUNT; i++)); do
            local OLD_RELEASE="${RELEASES[$i]}"
            
            # Não remover a versão atual ou anterior
            if [ "${RELEASES_DIR}/${OLD_RELEASE}" != "$RELEASE_PATH" ] ; \
               [ "${RELEASES_DIR}/${OLD_RELEASE}" != "$PREVIOUS_RELEASE" ]; then
                rm -rf "${RELEASES_DIR}/${OLD_RELEASE}"
                log_info "Removida: ${OLD_RELEASE}"
            fi
        done
    fi
    
    log_success "Limpeza concluída! Total de releases: $(ls -d release_* 2>/dev/null | wc -l)"
}

#------------------------------------------------------------------------------
# RELATÓRIO FINAL
#------------------------------------------------------------------------------

print_summary() {
    print_section "✅ DEPLOY CONCLUÍDO COM SUCESSO"
    
    echo ""
    echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
    echo -e "${GREEN}║  📊 RESUMO DO DEPLOY                                         ║${NC}"
    echo -e "${GREEN}╠══════════════════════════════════════════════════════════════╣${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}║  Release Ativa: ${RELEASE_NAME}${NC}"
    echo -e "${GREEN}║  Caminho: ${RELEASE_PATH}${NC}"
    echo -e "${GREEN}║  Horário: $(date '+%Y-%m-%d %H:%M:%S')${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}║  Backups salvos em: ${BACKUPS_DIR}${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}╠══════════════════════════════════════════════════════════════╣${NC}"
    echo -e "${GREEN}║  🔙 EM CASO DE PROBLEMAS:                                    ║${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}║  Execute o rollback:                                         ║${NC}"
    echo -e "${GREEN}║  ./rollback.sh                                               ║${NC}"
    echo -e "${GREEN}║                                                              ║${NC}"
    echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
    echo ""
}

#------------------------------------------------------------------------------
# MAIN - Execução Principal
#------------------------------------------------------------------------------

main() {
    print_header
    
    # Verificar se está rodando como usuário correto
    if [ "$(whoami)" != "$APP_USER" ]; then
        log_warning "Este script deve ser executado como usuário '${APP_USER}'"
        log_info "Execute: su - ${APP_USER} -c '${0}'"
    fi
    
    # Confirmação inicial
    echo -e "${YELLOW}Este script irá:${NC}"
    echo "  1. Criar backup do banco de dados"
    echo "  2. Preparar nova versão do código"
    echo "  3. Permitir que você teste antes de ativar"
    echo "  4. Ativar a nova versão via atomic symlink"
    echo ""
    
    if ! confirm "Deseja continuar com o deploy?"; then
        log_info "Deploy cancelado."
        exit 0
    fi
    
    # Executar etapas
    setup_directories
    backup_database
    download_release
    create_shared_symlinks
    set_permissions
    
    # Modo de teste - aguarda confirmação
    if ! test_mode; then
        exit 1
    fi
    
    # Ativar nova versão
    activate_release
    cleanup_old_releases
    
    # Resumo final
    print_summary
}

# Executar
main "$@"
