"""
Reconstruit ip_parent/ip_enfant en utilisant le champ host et config.yaml.
1) Pour chaque IP avec host, retrouve l'IP du host dans config.yaml et met ip_parent.
2) Recalcule ip_enfant depuis ip_parent.
"""
from __future__ import annotations

import json
import sqlite3
from pathlib import Path
from typing import Any, Dict

import yaml


CONFIG_PATH = Path(__file__).resolve().parents[3] / "config.yaml"


def load_config() -> Dict[str, Any]:
    with CONFIG_PATH.open("r", encoding="utf-8") as handle:
        return yaml.safe_load(handle) or {}


def ensure_columns(conn: sqlite3.Connection) -> None:
    cursor = conn.execute("PRAGMA table_info(ip)")
    columns = {row[1] for row in cursor.fetchall()}
    if "ip_parent" not in columns:
        conn.execute("ALTER TABLE ip ADD COLUMN ip_parent TEXT")
    if "ip_enfant" not in columns:
        conn.execute("ALTER TABLE ip ADD COLUMN ip_enfant TEXT")
    conn.commit()


def host_ip_map(config: Dict[str, Any]) -> Dict[str, str]:
    mapping: Dict[str, str] = {}
    for host in config.get("hosts", []) or []:
        if not isinstance(host, dict):
            continue
        name = (host.get("name") or "").strip()
        ip = (host.get("ip") or "").strip()
        if name and ip:
            mapping[name.lower()] = ip
    return mapping


def main() -> None:
    config = load_config()
    db_path = Path(config.get("database", {}).get("path", "./data/db.sqlite"))

    if not db_path.exists():
        raise FileNotFoundError(f"Base de données introuvable: {db_path}")

    host_map = host_ip_map(config)
    conn = sqlite3.connect(db_path)
    try:
        ensure_columns(conn)

        cursor = conn.execute("SELECT ip, host FROM ip")
        rows = cursor.fetchall()

        updated = 0
        skipped = 0
        for ip_address, host in rows:
            if not host:
                skipped += 1
                continue
            parent_ip = host_map.get(str(host).lower())
            if not parent_ip:
                print(f"[WARN] host sans IP config: {host} (ip {ip_address})")
                skipped += 1
                continue
            conn.execute("UPDATE ip SET ip_parent = ? WHERE ip = ?", (parent_ip, ip_address))
            updated += 1

        print(f"[INFO] ip_parent mis à jour: {updated} | ignorés: {skipped}")

        config_by_ip = {ip for ip in host_map.values()}
        parent_children: Dict[str, list[str]] = {}
        for ip_address, host in rows:
            host_value = (host or "").strip()
            if host_value in config_by_ip:
                parent_children.setdefault(host_value, []).append(ip_address)

        for parent_ip in config_by_ip:
            children = parent_children.get(parent_ip, [])
            conn.execute(
                "UPDATE ip SET ip_enfant = ? WHERE ip = ?",
                (json.dumps(children), parent_ip)
            )

        conn.commit()
        print("[INFO] ip_enfant recalculé.")
    finally:
        conn.close()


if __name__ == "__main__":
    main()
