#!/usr/bin/env python3
"""
Validador de Domínios .com.br
- DNS lookup + HTTP HEAD
- 100 conexões concorrentes
- Salva resultados em tempo real
"""

import asyncio
import aiohttp
import socket
import time
import sys
from pathlib import Path
from datetime import datetime

# Configuração
INPUT_FILE = "/Users/neog/DomainChecker/dominios-com-br-VALIDOS.txt"
OUTPUT_DIR = "/Users/neog/DomainChecker/resultados"
CONCURRENT = 100  # conexões simultâneas
TIMEOUT = 5  # segundos

# Contadores
stats = {
    "total": 0,
    "processed": 0,
    "online": 0,
    "offline": 0,
    "dns_failed": 0,
    "timeout": 0,
    "error": 0,
    "start_time": None
}

async def check_dns(domain: str) -> bool:
    """Verifica se o domínio resolve via DNS"""
    try:
        loop = asyncio.get_event_loop()
        await asyncio.wait_for(
            loop.getaddrinfo(domain, None),
            timeout=3
        )
        return True
    except:
        return False

async def check_http(session: aiohttp.ClientSession, domain: str) -> dict:
    """Faz HTTP HEAD request"""
    for scheme in ["https", "http"]:
        url = f"{scheme}://{domain}"
        try:
            async with session.head(url, timeout=aiohttp.ClientTimeout(total=TIMEOUT), allow_redirects=True) as resp:
                return {
                    "status": "online",
                    "http_code": resp.status,
                    "scheme": scheme
                }
        except asyncio.TimeoutError:
            continue
        except:
            continue
    return {"status": "offline", "http_code": 0}

async def validate_domain(session: aiohttp.ClientSession, domain: str, online_file, offline_file) -> str:
    """Valida um domínio completo"""
    global stats

    # 1. DNS Check
    dns_ok = await check_dns(domain)
    if not dns_ok:
        stats["dns_failed"] += 1
        stats["processed"] += 1
        return "dns_failed"

    # 2. HTTP Check
    result = await check_http(session, domain)

    if result["status"] == "online":
        stats["online"] += 1
        online_file.write(f"{domain}\n")
        online_file.flush()
    else:
        stats["offline"] += 1
        offline_file.write(f"{domain}\n")
        offline_file.flush()

    stats["processed"] += 1
    return result["status"]

def print_progress():
    """Mostra progresso"""
    elapsed = time.time() - stats["start_time"]
    rate = stats["processed"] / elapsed if elapsed > 0 else 0
    remaining = (stats["total"] - stats["processed"]) / rate if rate > 0 else 0

    pct = (stats["processed"] / stats["total"] * 100) if stats["total"] > 0 else 0

    print(f"\r⏳ {stats['processed']:,}/{stats['total']:,} ({pct:.1f}%) | "
          f"✅ {stats['online']:,} | ❌ {stats['offline']:,} | 🔍 DNS fail: {stats['dns_failed']:,} | "
          f"📊 {rate:.0f}/s | ETA: {remaining/60:.1f}min", end="", flush=True)

async def worker(queue: asyncio.Queue, session: aiohttp.ClientSession, online_file, offline_file):
    """Worker que processa domínios da fila"""
    while True:
        domain = await queue.get()
        if domain is None:
            break
        try:
            await validate_domain(session, domain, online_file, offline_file)
        except Exception as e:
            stats["error"] += 1
            stats["processed"] += 1
        queue.task_done()

async def main():
    global stats

    print("=" * 60)
    print("🇧🇷 VALIDADOR DE DOMÍNIOS .COM.BR")
    print("=" * 60)

    # Criar diretório de saída
    Path(OUTPUT_DIR).mkdir(exist_ok=True)

    # Carregar domínios
    print(f"\n📂 Carregando domínios de: {INPUT_FILE}")
    with open(INPUT_FILE, "r") as f:
        domains = [line.strip() for line in f if line.strip()]

    stats["total"] = len(domains)
    print(f"📊 Total de domínios: {stats['total']:,}")

    # Arquivos de saída
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    online_path = f"{OUTPUT_DIR}/online_{timestamp}.txt"
    offline_path = f"{OUTPUT_DIR}/offline_{timestamp}.txt"

    print(f"\n📁 Salvando resultados em:")
    print(f"   ✅ {online_path}")
    print(f"   ❌ {offline_path}")

    print(f"\n🚀 Iniciando validação com {CONCURRENT} conexões simultâneas...")
    print("-" * 60)

    stats["start_time"] = time.time()

    # Criar fila e workers
    queue = asyncio.Queue()

    # Configurar sessão HTTP
    connector = aiohttp.TCPConnector(limit=CONCURRENT, limit_per_host=10)

    async with aiohttp.ClientSession(connector=connector) as session:
        with open(online_path, "w") as online_file, open(offline_path, "w") as offline_file:
            # Criar workers
            workers = [
                asyncio.create_task(worker(queue, session, online_file, offline_file))
                for _ in range(CONCURRENT)
            ]

            # Adicionar domínios à fila com progress updates
            for i, domain in enumerate(domains):
                await queue.put(domain)
                if i % 1000 == 0:
                    print_progress()

            # Aguardar processamento
            await queue.join()

            # Parar workers
            for _ in range(CONCURRENT):
                await queue.put(None)
            await asyncio.gather(*workers)

    # Resultado final
    elapsed = time.time() - stats["start_time"]
    print("\n\n" + "=" * 60)
    print("✅ VALIDAÇÃO CONCLUÍDA!")
    print("=" * 60)
    print(f"⏱️  Tempo total: {elapsed/60:.1f} minutos")
    print(f"📊 Taxa média: {stats['processed']/elapsed:.0f} domínios/segundo")
    print(f"\n📈 RESULTADOS:")
    print(f"   ✅ Online:     {stats['online']:,}")
    print(f"   ❌ Offline:    {stats['offline']:,}")
    print(f"   🔍 DNS Failed: {stats['dns_failed']:,}")
    print(f"   ⚠️  Erros:      {stats['error']:,}")
    print(f"\n📁 Arquivos gerados:")
    print(f"   {online_path}")
    print(f"   {offline_path}")

if __name__ == "__main__":
    try:
        asyncio.run(main())
    except KeyboardInterrupt:
        print("\n\n⛔ Interrompido pelo usuário")
        print(f"Processados: {stats['processed']:,} de {stats['total']:,}")
        sys.exit(0)
