"""Inventario real de la instalacion (NVR por ubicacion / IP fija)."""
from __future__ import annotations

from typing import Any, Dict, List, Optional

from .models import Device, load_config


# Valores por defecto (casa Paterna). Se pueden ampliar en config.json → known_nvrs.
DEFAULT_KNOWN_NVRS: List[Dict[str, Any]] = [
    {
        "ip": "192.168.1.62",
        "name": "NVR1 Salon TV1",
        "location": "Salon",
        "role": "principal_hint",
        "note": "NVR 1 del salon (TV). Suele ser el principal que ve/graba mas camaras.",
    },
    {
        "ip": "192.168.1.64",
        "name": "NVR2 Salon TV2",
        "location": "Salon",
        "role": "visor",
        "note": "Segundo NVR del salon (otra tele). Vista = Extra/Sub.",
    },
    {
        "ip": "192.168.1.76",
        "name": "NVR Dormitorio",
        "location": "Dormitorio",
        "role": "visor",
        "note": "NVR en tele del dormitorio. Vista = Extra/Sub.",
    },
    {
        "ip": "192.168.1.57",
        "name": "NVR Escalera",
        "location": "Escalera",
        "role": "visor",
        "note": "NVR en tele de la escalera. Vista = Extra/Sub.",
    },
]


def _entries(cfg: Optional[Dict[str, Any]] = None) -> List[Dict[str, Any]]:
    c = cfg if cfg is not None else load_config()
    raw = c.get("known_nvrs")
    if isinstance(raw, list) and raw:
        return [x for x in raw if isinstance(x, dict) and x.get("ip")]
    return list(DEFAULT_KNOWN_NVRS)


def known_nvr_map(cfg: Optional[Dict[str, Any]] = None) -> Dict[str, Dict[str, Any]]:
    return {str(e["ip"]).strip(): e for e in _entries(cfg)}


def label_for(ip: str, cfg: Optional[Dict[str, Any]] = None) -> str:
    e = known_nvr_map(cfg).get(ip)
    if not e:
        return ""
    return str(e.get("name") or e.get("location") or ip)


def principal_hint_ip(cfg: Optional[Dict[str, Any]] = None) -> Optional[str]:
    for e in _entries(cfg):
        if str(e.get("role", "")).lower() in ("principal", "principal_hint", "main"):
            return str(e["ip"]).strip()
    return None


def known_visor_ips(principal_ip: str = "", cfg: Optional[Dict[str, Any]] = None) -> List[str]:
    pip = (principal_ip or principal_hint_ip(cfg) or "").strip()
    out = []
    for e in _entries(cfg):
        ip = str(e["ip"]).strip()
        if ip and ip != pip:
            out.append(ip)
    return out


def enrich_device(d: Device, cfg: Optional[Dict[str, Any]] = None) -> bool:
    """Pone nombre de ubicacion en hostname y fuerza tipo NVR. True si era conocido."""
    e = known_nvr_map(cfg).get(d.ip)
    if not e:
        return False
    name = str(e.get("name") or "").strip()
    loc = str(e.get("location") or "").strip()
    if name:
        d.hostname = name
    d.device_type = "NVR"
    bits = [loc] if loc else []
    note = str(e.get("note") or "").strip()
    if note:
        bits.append(note)
    role = str(e.get("role") or "").strip()
    if role:
        bits.append(f"rol={role}")
    extra = " | ".join(bits)
    if extra:
        if d.notes and extra not in d.notes:
            d.notes = f"{d.notes} | {extra}"
        elif not d.notes:
            d.notes = extra
    return True


def enrich_devices(devices: List[Device], cfg: Optional[Dict[str, Any]] = None) -> int:
    n = 0
    for d in devices:
        if enrich_device(d, cfg):
            n += 1
    return n


def inventory_text(cfg: Optional[Dict[str, Any]] = None) -> str:
    lines = [
        "INVENTARIO NVR CONOCIDOS (esta casa)",
        "-" * 40,
    ]
    hint = principal_hint_ip(cfg)
    for e in _entries(cfg):
        ip = e["ip"]
        mark = " ← principal sugerido (marque ☑ si es el que graba/ve todas)" if ip == hint else ""
        lines.append(
            f"  {ip}  {e.get('name', '')}  [{e.get('location', '')}]  "
            f"rol={e.get('role', '-')}{mark}"
        )
        if e.get("note"):
            lines.append(f"      {e['note']}")
    lines.append("")
    lines.append(
        "Si aparecen mas NVR al escanear, anote su IP en config.json → known_nvrs "
        "o digaselo al tecnico para actualizar el inventario."
    )
    return "\n".join(lines)
