import boto3
import paramiko
import os


class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKCYAN = '\033[96m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'
    BOLD = '\033[1m'
    UNDERLINE = '\033[4m'


def sincronizar_servidor_git(server_name, key_file, ip_address, comando_git):
    print(f"Conectando con: {server_name} - {ip_address}")
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.WarningPolicy())
    # Valido el privatekey
    privkey = paramiko.RSAKey.from_private_key_file(key_file)
    
    deploy_success = False
    
    try:
        ssh.connect(hostname=ip_address, username="ubuntu", pkey=privkey)
        print("Conexion establecida")
        
        # Ejecutar git pull
        print(f"  → Ejecutando: {comando_git}")
        _, stdout, stderr = ssh.exec_command(comando_git)
        stdout_content = stdout.read().decode('utf-8')
        stderr_content = stderr.read().decode('utf-8')
        
        print('stdout:', stdout_content)
        if stderr_content:
            print('stderr:', stderr_content)
        
        # Verificar si git pull fue exitoso
        git_success, git_msg = verificar_git_pull_exitoso(stdout_content, stderr_content)
        
        if git_success:
            print(f"  {bcolors.OKGREEN}✓ Git pull exitoso: {git_msg}{bcolors.ENDC}")
            print(f"  {bcolors.OKGREEN}✅ Deploy completado exitosamente en {server_name}{bcolors.ENDC}")
            deploy_success = True
        else:
            print(f"  {bcolors.FAIL}❌ Git pull falló: {git_msg}{bcolors.ENDC}")
            
        ssh.close()
        return deploy_success, git_msg
        
    except Exception as e:
        print(f"{bcolors.FAIL}❌ Error en la conexión: {e}{bcolors.ENDC}")
        if ssh:
            ssh.close()
        return False, f"Connection error: {e}"


def get_instance_name(tags):
    """
    Obtiene el valor del tag 'Name' de una lista de tags de una instancia EC2.

    Args:
        tags (list): Lista de tags de la instancia en formato [{'Key': '...', 'Value': '...'}, ...]

    Returns:
        str: El valor del tag 'Name' si existe, o None si no está presente.
    """
    if tags:
        for tag in tags:
            if tag['Key'] == 'Name':
                return tag['Value']
    return None


def verificar_git_pull_exitoso(stdout_content, stderr_content):
    """Verifica si git pull fue exitoso"""
    if "Already up to date" in stdout_content or "Fast-forward" in stdout_content:
        return True, "Success - Repository updated"
    if "up-to-date" in stdout_content.lower():
        return True, "Success - Already up to date"
    if any(error in stderr_content.lower() for error in ["error:", "fatal:", "permission denied"]):
        return False, f"Git Error: {stderr_content.strip()}"
    if stdout_content.strip() == "":
        return False, "No output from git pull"
    return True, "Git pull completed"




rutaDirectorioPem = "/home/ubuntu/pem/"
print("Iniciando Conexion a AWS - Listando Instancias Disponibles")
# Especificar región por defecto si no está en variables de entorno
aws_region = os.getenv('AWS_DEFAULT_REGION', 'us-east-2')
print(f"🌍 Usando región AWS: {aws_region}")
ec2 = boto3.resource('ec2', region_name=aws_region)
contador = 0
for instance in ec2.instances.all():
    
    sincronizar_git = 0
    instance_name = get_instance_name(instance.tags)
    if not instance_name or not any(word in instance_name.lower() for word in ["server0", "balanceador"]):
        continue
    
    #valido el estado de la maquina
    instance_status = instance.state["Name"]
    if instance_status != "running":
        continue
    
    #imprimo el nombre de la maquina
    print(f"{bcolors.OKCYAN}=> Conectando con {instance.id}{bcolors.ENDC} ({instance_name})")
    
    #imprimo el nombre de la llave de conexion
    instance_key_name = instance.key_name
    #print(instance_key_name)
    
    #inicia la rutina de sincronziacion para cada servidor
    print(f"{bcolors.OKGREEN}=> Sincronizando con {instance_name} - {instance.public_ip_address}  - Status {instance_status}{bcolors.ENDC}")
    if instance_name and any(word in instance_name.lower() for word in ["server0"]):
        comando_git = "cd /var/www/html/medifolios;git pull origin master;"
        pem = rutaDirectorioPem+"server0medifolios_v2.pem"
    if instance_name and any(word in instance_name.lower() for word in ["balanceador"]):
        comando_git = "cd /var/www/html;git pull origin master;"
        pem = rutaDirectorioPem+"balanceador_carga.pem"
          
    # Validar existencia del archivo PEM
    if not os.path.exists(pem):
        print(f"{bcolors.FAIL}=> Archivo PEM no encontrado: {pem}{bcolors.ENDC}")
        continue
        
    # Ejecuto la sincronizacion con el directorio
    success, message = sincronizar_servidor_git(instance_name, pem, instance.private_ip_address, comando_git)
    
    if success:
        print(f"{bcolors.OKGREEN}🎉 {instance_name} sincronizado exitosamente{bcolors.ENDC}")
        contador += 1
    else:
        print(f"{bcolors.FAIL}💥 Error en {instance_name}: {message}{bcolors.ENDC}")
    
    print("= = = = = = = = = =")
print(f"\n{bcolors.HEADER}📊 RESUMEN FINAL DE SINCRONIZACIÓN{bcolors.ENDC}")
print(f"🎯 Servidores sincronizados exitosamente: {contador}")
if contador > 0:
    print(f"{bcolors.OKGREEN}✅ Sincronización completada{bcolors.ENDC}")
else:
    print(f"{bcolors.FAIL}❌ No se logró sincronizar ningún servidor{bcolors.ENDC}")
    
print("Finaliza Sincronizacion con Servidores")



