#!/usr/bin/env python3
import pymysql
import sys
import socket
from urllib.parse import urlparse

# Konfiguracja bazy danych
DB_HOST = 'localhost'
DB_USER = 'site_dc24heu_user'
DB_PASSWORD = 'C7tS9uSXDN6vqbBLpnCxj1NsS0kKJntn'
DB_NAME = 'site_dc24heu_db'

def extract_host_and_port(address):
    """Zmienia surowy adres dchub:// na czysty hostname i port do skanowania"""
    # Usunięcie nietypowych znaków, które mogą zepsuć parsowanie
    clean_addr = address.strip()
    
    # Dodanie sztucznego schematu jeśli brakuje, żeby urlparse zadziałało
    if "://" not in clean_addr:
        clean_addr = "dchub://" + clean_addr
        
    parsed = urlparse(clean_addr)
    host = parsed.hostname
    port = parsed.port
    
    # Ustawianie domyślnych portów jeśli ich nie podano
    if not port:
        if parsed.scheme in ['adcs', 'nmdcs']:
            port = 411  # Często używany też dla TLS, choć bywa różnie
        else:
            port = 411  # Standardowy port DC
            
    return host, port, parsed.scheme

def check_if_hub_is_alive(host, port):
    """Próbuje nawiązać połączenie TCP z portem huba (timeout 3 sekundy)"""
    if not host:
        return False
        
    try:
        # Tworzenie surowego gniazda TCP
        with socket.create_connection((host, port), timeout=3):
            return True
    except (socket.timeout, socket.error, socket.gaierror):
        return False

def setup_unified_table(cursor):
    """Tworzy ujednoliconą tabelę dla połączonych i sprawdzonych hubów"""
    sql = """
    CREATE TABLE IF NOT EXISTS hublist_unified_checked (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(255),
        description TEXT,
        users INT DEFAULT 0,
        address_primary VARCHAR(255),
        address_secondary VARCHAR(255),
        domain_key VARCHAR(255) UNIQUE, 
        country VARCHAR(50),
        shared BIGINT DEFAULT 0,
        status VARCHAR(20) DEFAULT 'UNCHECKED',
        last_checked TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
    """
    cursor.execute(sql)

def main():
    try:
        connection = pymysql.connect(
            host=DB_HOST, user=DB_USER, password=DB_PASSWORD,
            database=DB_NAME, charset='utf8mb4',
            cursorclass=pymysql.cursors.DictCursor
        )
    except pymysql.MySQLError as e:
        print(f"Błąd połączenia z bazą: {e}")
        sys.exit(1)

    try:
        with connection.cursor() as cursor:
            setup_unified_table(cursor)
            
            print("Pobieranie danych z tabeli TE-Home...")
            cursor.execute("SELECT * FROM hublist_tehome_net_downloaded_hubs;")
            tehome_hubs = cursor.fetchall()
            
            print("Pobieranie danych z tabeli PWiAM...")
            cursor.execute("SELECT * FROM hublist_pwiam_com_downloaded_hubs;")
            pwiam_hubs = cursor.fetchall()
            
            # Łączenie i deduplikacja
            unified_hubs = {} # Słownik, w którym kluczem będzie 'domena' huba
            all_hubs = tehome_hubs + pwiam_hubs
            
            print(f"Rozpoczynam deduplikację {len(all_hubs)} rekordów...")
            
            for hub in all_hubs:
                host, port, scheme = extract_host_and_port(hub['address'])
                if not host:
                    continue
                    
                domain_key = host.lower() # Używamy domeny (bez portu) jako klucza aby łapać duplikaty dchub/adc
                
                if domain_key not in unified_hubs:
                    # Dodajemy huba po raz pierwszy
                    unified_hubs[domain_key] = {
                        'name': hub['name'],
                        'description': hub['description'],
                        'users': hub['users'],
                        'country': hub['country'],
                        'shared': hub['shared'],
                        'address_primary': hub['address'],
                        'address_secondary': '',
                        'check_host': host,
                        'check_port': port
                    }
                else:
                    # Hub już istnieje, łączymy dane
                    existing = unified_hubs[domain_key]
                    
                    # Jeśli adres się różni (np. jeden to nmdc, drugi adcs), zapisz jako alternatywny
                    if hub['address'] != existing['address_primary']:
                        existing['address_secondary'] = hub['address']
                        
                    # Aktualizujemy nazwę, jeśli nowa jest dłuższa/lepsza, lub bierzemy max userów
                    if hub['users'] > existing['users']:
                        existing['users'] = hub['users']
                        existing['shared'] = hub['shared']
                        existing['name'] = hub['name'] # Zakładamy, że większa lista miała dokładniejszą nazwę
                        
            print(f"Po deduplikacji wytypowano {len(unified_hubs)} unikalnych hubów.")
            print("Rozpoczynam weryfikację dostępności w sieci (Pingowanie portów)... Może to chwilę potrwać.")
            
            # Zapytanie INSERT
            insert_sql = """
            INSERT INTO hublist_unified_checked 
            (name, description, users, address_primary, address_secondary, domain_key, country, shared, status)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
            ON DUPLICATE KEY UPDATE
            name=VALUES(name), users=VALUES(users), address_primary=VALUES(address_primary), 
            address_secondary=VALUES(address_secondary), status=VALUES(status);
            """
            
            online_count = 0
            offline_count = 0
            
            for domain_key, data in unified_hubs.items():
                sys.stdout.write(f"Sprawdzanie {domain_key}:{data['check_port']}... ")
                sys.stdout.flush()
                
                is_alive = check_if_hub_is_alive(data['check_host'], data['check_port'])
                status = 'ONLINE' if is_alive else 'OFFLINE'
                
                if is_alive:
                    print("ONLINE")
                    online_count += 1
                else:
                    print("OFFLINE")
                    offline_count += 1
                
                # Zapis do bazy
                cursor.execute(insert_sql, (
                    data['name'], data['description'], data['users'], 
                    data['address_primary'], data['address_secondary'], 
                    domain_key, data['country'], data['shared'], status
                ))
            
            connection.commit()
            print("\n--- PODSUMOWANIE ---")
            print(f"Znaleziono działających (ONLINE): {online_count}")
            print(f"Martwych (OFFLINE): {offline_count}")
            print("Zapisano wszystko w tabeli: hublist_unified_checked")

    except Exception as e:
        print(f"Wystąpił błąd: {e}")
    finally:
        connection.close()

if __name__ == '__main__':
    main()
