#!/bin/bash

# ======================== PARÁMETROS ========================

while getopts r:p:t:v:n:l:s:e: flag; do
  case "${flag}" in
  r) restart=${OPTARG} ;;
  p) prod=${OPTARG} ;;
  t) teste=${OPTARG} ;;
  v) version=${OPTARG} ;;
  n) nombre=${OPTARG} ;;
  l) listar=${OPTARG} ;;
  s) status=${OPTARG} ;;
  e) exacto=${OPTARG} ;; 
  esac
done

# ======================== VARIABLES ========================

APP_NAME="DolphinX"
APP_TESTE_NAME="DolphinX-teste"
ARTIFACTORY_BASE_URL="http://maestro.datapar.com/artifactory/datapar/FATURAX/APP"
LOG_DIR="/var/deploy_logs"
TEMP_DIR="/tmp/deploy_temp"
CHECK_INTERVAL=5
MESSAGE_INTERVAL=60
DEPLOY_TIMEOUT=600

restart="${restart:-false}"
prod="${prod:-false}"
teste="${teste:-false}"
version="${version:-false}"
nombre="${nombre:-}"
listar="${listar:-false}"
status="${status:-false}"
exacto="${exacto:-false}"

clear
cat <<"EOF"
 
 /$$$$$$$  /$$$$$$$$ /$$$$$$$  /$$        /$$$$$$  /$$     /$$ /$$$$$$$$ /$$$$$$$         /$$$$$$   /$$$$$$  /$$       /$$$$$$$$  /$$$$$$ 
| $$__  $$| $$_____/| $$__  $$| $$       /$$__  $$|  $$   /$$/| $$_____/| $$__  $$       /$$__  $$ /$$__  $$| $$      | $$_____/ /$$__  $$
| $$  \ $$| $$      | $$  \ $$| $$      | $$  \ $$ \  $$ /$$/ | $$      | $$  \ $$      | $$  \__/| $$  \ $$| $$      | $$      | $$  \__/
| $$  | $$| $$$$$   | $$$$$$$/| $$      | $$  | $$  \  $$$$/  | $$$$$   | $$$$$$$/      |  $$$$$$ | $$$$$$$$| $$      | $$$$$   |  $$$$$$ 
| $$  | $$| $$__/   | $$____/ | $$      | $$  | $$   \  $$/   | $$__/   | $$__  $$       \____  $$| $$__  $$| $$      | $$__/    \____  $$
| $$  | $$| $$      | $$      | $$      | $$  | $$    | $$    | $$      | $$  \ $$       /$$  \ $$| $$  | $$| $$      | $$       /$$  \ $$
| $$$$$$$/| $$$$$$$$| $$      | $$$$$$$$|  $$$$$$/    | $$    | $$$$$$$$| $$  | $$      |  $$$$$$/| $$  | $$| $$$$$$$$| $$$$$$$$|  $$$$$$/
|_______/ |________/|__/      |________/ \______/     |__/    |________/|__/  |__/       \______/ |__/  |__/|________/|________/ \______/ 
                                                                                                                                                                                                                                                                                   
EOF

# ======================== CONFIGURACIÓN DE LOGS ========================

mkdir -p "$LOG_DIR"
find "$LOG_DIR" -type f -name "deploy_fx_*.log" -mtime +5 -exec rm -f {} + 2>/dev/null
LOG_FILE="$LOG_DIR/deploy_fx_$(date +'%Y-%m-%d').log"

log() {
  local type="$1"
  local msg="$2"
  echo -e "$(date +'%Y-%m-%d %H:%M:%S') - ${type}: $msg" | tee -a "$LOG_FILE"
}

# ======================== FUNCIONES DE LIMPIEZA ========================

cleanup() {
  log INFO "Limpiando archivos generados"
  
  # Limpiar directorio temporal
  [[ -d "$TEMP_DIR" ]] && rm -rf "$TEMP_DIR" 2>/dev/null
  
  # Limpiar archivos locales relacionados con DolphinX
  [[ -f "$APP_NAME.war" ]] && rm -f "$APP_NAME.war"
  [[ -f "$APP_TESTE_NAME.war" ]] && rm -f "$APP_TESTE_NAME.war"
  
  # Limpiar archivos wget-log
  find . -name "wget-log*" -delete 2>/dev/null
  
  # Limpiar script temporal si existe
  find /home -type f -name "script_fx_docker_final.sh" -exec rm -f {} \; 2>/dev/null
  
  log INFO "Limpieza completada"
}


# Configurar trap para limpieza automática
trap cleanup EXIT ERR INT TERM

# ======================== VALIDACIÓN DE CONTENEDORES ========================

validate_container_active() {
  local container_name="$1"
  local quiet="${2:-false}"
  
  # Verificar si Docker está disponible
  if ! command -v docker &> /dev/null; then
    [[ "$quiet" == "false" ]] && log WARN "Docker no disponible. Saltando validación para: $container_name"
    return 0
  fi
  
  # Verificar si el contenedor está ejecutándose
  if docker ps --format "{{.Names}}" 2>/dev/null | grep -q "^${container_name}$"; then
    [[ "$quiet" == "false" ]] && log INFO "✓ Contenedor '$container_name' está activo"
    return 0
  else
    [[ "$quiet" == "false" ]] && log WARN "✗ Contenedor '$container_name' no está activo. Saltando deploy..."
    return 1
  fi
}

# ======================== GESTIÓN DE ARCHIVOS WAR ========================

descargar_war() {
  local version="$1"
  local war_original_path="${TEMP_DIR}/${APP_NAME}.war"

  # Limpiar y crear directorio temporal
  rm -rf "$TEMP_DIR"
  mkdir -p "$TEMP_DIR"

  log INFO "Descargando WAR base a: $war_original_path"
  
  # Cambiar al directorio temporal 
  local original_dir=$(pwd)
  cd "$TEMP_DIR"
  
  # Limpiar cualquier archivo wget-log previo
  rm -f wget-log* 2>/dev/null
  
  # Descargar con wget
  if wget --no-check-certificate \
          --progress=bar:force \
          --timeout=30 \
          --tries=3 \
          -O "$war_original_path" \
          "${ARTIFACTORY_BASE_URL}/${APP_NAME}/${version}/${APP_NAME}-${version}.war"; then
    
    if [[ -f "$war_original_path" && -s "$war_original_path" ]]; then
      local file_size=$(stat -c%s "$war_original_path" 2>/dev/null || echo "0")
      log SUCCESS "WAR descargado correctamente"
    else
      log ERROR "El archivo descargado está vacío o no existe"
      cd "$original_dir"
      cleanup
      exit 1
    fi
  else
    log ERROR "Error en la descarga del WAR"
    cd "$original_dir"
    cleanup
    exit 1
  fi
  
  # Limpiar wget-log inmediatamente después
  rm -f wget-log* 2>/dev/null
  
  # Volver al directorio original
  cd "$original_dir"
}

preparar_war_para_ambiente() {
  local app_name="$1"
  local war_original_path="${TEMP_DIR}/${APP_NAME}.war"
  local war_destino_path="${TEMP_DIR}/${app_name}.war"

  # Si es el mismo nombre (producción), no necesita copia
  if [[ "$app_name" == "$APP_NAME" ]]; then
    log INFO "WAR de producción listo: $war_original_path"
    return 0
  fi

  # Para teste, copiar y renombrar
  log INFO "Preparando WAR para teste: $app_name"
  if cp "$war_original_path" "$war_destino_path"; then
    log SUCCESS "WAR para teste preparado: $war_destino_path"
    return 0
  else
    log ERROR "Error al preparar WAR para teste"
    cleanup
    exit 1
  fi
}

# ======================== FUNCIONES DE DEPLOYMENT ========================

deploy_application() {
  local app_name="$1"
  local deploy_path="$2"
  local container_name="$3"
  local war_temp_path="${TEMP_DIR}/${app_name}.war"

  if [[ "$version" == "false" ]]; then
    log ERROR "Debe especificar la versión para realizar el deploy."
    cleanup
    exit 1
  fi

  if [[ ! -f "$war_temp_path" ]]; then
    log ERROR "Archivo WAR no encontrado en: $war_temp_path"
    cleanup
    exit 1
  fi

  log INFO "Limpiando archivos antiguos..."
 if [[ -d "$deploy_path" ]]; then
  rm -f "${deploy_path}/"*.war*
 fi


  log INFO "Copiando WAR a deployments..."
  if cp "$war_temp_path" "$deploy_path/${app_name}.war"; then
    log SUCCESS "Deploy completado correctamente"
    return 0
  else
    log ERROR "Error al copiar el WAR a $deploy_path"
    cleanup
    exit 1
  fi
}

check_deploy_status() {
  local deploy_path="$1"
  local app_name="$2"
  local container_name="$3"

  local elapsed=0
  local last_message_time=0

  log INFO "Verificando estado del deploy para $app_name en $container_name"

  while [[ $elapsed -lt $DEPLOY_TIMEOUT ]]; do
    local status_file
    status_file=$(find "$deploy_path" -type f -name "${app_name}.war.*" 2>/dev/null | grep -E "\.isdeploying$|\.deployed$|\.failed$|\.undeployed$" | head -n 1)

    if [[ "$status_file" == *".failed" ]]; then
      log ERROR "[$container_name] Deploy de $app_name falló"
      return 1
    elif [[ "$status_file" == *".undeployed" ]]; then
      log ERROR "[$container_name] Deploy de $app_name fue revertido"
      return 1
    elif [[ "$status_file" == *".deployed" ]]; then
      log SUCCESS "[$container_name] Deploy de $app_name completado correctamente."
      return 0
    elif [[ "$status_file" == *".isdeploying" ]]; then
      if ((elapsed - last_message_time >= MESSAGE_INTERVAL)); then
        log INFO "[$container_name] Estado: $app_name en despliegue... (${elapsed}s)"
        last_message_time=$elapsed
      fi
    else
      if ((elapsed - last_message_time >= MESSAGE_INTERVAL)); then
        log WARN "[$container_name] Estado desconocido. Esperando archivos de estado... (${elapsed}s)"
        last_message_time=$elapsed
      fi
    fi

    sleep $CHECK_INTERVAL
    elapsed=$((elapsed + CHECK_INTERVAL))
  done

  log ERROR "[$container_name] Timeout esperando que $app_name se despliegue correctamente."
  return 1
}

reinicia_docker() {
  local container_name="$1"
  log INFO "Reiniciando el contenedor Docker $container_name..."
  
  if docker restart "$container_name" >>"$LOG_FILE" 2>&1; then
    log SUCCESS "Contenedor $container_name reiniciado correctamente."
    return 0
  else
    log ERROR "Falló el reinicio del contenedor $container_name."
    return 1
  fi
}

# ======================== BÚSQUEDA DE CONTENEDORES ========================

listar_carpetas() {
  local carpetas=()

  echo "Buscando carpetas..."

  if [[ "$prod" == "true" ]]; then
    local patron_prod="_fx_wildfly_prod"
    while IFS= read -r dir; do
      [[ -n "$dir" ]] && carpetas+=("$dir")
    done < <(find /home /opt -type d -iname "*${patron_prod}" 2>/dev/null)
  fi

  if [[ "$teste" == "true" ]]; then
    local patron_teste="_fx_wildfly_teste"
    while IFS= read -r dir; do
      [[ -n "$dir" ]] && carpetas+=("$dir")
    done < <(find /docker /home /opt -type d -iname "*${patron_teste}" 2>/dev/null)
  fi

  if [[ ${#carpetas[@]} -eq 0 ]]; then
    log WARN "No se encontraron carpetas con los parámetros especificados."
    return 1
  fi

  local running_containers
  running_containers=$(docker ps --format "{{.Names}}" 2>/dev/null)

  local carpetas_activas=()

  echo -e "\n=============================================="
  echo -e "           Carpetas encontradas"
  echo -e "=============================================="

  for i in "${!carpetas[@]}"; do
    local carpeta="${carpetas[$i]}"
    local carpeta_nombre=$(basename "$carpeta")

    if echo "$running_containers" | grep -q "^${carpeta_nombre}$"; then
      printf "%2s) %s ✓ \n" "$((i + 1))" "$carpeta_nombre"
      carpetas_activas+=("$carpeta")
    else
      printf "%2s) %s ✗ \n" "$((i + 1))" "$carpeta_nombre"
    fi
  done

  if [[ ${#carpetas_activas[@]} -eq 0 ]]; then
    log WARN "No se encontraron contenedores activos para los parámetros especificados."
    return 1
  fi

  # Realizar deploy en cada carpeta con contenedor ACTIVO
  for carpeta in "${carpetas_activas[@]}"; do
    if [[ "$prod" == "true" && "$carpeta" == *"_fx_wildfly_prod" ]]; then
      realizar_deploy "$carpeta" "$APP_NAME"
    elif [[ "$teste" == "true" && "$carpeta" == *"_fx_wildfly_teste" ]]; then
      realizar_deploy "$carpeta" "$APP_TESTE_NAME"
    fi
  done

  return 0
}


buscar_por_nombre() {
  local nombre="$1"
  local carpetas=()
  log INFO "Buscando carpetas por nombre..."

  IFS=',' read -ra nombres_array <<< "$nombre"
  for n in "${nombres_array[@]}"; do
    n=$(echo "$n" | xargs)
    [[ -z "$n" ]] && continue

    if [[ "$exacto" == "true" ]]; then
      #  Modo exacto: busca carpeta con nombre completo
      while IFS= read -r carpeta; do
        [[ -n "$carpeta" ]] && carpetas+=("$carpeta")
      done < <(find /home /opt -type d -iname "$n" 2>/dev/null)
    else
      #  Modo parcial: concatena con sufijos según ambiente
      if [[ "$prod" == "true" ]]; then
        local patron_prod="_fx_wildfly_prod"
        while IFS= read -r carpeta; do
          [[ -n "$carpeta" ]] && carpetas+=("$carpeta")
        done < <(find /docker /home /opt -type d -iname "${n}${patron_prod}" 2>/dev/null)
      fi

      if [[ "$teste" == "true" ]]; then
        local patron_teste="_fx_wildfly_teste"
        while IFS= read -r carpeta; do
          [[ -n "$carpeta" ]] && carpetas+=("$carpeta")
        done < <(find /home /opt -type d -iname "${n}${patron_teste}" 2>/dev/null)
      fi
    fi
  done

  if [[ ${#carpetas[@]} -eq 0 ]]; then
    log WARN "No se encontraron carpetas con el nombre especificado."
    return 1
  fi

  # Filtrar solo carpetas con contenedores activos
  local carpetas_activas=()
  for carpeta in "${carpetas[@]}"; do
    local carpeta_nombre=$(basename "$carpeta")
    if validate_container_active "$carpeta_nombre" "true"; then
      carpetas_activas+=("$carpeta")
    fi
  done

  if [[ ${#carpetas_activas[@]} -eq 0 ]]; then
    log WARN "No se encontraron contenedores activos con los nombres especificados."
    return 1
  fi

  # Mostrar listado numerado de carpetas con contenedores activos
  echo -e "\n=============================================="
  echo -e "           Carpetas encontradas"
  echo -e "=============================================="
  for i in "${!carpetas_activas[@]}"; do
    local carpeta_nombre=$(basename "${carpetas_activas[$i]}")
    printf "%2s) %s ✓\n" "$((i + 1))" "$carpeta_nombre"
  done

  # Realizar deploy en cada carpeta con contenedor activo
  for carpeta in "${carpetas_activas[@]}"; do
    if [[ "$prod" == "true" && "$carpeta" == *"_fx_wildfly_prod" ]]; then
      realizar_deploy "$carpeta" "$APP_NAME"
    elif [[ "$teste" == "true" && "$carpeta" == *"_fx_wildfly_teste" ]]; then
      realizar_deploy "$carpeta" "$APP_TESTE_NAME"
    fi
  done
  
  return 0
}

realizar_deploy() {
  local carpeta="$1"
  local app_name="$2"
  local carpeta_nombre=$(basename "$carpeta")
  local deploy_path="${carpeta}/deployments"

  echo -e "\n**************************************************"
  echo "              $carpeta_nombre"
  echo -e "****************************************************"

  # Validar que el contenedor esté activo (sin log repetido)
  if ! validate_container_active "$carpeta_nombre" "true"; then
    log WARN "Saltando deploy para '$carpeta_nombre' - contenedor no activo"
    return 1
  fi

  if [[ ! -d "$deploy_path" ]]; then
    log ERROR "No se encontró la carpeta deployments en: $carpeta"
    return 1
  fi

  log INFO "Iniciando deploy de $app_name en $carpeta_nombre"
  log INFO "Ruta deployments: $deploy_path"

  if ! deploy_application "$app_name" "$deploy_path" "$carpeta_nombre"; then
    return 1
  fi
  
  if [[ "$status" == "true" ]]; then
    if ! check_deploy_status "$deploy_path" "$app_name" "$carpeta_nombre"; then
      log WARN "Deploy status check falló para $carpeta_nombre"
    fi
  fi

  if [[ "$restart" == "true" ]]; then
    if ! reinicia_docker "$carpeta_nombre"; then
      log WARN "Reinicio falló para $carpeta_nombre"
    fi
  fi
  
  return 0
}

# ======================== EJECUCIÓN PRINCIPAL ========================

# Validación de parámetros
if [[ "$version" == "false" ]]; then
  log ERROR "Debe especificar la versión con -v para ejecutar el script."
  cleanup
  exit 1
fi

# Descargar WAR base una sola vez
if [[ "$prod" == "true" || "$teste" == "true" ]]; then
  descargar_war "$version"
fi

# Preparar WARs específicos para cada ambiente
if [[ "$prod" == "true" ]]; then
  preparar_war_para_ambiente "$APP_NAME"
fi

if [[ "$teste" == "true" ]]; then
  preparar_war_para_ambiente "$APP_TESTE_NAME"
fi

if [[ "$listar" == "true" ]]; then
  if listar_carpetas; then
    exit_code=0
  else
    exit_code=1
  fi
elif [[ -n "$nombre" ]]; then
  if buscar_por_nombre "$nombre"; then
    exit_code=0
  else
    exit_code=1
  fi
else
  log ERROR "No se especificó ningún parámetro válido. Usa -l true para listar o -n <nombre> para buscar una carpeta específica."
  exit_code=1
fi

# Remover trap de error si todo salió bien
if [[ $exit_code -eq 0 ]]; then
  trap - EXIT ERR INT TERM
  cleanup
fi

exit $exit_code
