#!/bin/bash

# Configuración inicial
readonly LOG_DIR="/var/deploy_logs"
readonly TEMP_DIR="/tmp/deploy_temp"
readonly BASE_URL="http://maestro.datapar.com/artifactory/datapar/APIDFE/APP"
readonly SCRIPT_URL="https://gist.githubusercontent.com/Rose-mb/e5986be632ea0e307c4d8cdcddec2a47/raw/458e02c172c0885aefb843696cdf1c9ad665e32f/script_compatibiliza_multi_tenant_apidfe.sh"

# Aplicaciones
readonly APP_NAME="apidfe"
readonly APP_NAME_FRONT="apidfe-dash"

# Variables globales
CUSTOM=false
USER=false
PASS=false
HOST=false
NOMBRE=""
PROD=false
TESTE=false
LISTAR=false
VERSION=""
EXACTO=false

# Configurar logging
setup_logging() {
    find "$LOG_DIR" -type f -name "deploy_apidfe_*.log" -delete 2>/dev/null
    mkdir -p "$LOG_DIR"
    readonly LOG_FILE="$LOG_DIR/deploy_apidfe_$(date +%Y-%m-%d).log"
}

# Función de logging
log() {
    echo -e "$(date +'%Y-%m-%d %H:%M:%S') - $1: $2" | tee -a "$LOG_FILE"
}

cleanup() {
    log INFO "Ejecutando limpieza final..."

    # Limpiar directorio temporal
    [[ -d "$TEMP_DIR" ]] && rm -rf "$TEMP_DIR" 2>/dev/null

    # Limpiar archivos WAR locales
    [[ -f "$APP_NAME.war" ]] && rm -f "$APP_NAME.war"
    [[ -f "$APP_NAME_FRONT.war" ]] && rm -f "$APP_NAME_FRONT.war"

    # Limpiar cualquier script auxiliar descargado en el directorio actual
    rm -f script_compatibiliza_multi_tenant_apidfe.sh 2>/dev/null

    # Limpiar scripts auxiliares en /home (por si se copiaron ahí)
    find /root -type f -name "script_apidfe_docker_*" -exec rm -f {} \; 2>/dev/null

    log INFO "Limpieza completada"
}

# Trap para manejar tanto éxito como error
trap 'cleanup' EXIT

# Función para verificar si un contenedor Docker está activo
get_running_containers() {
    docker ps --format "{{.Names}}" 2>/dev/null
}

# Parsear argumentos
parse_arguments() {
    while getopts "v:c:u:s:h:n:l:p:t:e:" flag; do
        case "${flag}" in
            v) VERSION=${OPTARG} ;;
            c) CUSTOM=${OPTARG} ;;
            u) USER=${OPTARG} ;;
            s) PASS=${OPTARG} ;;
            h) HOST=${OPTARG} ;;
            n) NOMBRE=${OPTARG} ;;
            l) LISTAR=${OPTARG} ;;
            p) PROD=${OPTARG} ;;
            t) TESTE=${OPTARG} ;;
            e) EXACTO=${OPTARG} ;;
        esac
    done
    
    # Establecer valores por defecto
    CUSTOM="${CUSTOM:-false}"
    LISTAR="${LISTAR:-false}"
    USER="${USER:-false}"
    PASS="${PASS:-false}"
    HOST="${HOST:-false}"
    PROD="${PROD:-false}"
    TESTE="${TESTE:-false}"
    EXACTO="${EXACTO:-false}"
}

# Mostrar banner
show_banner() {
    clear
    cat <<"EOF"
 /$$$$$$$$  /$$$$$$   /$$$$$$  /$$$$$$$$ /$$   /$$ /$$$$$$$   /$$$$$$          /$$$$$$$$
| $$_____/ /$$__  $$ /$$__  $$|__  $$__/| $$  | $$| $$__  $$ /$$__  $$        | $$_____/
| $$      | $$  \ $$| $$  \__/   | $$   | $$  | $$| $$  \ $$| $$  \ $$        | $$      
| $$$$$   | $$$$$$$$| $$         | $$   | $$  | $$| $$$$$$$/| $$$$$$$$ /$$$$$$| $$$$$   
| $$__/   | $$__  $$| $$         | $$   | $$  | $$| $$__  $$| $$__  $$|______/| $$__/   
| $$      | $$  | $$| $$    $$   | $$   | $$  | $$| $$  \ $$| $$  | $$        | $$      
| $$      | $$  | $$|  $$$$$$/   | $$   |  $$$$$$/| $$  | $$| $$  | $$        | $$$$$$$$
|__/      |__/  |__/ \______/    |__/    \______/ |__/  |__/|__/  |__/        |________/      

EOF
}

# Validar parámetros requeridos
validate_parameters() {
    # Si NO es búsqueda exacta, entonces se requiere -p o -t
    if [[ "$EXACTO" != "true" && "$PROD" == false && "$TESTE" == false ]]; then
        log ERROR "Debe especificar al menos un entorno: -p para producción o -t para teste"
        return 1
    fi

    if [[ -z "$VERSION" ]]; then
        log ERROR "Debe especificar una versión con -v"
        return 1
    fi

    return 0
}

# Descargar WAR 
download_war() {
    local url="$1"
    local dest_file="$2"
    local description="$3"
    
    log INFO "Descargando $description a: $dest_file"
    
    # Eliminar archivo existente
    [[ -f "$dest_file" ]] && rm -f "$dest_file"
    
    wget --no-check-certificate --progress=bar:force -O "$dest_file" "$url" 2>&1 | tee -a "$LOG_FILE" || {
        log ERROR "Fallo la descarga del $description"
        return 1
    }
    
    if [[ -f "$dest_file" ]]; then
        log SUCCESS "Descarga exitosa de $description"
        return 0
    else
        log ERROR "Error: archivo $description no se creó correctamente"
        return 1
    fi
}

# Función para descargar WAR backend
descargar_war_backend() {
    local war_temp_path="$TEMP_DIR/$APP_NAME.war"
    
    download_war \
        "$BASE_URL/$APP_NAME/$VERSION/$APP_NAME-$VERSION.war" \
        "$war_temp_path" \
        "WAR backend" || return 1
    
    return 0
}

# Función para descargar WAR frontend
descargar_war_frontend() {
    local war_temp_path="$TEMP_DIR/$APP_NAME_FRONT.war"
    
    download_war \
        "$BASE_URL/$APP_NAME_FRONT/$VERSION/$APP_NAME_FRONT-$VERSION.war" \
        "$war_temp_path" \
        "WAR frontend" || return 1
    
    return 0
}

# Deploy del frontend
deploy_front() {
    local war_temp_path="$TEMP_DIR/$APP_NAME_FRONT.war"
    
    if [[ ! -f "$war_temp_path" ]]; then
        log ERROR "El WAR del frontend no está disponible en $war_temp_path"
        return 1
    fi

    log INFO "Desplegando frontend..."
    rm -rf "$APP_NAME_FRONT"
    
    cp "$war_temp_path" "$APP_NAME_FRONT.war" || {
        log ERROR "Error al copiar WAR frontend"
        return 1
    }
    
    unzip -q "$APP_NAME_FRONT.war" || {
        log ERROR "Error al extraer WAR frontend"
        return 1
    }
    
    rm -f "$APP_NAME_FRONT.war"
    log SUCCESS "Actualización del frontend completa"
    return 0
}

# Deploy del backend
deploy_back() {
    local war_temp_path="$TEMP_DIR/$APP_NAME.war"
    
    if [[ ! -f "$war_temp_path" ]]; then
        log ERROR "El WAR del backend no está disponible en $war_temp_path"
        return 1
    fi

    log INFO "Desplegando backend..."
    cp "$war_temp_path" "$APP_NAME.war" || {
        log ERROR "Error al copiar WAR backend"
        return 1
    }
    
    log SUCCESS "Actualización del backend completa"
    return 0
}

# Buscar contenedor MySQL asociado
buscar_mysql() {
    local base="$1"
    local entorno="$2"
    local mysql_contenedor="${base}_mysql_${entorno}"
    
    if find /home /opt -maxdepth 4 -type d -iname "$mysql_contenedor" 2>/dev/null | grep -q .; then
        echo "$mysql_contenedor"
    else
        echo "No se encontró carpeta MySQL"
    fi
}

# Función de compatibilización
compatibiliza() {
    local mysql_contenedor="$1"
    
    log INFO "Ejecutando compatibilización en MySQL ($mysql_contenedor)..."

    # Verificar que el contenedor esté activo
    if ! docker ps --format "table {{.Names}}" | grep -q "^${mysql_contenedor}$"; then
        log ERROR "Contenedor MySQL '$mysql_contenedor' no está activo"
        return 1
    fi

    # Obtener IP del contenedor
    local mysql_ip=$(docker inspect -f '{{(index (index .NetworkSettings.Ports "3306/tcp") 0).HostIp}}' "$mysql_contenedor" 2>/dev/null)
    
    if [[ -z "$mysql_ip" ]]; then
        log ERROR "No se pudo obtener la IP de mapeo para MySQL"
        return 1
    fi

    # Descargar el script de compatibilización
    log INFO "Descargando script de compatibilización..."
    wget --no-check-certificate -q "$SCRIPT_URL" -O "script_compatibiliza_multi_tenant_apidfe.sh" || {
        log ERROR "Error al descargar script de compatibilización"
        return 1
    }
    
    chmod +x script_compatibiliza_multi_tenant_apidfe.sh

    # Copiar script al contenedor MySQL
    docker cp script_compatibiliza_multi_tenant_apidfe.sh "$mysql_contenedor:/tmp/script_compatibiliza.sh" >/dev/null 2>&1 || {
        log ERROR "Error al copiar script al contenedor MySQL"
        return 1
    }
    
    docker exec "$mysql_contenedor" chmod +x /tmp/script_compatibiliza.sh

    # Ejecutar el script dentro del contenedor MySQL
    if [[ "$USER" != "false" && "$PASS" != "false" && "$HOST" != "false" ]]; then
        log INFO "Usando credenciales proporcionadas..."
        docker exec "$mysql_contenedor" /bin/bash -c "/tmp/script_compatibiliza.sh '$USER' '$PASS' '$HOST'" || {
            log ERROR "Error al ejecutar compatibilización con credenciales personalizadas"
            return 1
        }
    else
        log INFO "Usando credenciales predeterminadas..."
        docker exec "$mysql_contenedor" /bin/bash -c "/tmp/script_compatibiliza.sh 'root' 'Mysql42.$' '$mysql_ip'" || {
            log ERROR "Error al ejecutar compatibilización con credenciales predeterminadas"
            return 1
        }
    fi

    # Limpieza
    rm -f script_compatibiliza_multi_tenant_apidfe.sh
    docker exec "$mysql_contenedor" rm -f /tmp/script_compatibiliza.sh >/dev/null 2>&1

    log SUCCESS "Compatibilización completada en el contenedor MySQL: $mysql_contenedor"
    return 0
}

# Ejecutar deploy en un entorno específico
ejecutar_deploy_entorno() {
    local ruta="$1"
    local entorno="$2"
    local container_name=$(basename "$ruta")
    
    log INFO "Iniciando deploy ($entorno)..."
    local tomcat_webapps_dir="$ruta/tomcat/webapps"
    log INFO "Ruta deployments: $tomcat_webapps_dir"

    if [[ ! -d "$tomcat_webapps_dir" ]]; then
        log WARN "No se encontró la carpeta tomcat/webapps en: $ruta"
        return 1
    fi

    log INFO "Borrando archivos existentes en $tomcat_webapps_dir..."
    (
        cd "$tomcat_webapps_dir" || {
            log ERROR "No se pudo acceder a $tomcat_webapps_dir"
            return 1
        }
        
        # Limpiar archivos existentes
        find . -maxdepth 1 \( -name "*apidfe.war*" -o -name "*script*" \) -exec rm -rf "{}" \;
        
        # Ejecutar deploys
        deploy_front || return 1
        deploy_back || return 1
    ) || return 1

    return 0
}

# Función para buscar y procesar carpetas
buscar_carpetas() {
    local patron_busqueda="$1"
    local entornos=()
    
    [[ "$PROD" == "true" ]] && entornos+=("prod")
    [[ "$TESTE" == "true" ]] && entornos+=("teste")

    declare -A carpetas_por_base
    declare -A mysql_por_base

    local running_containers
    running_containers=$(get_running_containers)

    if [[ "$EXACTO" == "true" ]]; then
        # Buscar carpeta exacta (nombre completo)
        while IFS= read -r dir; do
            [[ -z "$dir" ]] && continue
            local carpeta=$(basename "$dir")

            # Extraer entorno del nombre completo
            if [[ "$carpeta" == *_api_tomcat_prod ]]; then
                entorno_detectado="prod"
                base="${carpeta/_api_tomcat_prod/}"
            elif [[ "$carpeta" == *_api_tomcat_teste ]]; then
                entorno_detectado="teste"
                base="${carpeta/_api_tomcat_teste/}"
            else
                continue  # Saltar si no coincide con el patrón esperado
            fi

            carpetas_por_base["$base"]="$dir|$entorno_detectado"

            # Buscar contenedor MySQL por nombre en lugar de carpeta
            if [[ "$CUSTOM" == "true" ]]; then
                local mysql_name="${base}_mysql_${entorno_detectado}"
                if echo "$running_containers" | grep -q "^${mysql_name}$"; then
                    mysql_por_base["$base|$entorno_detectado"]="$mysql_name"
                else
                    mysql_por_base["$base|$entorno_detectado"]="No se encontró contenedor MySQL"
                fi
            fi
        done < <(find /home /opt /docker -type d -iname "$patron_busqueda" 2>/dev/null)
    else
        # Buscar por patrón + sufijo
        for entorno in "${entornos[@]}"; do
            while IFS= read -r dir; do
                [[ -z "$dir" ]] && continue
                local carpeta=$(basename "$dir")
                local base="${carpeta/_api_tomcat_${entorno}/}"
                carpetas_por_base["$base"]+="$dir|$entorno;"

                if [[ "$CUSTOM" == "true" ]]; then
                    local mysql_name="${base}_mysql_${entorno}"
                    if echo "$running_containers" | grep -q "^${mysql_name}$"; then
                        mysql_por_base["$base|$entorno"]="$mysql_name"
                    else
                        mysql_por_base["$base|$entorno"]="No se encontró contenedor MySQL"
                    fi
                fi
            done < <(find /home /opt /docker -type d -iname "${patron_busqueda}_api_tomcat_${entorno}" 2>/dev/null)
        done
    fi

    if [[ ${#carpetas_por_base[@]} -eq 0 ]]; then
        log ERROR "No se encontraron carpetas para el patrón especificado"
        return 1
    fi

    mostrar_resumen_carpetas carpetas_por_base mysql_por_base "$running_containers"
    ejecutar_deploys carpetas_por_base mysql_por_base entornos "$running_containers"

    return 0
}

# Mostrar resumen de carpetas encontradas
mostrar_resumen_carpetas() {
    local -n carpetas_ref=$1
    local -n mysql_ref=$2
    local running_containers="$3"

    echo
    echo "================================================="
    echo "        Resumen de carpetas encontradas:"
    echo "================================================="

    for base in $(printf "%s\n" "${!carpetas_ref[@]}" | sort); do
        IFS=';' read -ra entradas <<<"${carpetas_ref[$base]}"
        for entrada in "${entradas[@]}"; do
            [[ -z "$entrada" ]] && continue
            IFS='|' read -r ruta entorno <<<"$entrada"
            local carpeta=$(basename "$ruta")

            if echo "$running_containers" | grep -q "^${carpeta}$"; then
                estado="✓"
            else
                estado="✗ "
            fi

            if [[ "$CUSTOM" == "true" ]]; then
               local clave_mysql="${base}|${entorno}"
               local mysql_name="${mysql_ref[$clave_mysql]:-No encontrado}"

              if [[ "$mysql_name" == "No se encontró contenedor MySQL" || -z "$mysql_name" ]]; then
                 mysql_estado="✗"
              elif echo "$running_containers" | grep -q "^${mysql_name}$"; then
                 mysql_estado="✓"
              else
                 mysql_estado="✗"
               fi
               printf "%-37s→ MySQL: %s %s\n" "${carpeta} ${estado}" "$mysql_name" "$mysql_estado"
            else
               printf "%-37s\n" "${carpeta} ${estado}"
            fi
        done
    done
    echo
}

# Ejecutar todos los deploys
ejecutar_deploys() {
    local -n carpetas_ref=$1
    local -n mysql_ref=$2
    local -n entornos_ref=$3
    local running_containers="$4"

    for base in $(printf "%s\n" "${!carpetas_ref[@]}" | sort); do
        echo -e "\n*******************************************"
        echo "                 $base"
        echo "*******************************************"

        IFS=';' read -ra entradas <<<"${carpetas_ref[$base]}"
        for entrada in "${entradas[@]}"; do
            [[ -z "$entrada" ]] && continue
            IFS='|' read -r ruta entorno <<<"$entrada"
            local carpeta=$(basename "$ruta")

            if echo "$running_containers" | grep -q "^${carpeta}$"; then
                ejecutar_deploy_entorno "$ruta" "$entorno" || return 1
            else
                log WARN "Saltando deploy para '$carpeta' - contenedor no activo"
            fi
        done

        if [[ "$CUSTOM" == "true" ]]; then
            for entorno in "${entornos_ref[@]}"; do
                local clave_mysql="${base}|${entorno}"
                local mysql_contenedor="${mysql_ref[$clave_mysql]}"
                
                if [[ -n "$mysql_contenedor" && "$mysql_contenedor" != "No se encontró contenedor MySQL" ]]; then
                   if echo "$running_containers" | grep -q "^${mysql_contenedor}$"; then
                     compatibiliza "$mysql_contenedor" || return 1
                   else
                      log WARN "MySQL '$mysql_contenedor' no está activo. Saltando compatibilización."
                    fi
               else
                  log WARN "No se ejecutó compatibilización para $base/$entorno: contenedor MySQL no encontrado"
               fi

            done
        fi
    done

    return 0
}

# Listar todas las carpetas
listar_carpetas() {
    log INFO "Buscando todas las carpetas disponibles..."
    buscar_carpetas "*"
}

# Buscar por nombres específicos
buscar_por_nombres() {
    IFS=',' read -ra nombres <<< "$NOMBRE"
    log INFO "Buscando carpetas por nombres especificados..."
    
    for nom in "${nombres[@]}"; do
        log INFO "Procesando: $nom"
        if [[ "$EXACTO" == "true" ]]; then
            buscar_carpetas "$nom" || return 1
        else
            buscar_carpetas "*${nom}" || return 1
        fi
    done
    
    return 0
}

# Función principal
main() {
    setup_logging
    parse_arguments "$@"
    show_banner

    # Validar parámetros
    validate_parameters || exit 1

    # Preparar directorio temporal y descargar archivos
    rm -rf "$TEMP_DIR"
    mkdir -p "$TEMP_DIR" || {
        log ERROR "Error al crear directorio temporal"
        exit 1
    }

    # Descargar archivos necesarios (siempre descarga)
    descargar_war_backend || {
        log ERROR "Error en la descarga del WAR backend"
        exit 1
    }
    
    descargar_war_frontend || {
        log ERROR "Error en la descarga del WAR frontend"
        exit 1
    }

    # Ejecutar según el modo especificado
    if [[ -n "$NOMBRE" ]]; then
        buscar_por_nombres || {
            log ERROR "Error en búsqueda por nombres"
            exit 1
        }
    elif [[ "$LISTAR" == "true" ]]; then
        listar_carpetas || {
            log ERROR "Error al listar carpetas"
            exit 1
        }
    fi
   
    log SUCCESS "Deploy APIDFE completado exitosamente"
    exit 0
}

# Ejecutar script principal
main "$@"