"""Move hypervisors from servers table to a dedicated hypervisors table.

Usage:
    python tools/move_hypervisors.py <hyperviseur_csv_path>
"""
import csv
import os
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"


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("csv_path", help="Hyperviseur CSV iTop")
    args = parser.parse_args()

    engine = create_engine(DATABASE_URL)
    print(f"[INFO] DB: {DATABASE_URL.split('@')[-1]}")
    print(f"[INFO] CSV: {args.csv_path}")

    with open(args.csv_path, "r", encoding="utf-8-sig", newline="") as f:
        reader = csv.DictReader(f)
        rows = list(reader)
    print(f"[INFO] {len(rows)} lignes CSV")

    conn = engine.connect().execution_options(isolation_level="AUTOCOMMIT")

    # Crée la table si pas existante
    conn.execute(text("""
        CREATE TABLE IF NOT EXISTS hypervisors (
            id SERIAL PRIMARY KEY,
            hostname citext UNIQUE NOT NULL,
            fqdn varchar(255),
            cluster_name varchar(100),
            underlying_server varchar(100),
            site varchar(100),
            domain_ltd varchar(50),
            description text,
            responsable_nom text,
            moved_from_server_id integer,
            created_at timestamptz DEFAULT now()
        )
    """))

    moved = 0
    not_in_servers = 0
    skipped = 0

    for r in rows:
        hostname = (r.get("Nom") or r.get("Hostname") or "").strip()
        if not hostname or hostname in ("(null)",) or not any(c.isalpha() for c in hostname):
            skipped += 1
            continue

        srv = conn.execute(text(
            "SELECT id, fqdn, site, domain_ltd, patch_owner_details, responsable_nom FROM servers WHERE hostname=:h"
        ), {"h": hostname}).fetchone()

        if not srv:
            # Pas en base servers, on insère quand même dans hypervisors
            try:
                conn.execute(text("""
                    INSERT INTO hypervisors (hostname, cluster_name, underlying_server, description, responsable_nom)
                    VALUES (:h, :cl, :srv, :desc, :resp)
                    ON CONFLICT (hostname) DO NOTHING
                """), {
                    "h": hostname,
                    "cl": (r.get("vCluster->Nom") or "").strip()[:100] or None,
                    "srv": (r.get("Serveur->Nom") or "").strip()[:100] or None,
                    "desc": (r.get("Description") or "").strip() or None,
                    "resp": None,
                })
                not_in_servers += 1
            except Exception as e:
                print(f"  [ERR insert] {hostname}: {str(e)[:120]}")
                skipped += 1
            continue

        try:
            # Insert dans hypervisors
            conn.execute(text("""
                INSERT INTO hypervisors
                (hostname, fqdn, cluster_name, underlying_server, site, domain_ltd,
                 description, responsable_nom, moved_from_server_id)
                VALUES (:h, :fqdn, :cl, :usrv, :site, :domain, :desc, :resp, :sid)
                ON CONFLICT (hostname) DO UPDATE SET
                    cluster_name=EXCLUDED.cluster_name,
                    underlying_server=EXCLUDED.underlying_server,
                    moved_from_server_id=EXCLUDED.moved_from_server_id
            """), {
                "h": hostname, "fqdn": srv.fqdn,
                "cl": (r.get("vCluster->Nom") or "").strip()[:100] or None,
                "usrv": (r.get("Serveur->Nom") or "").strip()[:100] or None,
                "site": srv.site, "domain": srv.domain_ltd,
                "desc": (r.get("Description") or srv.patch_owner_details or "").strip()[:1000] or None,
                "resp": srv.responsable_nom,
                "sid": srv.id,
            })

            # Nettoie les FK puis delete du servers
            for tbl, col in [("server_ips", "server_id"), ("qualys_assets", "server_id"),
                             ("server_audit", "server_id"), ("server_audit_full", "server_id"),
                             ("server_correspondance", "server_id"), ("cluster_members", "server_id"),
                             ("patch_history", "server_id"), ("patch_sessions", "server_id"),
                             ("patch_validation", "server_id"), ("quickwin_entries", "server_id"),
                             ("quickwin_server_config", "server_id"), ("server_specifics", "server_id"),
                             ("server_pairs", "server_a_id"), ("server_pairs", "server_b_id")]:
                try:
                    conn.execute(text(f"DELETE FROM {tbl} WHERE {col}=:sid"), {"sid": srv.id})
                except Exception:
                    pass
            conn.execute(text("DELETE FROM servers WHERE id=:sid"), {"sid": srv.id})
            moved += 1
        except Exception as e:
            print(f"  [ERR move] {hostname}: {str(e)[:150]}")
            skipped += 1

    conn.close()
    print(f"[DONE] Deplaces: {moved} | Inseres directement (pas en servers): {not_in_servers} | Ignores: {skipped}")


if __name__ == "__main__":
    main()
