#!/usr/bin/env bash
#
# deploy.sh — Despliegue de Metafoliador v2 al servidor productivo
#
# Uso:
#   ./deploy.sh              # Despliega cambios detectados desde el último deploy
#   ./deploy.sh --all        # Despliega todo el proyecto (full sync)
#   ./deploy.sh --force      # Fuerza reinicio de todos los servicios sin importar qué cambió
#
# Requisitos:
#   - sshpass instalado localmente
#

set -euo pipefail

# ─── Configuración del servidor productivo ───────────────────────────────────
PROD_HOST="54.39.196.195"
PROD_PORT="2828"
PROD_USER="root"
PROD_PASS="L5yD@68%e%E[aj3u"
PROD_PATH="/var/www/html/metafoliadorv2"

# ─── Rutas locales ────────────────────────────────────────────────────────────
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$SCRIPT_DIR"
STATE_FILE="$PROJECT_ROOT/.deploy_state"

# ─── Opciones ─────────────────────────────────────────────────────────────────
MODE="diff"       # diff | all | force

for arg in "$@"; do
    case "$arg" in
        --all)   MODE="all" ;;
        --force) MODE="force" ;;
        --help|-h)
            echo "Uso: ./deploy.sh [--all] [--force]"
            echo "  (sin flags)  Despliega solo archivos modificados desde el último deploy"
            echo "  --all        Despliega todo el proyecto completo"
            echo "  --force      Fuerza reinicio de todos los servicios"
            exit 0
            ;;
        *) echo "Opción desconocida: $arg"; exit 1 ;;
    esac
done

# ─── Colores ──────────────────────────────────────────────────────────────────
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

log()  { echo -e "${GREEN}[DEPLOY]${NC} $1"; }
warn() { echo -e "${YELLOW}[AVISO]${NC} $1"; }
err()  { echo -e "${RED}[ERROR]${NC} $1"; exit 1; }
info() { echo -e "${BLUE}[INFO]${NC} $1"; }

# ─── SSH helper ───────────────────────────────────────────────────────────────
export SSHPASS="$PROD_PASS"
SSH_CMD="sshpass -e ssh -p $PROD_PORT -o StrictHostKeyChecking=no -o ConnectTimeout=10"
SCP_CMD="sshpass -e scp -P $PROD_PORT -o StrictHostKeyChecking=no -o ConnectTimeout=10"

# ─── Verificar conectividad ───────────────────────────────────────────────────
log "Verificando conectividad con $PROD_HOST:$PROD_PORT ..."
if ! $SSH_CMD $PROD_USER@$PROD_HOST "echo ok" &>/dev/null; then
    err "No se pudo conectar al servidor productivo. Verifica la conectividad."
fi
log "Conexión SSH establecida."

# ─── Determinar qué archivos sincronizar ──────────────────────────────────────
if [ "$MODE" = "all" ]; then
    log "Modo: despliegue COMPLETO de todo el proyecto."
    CHANGED_FILES="(todos los archivos)"
    CHANGED_COUNT="TODO"
else
    log "Modo: despliegue INCREMENTAL (solo archivos modificados desde el último deploy)."

    if [ -f "$STATE_FILE" ]; then
        LAST_DEPLOY=$(cat "$STATE_FILE")
        log "Último deploy: $LAST_DEPLOY"
    else
        warn "No se encontró estado de deploy anterior. Se desplegará todo."
        LAST_DEPLOY="1970-01-01 00:00:00"
    fi

    CHANGED_FILES=$(find "$PROJECT_ROOT" \
        -type f \
        -newermt "$LAST_DEPLOY" \
        ! -path '*/.git/*' \
        ! -path '*/__pycache__/*' \
        ! -path '*.pyc' \
        ! -path '*/.venv/*' \
        ! -path '*/venv/*' \
        ! -path '*/node_modules/*' \
        ! -path '*.log' \
        ! -path '*/.deploy_state' \
        ! -name '.env' \
        ! -name '.DS_Store' \
        -printf '%P\n' 2>/dev/null || true)

    if [ -z "$CHANGED_FILES" ]; then
        warn "No se detectaron archivos modificados desde el último deploy."
        warn "Usa --all para forzar un despliegue completo."
        exit 0
    fi

    CHANGED_COUNT=$(echo "$CHANGED_FILES" | wc -l)
    log "Se detectaron $CHANGED_COUNT archivo(s) modificado(s)."
fi

# ─── Analizar qué tipo de archivos cambiaron ─────────────────────────────────
RESTART_API=false
RESTART_WORKER=false
RESTART_BEAT=false
RUN_MIGRATIONS=false
RUN_PIP_INSTALL=false

if [ "$MODE" = "force" ]; then
    RESTART_API=true
    RESTART_WORKER=true
    RESTART_BEAT=true
    RUN_MIGRATIONS=true
    RUN_PIP_INSTALL=true
    log "Modo FORCE: se reiniciarán todos los servicios."
else
    if echo "$CHANGED_FILES" | grep -q "requirements.txt"; then
        RUN_PIP_INSTALL=true
        RESTART_API=true
        RESTART_WORKER=true
        info "requirements.txt modificado → pip install + reinicio API y worker"
    fi

    if echo "$CHANGED_FILES" | grep -qE "(alembic/|models/)"; then
        RUN_MIGRATIONS=true
        RESTART_API=true
        RESTART_WORKER=true
        info "Modelos/Migraciones modificados → alembic upgrade + reinicio API y worker"
    fi

    if echo "$CHANGED_FILES" | grep -qE "^app/.*\.py$"; then
        RESTART_API=true
        RESTART_WORKER=true
        info "Código Python modificado → reinicio API y worker"
    fi

    if echo "$CHANGED_FILES" | grep -qE "^(static/|templates/)"; then
        info "Archivos estáticos/templates modificados → no requiere reinicio"
    fi

    if echo "$CHANGED_FILES" | grep -q "config.py"; then
        RESTART_API=true
        RESTART_WORKER=true
        info "config.py modificado → reinicio API y worker"
    fi
fi

# ─── Mostrar resumen de acciones ──────────────────────────────────────────────
echo ""
echo "═══════════════════════════════════════════════════════════════"
echo "  RESUMEN DE DESPLIEGUE"
echo "═══════════════════════════════════════════════════════════════"
echo "  Destino:        $PROD_USER@$PROD_HOST:$PROD_PORT"
echo "  Ruta remota:    $PROD_PATH"
echo "  Modo:           $MODE"
echo "  Sincronizar:    $CHANGED_COUNT"
echo "  pip install:    $RUN_PIP_INSTALL"
echo "  Migraciones:    $RUN_MIGRATIONS"
echo "  Reiniciar API:  $RESTART_API"
echo "  Reiniciar Worker: $RESTART_WORKER"
echo "  Reiniciar Beat: $RESTART_BEAT"
echo "═══════════════════════════════════════════════════════════════"
echo ""

# ─── Confirmación ─────────────────────────────────────────────────────────────
if [ -t 0 ]; then
    read -rp "¿Continuar con el despliegue? [s/N] " CONFIRM
    if [[ ! "$CONFIRM" =~ ^[sSyY]$ ]]; then
        log "Despliegue cancelado."
        exit 0
    fi
else
    log "Modo no interactivo: continuando despliegue automáticamente."
fi

# ─── Ejecutar despliegue ──────────────────────────────────────────────────────
TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')

# 1. Sincronizar archivos vía tar+scp
log "Sincronizando archivos al servidor productivo ..."

if [ "$MODE" = "all" ]; then
    TAR_FILE=$(mktemp /tmp/deploy_metafoliador_XXXXXX.tar.gz)
    tar czf "$TAR_FILE" \
        --exclude='.git' \
        --exclude='__pycache__' \
        --exclude='*.pyc' \
        --exclude='.venv' \
        --exclude='venv' \
        --exclude='node_modules' \
        --exclude='*.log' \
        --exclude='.env' \
        --exclude='.DS_Store' \
        --exclude='.deploy_state' \
        -C "$PROJECT_ROOT" .
    log "Archivo comprimido: $(du -h "$TAR_FILE" | cut -f1)"
else
    TAR_FILE=$(mktemp /tmp/deploy_metafoliador_XXXXXX.tar.gz)
    echo "$CHANGED_FILES" | tar czf "$TAR_FILE" -C "$PROJECT_ROOT" -T -
    log "Archivo comprimido: $(du -h "$TAR_FILE" | cut -f1)"
fi

$SCP_CMD "$TAR_FILE" "${PROD_USER}@${PROD_HOST}:/tmp/deploy_metafoliador.tar.gz" || {
    rm -f "$TAR_FILE"
    err "Fallo la transferencia de archivos al servidor."
}

$SSH_CMD $PROD_USER@$PROD_HOST "cd $PROD_PATH && tar xzf /tmp/deploy_metafoliador.tar.gz && rm /tmp/deploy_metafoliador.tar.gz" || {
    rm -f "$TAR_FILE"
    err "Fallo la extracción de archivos en el servidor."
}

rm -f "$TAR_FILE"
log "Archivos sincronizados correctamente."

# 2. pip install si es necesario
if [ "$RUN_PIP_INSTALL" = true ]; then
    log "Instalando dependencias Python en el servidor productivo ..."
    $SSH_CMD $PROD_USER@$PROD_HOST "cd $PROD_PATH && source venv/bin/activate && pip install -r requirements.txt" || {
        warn "pip install falló — verificar manualmente."
    }
fi

# 3. Migraciones si es necesario
if [ "$RUN_MIGRATIONS" = true ]; then
    log "Ejecutando migraciones de base de datos ..."
    $SSH_CMD $PROD_USER@$PROD_HOST "cd $PROD_PATH && source venv/bin/activate && alembic upgrade head" || {
        warn "alembic upgrade falló — verificar manualmente."
    }
fi

# 4. Reiniciar servicios según corresponda
restart_service() {
    local service_name="$1"
    local service_unit="$2"
    log "Reiniciando $service_name ..."
    if $SSH_CMD $PROD_USER@$PROD_HOST "systemctl restart $service_unit" 2>/dev/null; then
        log "$service_name reiniciado (systemctl)."
    elif $SSH_CMD $PROD_USER@$PROD_HOST "supervisorctl restart $service_unit" 2>/dev/null; then
        log "$service_name reiniciado (supervisorctl)."
    else
        warn "No se pudo reiniciar $service_name. Reinicia manualmente."
    fi
}

if [ "$RESTART_API" = true ]; then
    restart_service "API (uvicorn)" "metafoliadorv2.service"
fi

if [ "$RESTART_WORKER" = true ]; then
    restart_service "Celery Worker" "metafoliadorv2-worker.service"
    restart_service "Webhook Worker" "metafoliadorv2-webhook-worker.service"
fi

if [ "$RESTART_BEAT" = true ]; then
    restart_service "Celery Beat" "metafoliador-beat"
fi

# ─── Guardar estado del deploy ────────────────────────────────────────────────
echo "$TIMESTAMP" > "$STATE_FILE"
log "Estado de deploy guardado: $TIMESTAMP"

echo ""
log "Despliegue completado exitosamente."
