"""Import iTop 'Instance de base de donnees' -> table server_databases.

Cree la table si absente. Pour chaque ligne CSV, match sur Serveur->Nom
(hostname) puis insert un enregistrement instance BDD avec:
 - instance_name (Nom)
 - db_type (Logiciel->Nom: SAP Hana, Oracle, PostgreSQL, SQL Server, MySQL...)
 - db_version (Database_version / Logiciel->Version)
 - db_edition (Database édition)
 - cluster_name (Cluster id->Nom)
 - environnement / etat iTop
 - description

Usage:
    python tools/import_sanef_databases.py <csv> [--truncate] [--dry-run]
"""
import os
import csv
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 clean(v):
    if v is None:
        return None
    s = str(v).strip()
    return s or None


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("csv_path")
    parser.add_argument("--truncate", action="store_true",
                        help="Vide server_databases avant import")
    parser.add_argument("--dry-run", action="store_true")
    args = parser.parse_args()

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

    # Cree la table si absente
    conn.execute(text("""
        CREATE TABLE IF NOT EXISTS server_databases (
            id serial PRIMARY KEY,
            server_id integer REFERENCES servers(id) ON DELETE CASCADE,
            hostname citext,
            instance_name varchar(100),
            db_type varchar(50),
            db_version varchar(100),
            db_edition varchar(50),
            cluster_name varchar(100),
            environnement varchar(50),
            etat varchar(30),
            description text,
            created_at timestamptz DEFAULT now(),
            UNIQUE (hostname, instance_name)
        )
    """))
    conn.execute(text("CREATE INDEX IF NOT EXISTS idx_srv_db_server ON server_databases(server_id)"))
    conn.execute(text("CREATE INDEX IF NOT EXISTS idx_srv_db_type ON server_databases(db_type)"))

    if args.truncate and not args.dry_run:
        conn.execute(text("TRUNCATE server_databases RESTART IDENTITY CASCADE"))
        print("[INFO] Table vidée")

    with open(args.csv_path, "r", encoding="utf-8-sig", newline="") as f:
        sample = f.read(4096); f.seek(0)
        delim = ";" if sample.count(";") > sample.count(",") else ","
        rows = list(csv.DictReader(f, delimiter=delim))
    print(f"[INFO] {len(rows)} lignes (delim={delim!r})")

    stats = {"inserted": 0, "updated": 0, "no_server": 0, "skipped": 0}

    for r in rows:
        # iTop utilise soit "Serveur->Nom" (PhysicalServer) soit "Système->Nom"
        # (VirtualMachine ou systeme generique) selon le type de CI lie
        hostname = clean(r.get("Système->Nom") or r.get("Systeme->Nom")
                         or r.get("Serveur->Nom") or "")
        if hostname:
            hostname = hostname.split(".")[0].lower()
        instance = clean(r.get("Nom"))
        if not hostname or not instance:
            stats["skipped"] += 1
            continue

        db_type = clean(r.get("Logiciel->Nom") or r.get("Type"))
        db_version = clean(r.get("Database_version") or r.get("Logiciel->Version")
                           or r.get("Version complète avec niveau de patch"))
        db_edition = clean(r.get("Database édition"))
        cluster = clean(r.get("Cluster id->Nom"))
        env = clean(r.get("Environnement"))
        etat = clean(r.get("Etat"))
        desc = clean(r.get("Description"))

        if db_version:
            db_version = db_version[:100]
        if db_type:
            db_type = db_type[:50]

        # Retrouve server_id
        srv = conn.execute(text("SELECT id FROM servers WHERE hostname=:h"),
                           {"h": hostname}).fetchone()
        sid = srv.id if srv else None
        if not sid:
            stats["no_server"] += 1

        if args.dry_run:
            print(f"  DRY: {hostname:20s} {instance:20s} [{db_type or '?'}]")
            continue

        # Upsert via ON CONFLICT (hostname, instance_name)
        try:
            conn.execute(text("""
                INSERT INTO server_databases
                (server_id, hostname, instance_name, db_type, db_version,
                 db_edition, cluster_name, environnement, etat, description)
                VALUES (:sid, :h, :inst, :type, :ver, :ed, :cl, :env, :etat, :desc)
                ON CONFLICT (hostname, instance_name) DO UPDATE SET
                    server_id = EXCLUDED.server_id,
                    db_type = EXCLUDED.db_type,
                    db_version = EXCLUDED.db_version,
                    db_edition = EXCLUDED.db_edition,
                    cluster_name = EXCLUDED.cluster_name,
                    environnement = EXCLUDED.environnement,
                    etat = EXCLUDED.etat,
                    description = EXCLUDED.description
            """), {
                "sid": sid, "h": hostname, "inst": instance,
                "type": db_type, "ver": db_version, "ed": db_edition,
                "cl": cluster, "env": env, "etat": etat, "desc": desc,
            })
            stats["inserted"] += 1
        except Exception as e:
            print(f"  [ERR] {hostname}/{instance}: {str(e)[:150]}")
            stats["skipped"] += 1

    conn.close()
    print(f"\n[DONE] Inserts/upserts: {stats['inserted']} | "
          f"Sans serveur en base: {stats['no_server']} | Skip: {stats['skipped']}")


if __name__ == "__main__":
    main()
