#!/usr/bin/env python3
"""
test_ami_connection.py - Test y diagnóstico de conexión AMI
Verifica la conexión con Asterisk Manager Interface
"""

import socket
import sys
import time

# Configuración AMI
AMI_HOST = '127.0.0.1'
AMI_PORT = 5038
AMI_USER = 'reportuser'
AMI_SECRET = 'tsadfgas5rSegura'
TIMEOUT = 10

class AMITester:
    def __init__(self):
        self.sock = None
        self.connected = False
    
    def connect(self):
        """Conecta al AMI"""
        try:
            print(f"Conectando a AMI en {AMI_HOST}:{AMI_PORT}...")
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.sock.settimeout(TIMEOUT)
            self.sock.connect((AMI_HOST, AMI_PORT))
            
            # Leer banner inicial
            banner = self.sock.recv(1024).decode('utf-8')
            print(f"✓ Conectado. Banner: {banner.strip()}")
            
            self.connected = True
            return True
            
        except socket.timeout:
            print("✗ Timeout conectando a AMI")
            return False
        except socket.error as e:
            print(f"✗ Error de socket: {e}")
            return False
        except Exception as e:
            print(f"✗ Error inesperado: {e}")
            return False
    
    def login(self):
        """Intenta login en AMI"""
        if not self.connected:
            print("✗ No conectado a AMI")
            return False
        
        try:
            # Enviar comando de login
            login_cmd = (
                f"Action: Login\r\n"
                f"Username: {AMI_USER}\r\n"
                f"Secret: {AMI_SECRET}\r\n"
                f"Events: off\r\n"
                f"\r\n"
            )
            
            print(f"\nEnviando login como '{AMI_USER}'...")
            self.sock.send(login_cmd.encode('utf-8'))
            
            # Leer respuesta
            response = ""
            start_time = time.time()
            while time.time() - start_time < 5:  # Timeout 5 segundos
                try:
                    data = self.sock.recv(1024).decode('utf-8')
                    if not data:
                        break
                    response += data
                    if "\r\n\r\n" in response:
                        break
                except socket.timeout:
                    break
            
            print(f"Respuesta:\n{response}")
            
            if "Success" in response:
                print("✓ Login exitoso")
                return True
            else:
                print("✗ Login fallido")
                return False
                
        except Exception as e:
            print(f"✗ Error durante login: {e}")
            return False
    
    def test_command(self, action, params=None):
        """Ejecuta un comando AMI de prueba"""
        if not self.connected:
            print("✗ No conectado a AMI")
            return False
        
        try:
            # Construir comando
            cmd = f"Action: {action}\r\n"
            if params:
                for key, value in params.items():
                    cmd += f"{key}: {value}\r\n"
            cmd += "\r\n"
            
            print(f"\nEjecutando: {action}")
            self.sock.send(cmd.encode('utf-8'))
            
            # Leer respuesta
            response = ""
            start_time = time.time()
            while time.time() - start_time < 5:
                try:
                    data = self.sock.recv(1024).decode('utf-8')
                    if not data:
                        break
                    response += data
                    if "\r\n\r\n" in response and "Response:" in response:
                        break
                except socket.timeout:
                    break
            
            print(f"Respuesta:\n{response}")
            return "Success" in response
            
        except Exception as e:
            print(f"✗ Error ejecutando comando: {e}")
            return False
    
    def disconnect(self):
        """Desconecta del AMI"""
        if self.sock:
            try:
                # Enviar logoff
                self.sock.send(b"Action: Logoff\r\n\r\n")
                time.sleep(0.5)
                self.sock.close()
                print("\n✓ Desconectado de AMI")
            except:
                pass
    
    def run_full_test(self):
        """Ejecuta test completo"""
        print("="*60)
        print("TEST DE CONEXIÓN AMI - ASTERISK MANAGER INTERFACE")
        print("="*60)
        
        # 1. Test de conectividad
        print("\n1. TEST DE CONECTIVIDAD")
        if not self.connect():
            return False
        
        # 2. Test de autenticación
        print("\n2. TEST DE AUTENTICACIÓN")
        if not self.login():
            self.disconnect()
            return False
        
        # 3. Tests de comandos
        print("\n3. TESTS DE COMANDOS")
        
        # Ping
        print("-"*40)
        self.test_command("Ping")
        
        # CoreStatus
        print("-"*40)
        self.test_command("CoreStatus")
        
        # CoreShowChannels
        print("-"*40)
        self.test_command("CoreShowChannels")
        
        # SIPpeers (o PJSIPShowEndpoints si usa PJSIP)
        print("-"*40)
        self.test_command("SIPpeers")
        
        # QueueStatus
        print("-"*40)
        self.test_command("QueueStatus")
        
        # 4. Desconectar
        self.disconnect()
        
        print("\n" + "="*60)
        print("TEST COMPLETADO")
        print("="*60)
        
        return True

def check_ami_config():
    """Verifica configuración AMI en manager.conf"""
    print("\nVERIFICANDO CONFIGURACIÓN AMI:")
    print("-"*40)
    
    try:
        with open('/etc/asterisk/manager.conf', 'r') as f:
            content = f.read()
            
            # Verificar si AMI está habilitado
            if 'enabled = yes' in content or 'enabled=yes' in content:
                print("✓ AMI está habilitado")
            else:
                print("✗ AMI NO está habilitado")
            
            # Verificar puerto
            if f'port = {AMI_PORT}' in content or f'port={AMI_PORT}' in content:
                print(f"✓ Puerto configurado: {AMI_PORT}")
            else:
                print(f"✗ Puerto no coincide con {AMI_PORT}")
            
            # Verificar usuario
            if f'[{AMI_USER}]' in content:
                print(f"✓ Usuario '{AMI_USER}' existe")
            else:
                print(f"✗ Usuario '{AMI_USER}' NO encontrado")
                
    except Exception as e:
        print(f"✗ No se pudo leer manager.conf: {e}")

def main():
    """Función principal"""
    import argparse
    
    parser = argparse.ArgumentParser(description='Test de conexión AMI')
    parser.add_argument('-q', '--quick', action='store_true',
                       help='Test rápido (solo conectividad)')
    parser.add_argument('-c', '--check-config', action='store_true',
                       help='Verificar configuración en manager.conf')
    
    args = parser.parse_args()
    
    if args.check_config:
        check_ami_config()
        return
    
    tester = AMITester()
    
    if args.quick:
        # Test rápido
        print("TEST RÁPIDO DE CONECTIVIDAD AMI")
        print("-"*40)
        if tester.connect():
            print("✓ Conexión exitosa")
            if tester.login():
                print("✓ Autenticación exitosa")
            tester.disconnect()
        else:
            print("✗ No se pudo conectar")
            sys.exit(1)
    else:
        # Test completo
        if not tester.run_full_test():
            sys.exit(1)

if __name__ == "__main__":
    main()