"""Fallback IP via DNS pour les serveurs sans IP en base.

Pour chaque server sans entry server_ips :
 - Essaie resolve(hostname.domain_ltd) si domain_ltd renseigne
 - Sinon teste les suffixes SANEF (sanef.groupe, sanef-rec.fr, recette.adds, sanef-int.adds, serveur.est.sanef.fr, serveur.ouest.sanef.fr, sanef.fr)
 - Insere l'IP resolue (ip_type='primary', description='DNS lookup')

Usage:
    python tools/fill_ips_by_dns.py [--dry-run] [--timeout 1]
"""
import os
import socket
import threading
import argparse
from sqlalchemy import create_engine, text

DATABASE_URL = os.getenv("DATABASE_URL_DEMO") or os.getenv("DATABASE_URL") \
    or "postgresql://patchcenter:PatchCenter2026!@localhost:5432/patchcenter_demo"

SUFFIXES = [
    "sanef.groupe",
    "sanef-rec.fr",
    "recette.adds",
    "sanef-int.adds",
    "serveur.est.sanef.fr",
    "serveur.ouest.sanef.fr",
    "sanef.fr",
    "sanef-int.fr",
]


def resolve(fqdn, timeout):
    result = [None]

    def _do():
        try:
            result[0] = socket.gethostbyname(fqdn)
        except Exception:
            pass

    t = threading.Thread(target=_do, daemon=True)
    t.start()
    t.join(timeout)
    return result[0]


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--dry-run", action="store_true")
    parser.add_argument("--timeout", type=float, default=1.0)
    args = parser.parse_args()

    engine = create_engine(DATABASE_URL)
    print(f"[INFO] DB: {DATABASE_URL.split('@')[-1]}")
    conn = engine.connect().execution_options(isolation_level="AUTOCOMMIT")

    rows = conn.execute(text("""
        SELECT s.id, s.hostname, s.domain_ltd
        FROM servers s
        WHERE NOT EXISTS (SELECT 1 FROM server_ips si WHERE si.server_id=s.id)
          AND s.hostname IS NOT NULL
        ORDER BY s.hostname
    """)).fetchall()
    print(f"[INFO] {len(rows)} serveurs sans IP")

    inserted = skipped = 0
    for i, r in enumerate(rows, 1):
        h = r.hostname
        print(f"  [{i}/{len(rows)}] {h}...", flush=True)
        # Essaie suffixes dans l'ordre: domain_ltd prioritaire, puis les autres
        order = []
        if r.domain_ltd:
            order.append(r.domain_ltd)
        for s in SUFFIXES:
            if s not in order:
                order.append(s)

        ip = None
        used_suffix = None
        for suffix in order:
            ip = resolve(f"{h}.{suffix}", args.timeout)
            if ip:
                used_suffix = suffix
                break
        if not ip:
            skipped += 1
            continue

        if args.dry_run:
            print(f"    DRY: {h} <- {ip} (via {used_suffix})")
            inserted += 1
            continue
        try:
            conn.execute(text("""
                INSERT INTO server_ips (server_id, ip_address, ip_type, description)
                VALUES (:sid, CAST(:ip AS inet), 'primary', :d)
            """), {"sid": r.id, "ip": ip, "d": f"DNS {used_suffix}"})
            inserted += 1
            print(f"    OK: {h} <- {ip} (via {used_suffix})", flush=True)
        except Exception as e:
            print(f"    [ERR] {h} {ip}: {str(e)[:100]}")
            skipped += 1

    conn.close()
    print(f"\n[DONE] Inserts: {inserted} | Sans DNS: {skipped}")


if __name__ == "__main__":
    main()
