# -*- coding: utf-8 -*-
import re, mysql.connector, sys, os, time
from netmiko import ConnectHandler
import concurrent.futures

# Forzar a Python a imprimir en pantalla al instante sin guardar en cach
sys.stdout.reconfigure(line_buffering=True)

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DB_PHP_PATH = '/var/www/html/db.php'

import os
import os
import os
import os
def __get_db_config_dynamic():
    cfg = {'host': '127.0.0.1', 'user': 'saas_admin', 'password': 'AdminSaaS2026!', 'database': 'adminolt_db'}
    for db_path in ['/var/www/html/db.php', '/root/Workspace360_paquete/db.php']:
        try:
            if os.path.exists(db_path):
                with open(db_path, 'r', encoding='utf-8', errors='ignore') as f:
                    for line in f:
                        line = line.strip()
                        if line.startswith('$host') and '=' in line:
                            part = line.split("'")[1] if "'" in line else line.split('"')[1]
                            cfg['host'] = '127.0.0.1' if part == 'localhost' else part
                        elif line.startswith('$user') and '=' in line:
                            cfg['user'] = line.split("'")[1] if "'" in line else line.split('"')[1]
                        elif line.startswith('$pass') and '=' in line:
                            cfg['password'] = line.split("'")[1] if "'" in line else line.split('"')[1]
                        elif line.startswith('$db') and '=' in line:
                            cfg['database'] = line.split("'")[1] if "'" in line else line.split('"')[1]
                break
        except: pass
    return cfg
DB_CONFIG = __get_db_config_dynamic()

def procesar_lote_ssh(olt, onus_lote):
    device = {
        'device_type': 'huawei_smartax',
        'host': olt['ip'],
        'username': olt['user'],
        'password': olt['pass'],
        'port': olt['port'],
        'global_delay_factor': 0.5,
    }
    
    exitos = 0
    try:
        print(f"-> [SSH] Conectando a OLT {olt['ip']}...")
        conn = ConnectHandler(**device)
        conn.enable()
        conn.send_command("undo smart", delay_factor=1)
        conn.send_command("scroll 512", delay_factor=1)
        
        db = mysql.connector.connect(**DB_CONFIG)
        cursor = db.cursor()
        
        for onu in onus_lote:
            id_bd, f, s, p, oid = onu
            out_wan = conn.send_command(f"display ont wan-info {f}/{s} {p} {oid}", read_timeout=15)
            
            ip_match = re.search(r'(?:IP address|IPv4 address)\s*:\s*([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})', out_wan, re.IGNORECASE)
            mode_match = re.search(r'Connection type\s*:\s*([A-Za-z0-9_-]+)', out_wan, re.IGNORECASE)
            vlan_match = re.search(r'VLAN ID\s*:\s*(\d+)', out_wan, re.IGNORECASE)
            user_match = re.search(r'User name\s*:\s*([^\r\n]+)', out_wan, re.IGNORECASE)

            ip_val = ip_match.group(1) if ip_match and ip_match.group(1) not in ["0.0.0.0", "127.0.0.1"] else "---"
            mode_val = mode_match.group(1) if mode_match else "---"
            vlan_val = vlan_match.group(1) if vlan_match else "---"
            user_val = user_match.group(1).strip() if user_match else "---"
            
            if ip_val != "---" or mode_val != "---":
                cursor.execute("""
                    UPDATE onus 
                    SET wan_ip=%s, wan_mode=%s, wan_vlan=%s, pppoe_user=%s 
                    WHERE id=%s
                """, (ip_val, mode_val, vlan_val, user_val, id_bd))
                db.commit()
                exitos += 1
                print(f"  [+] {f}/{s}/{p}:{oid} guardado -> IP: {ip_val} | PPPoE: {user_val}")
            else:
                print(f"  [-] {f}/{s}/{p}:{oid} ignorado -> Sin info en la OLT")
                
        conn.disconnect()
        cursor.close()
        db.close()
        print(f"<- [SSH] Lote completado en {olt['ip']}.")
        return exitos
    except Exception as e:
        print(f"[ERROR SSH] Falla en {olt['ip']}: {e}")
        return 0

if __name__ == "__main__":
    start_time = time.time()
    print("=== INICIANDO EXTRACCION MASIVA SSH (IP, VLAN, PPPoE) ===")
    db = mysql.connector.connect(**DB_CONFIG)
    cursor = db.cursor(dictionary=True)
    
    cursor.execute("SELECT id, ip_address, ssh_user, ssh_pass, ssh_port, nombre FROM olts")
    olts = cursor.fetchall()
    
    tareas = []
    total_onus = 0
    
    for olt in olts:
        cursor.execute("SELECT id, frame, slot, port, onu_id FROM onus WHERE olt_id=%s AND estado_actual='ONLINE'", (olt['id'],))
        onus = cursor.fetchall()
        total_onus += len(onus)
        
        lote_size = 30
        for i in range(0, len(onus), lote_size):
            lote = [(o['id'], o['frame'], o['slot'], o['port'], o['onu_id']) for o in onus[i:i+lote_size]]
            olt_data = {'ip': olt['ip_address'], 'user': olt['ssh_user'], 'pass': olt['ssh_pass'], 'port': olt['ssh_port'] or 22}
            tareas.append((olt_data, lote))
            
    db.close()
    
    print(f"-> Se analizaran {total_onus} ONUs ONLINE en {len(tareas)} bloques SSH.")
    
    total_exitos = 0
    with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
        resultados = [executor.submit(procesar_lote_ssh, tarea[0], tarea[1]) for tarea in tareas]
        for f in concurrent.futures.as_completed(resultados):
            total_exitos += f.result()
            
    tiempo_total = time.time() - start_time
    print(f"=== FIN: {total_exitos} ONUs actualizadas correctamente en {tiempo_total:.2f} segundos ===")
