"""
Guia L2: sintoma ConfigTool/NVR ven solo ~7 camaras y luego aparecen mas.

Topologia tipica (casa):
  Movistar 192.168.1.1 (DHCP ON)
    - NVR salon .62 / .64 (cable directo o via switch)
    - TVT PoE → D-Link .1.2 → Cudy FS1018PS1 (camaras PoE)
    - D-Link → Cudy M300 (WiFi) → camaras WiFi / NVR en Cudy

Sospechoso #1: Cudy FS1018PS1 con VLAN 1-16 ON (aisla puertos de acceso).
No tocar Movistar. No activar Storm Control / IGMP / Jumbo / VLAN nuevas todavia.
"""
from __future__ import annotations

from typing import List, Optional

from .models import Device, NetInfo, now_str
from .site_inventory import inventory_text, known_nvr_map


CUDY_FS1018_TARGET = """
CUDY FS1018PS1 (switch PoE 16) — SELECTOR FISICO
================================================
VLAN     OFF   ← OBLIGATORIO (si esta ON, aísla camaras entre si / uplink raro)
EXTEND   OFF   ← correcto (no poner ON)
WATCHDOG ON    ← se puede dejar ON

Si estaba VLAN ON: cambie a OFF, espere 1-2 min, abra ConfigTool y:
  ping -t 192.168.1.126
"""

DLINK_CHECKS = """
D-LINK (gestion, tipico 192.168.1.2) — SIN CAMBIOS AGRESIVOS
============================================================
1) Configuration → VLAN → 802.1Q VLAN
   - Solo VLAN 1 / Default
   - Puertos usados: Untagged / miembros VLAN 1
   - PVID = 1 en: puerto→TVT, puerto→Cudy FS1018, puerto→NVR, puerto→Cudy M300
   - Asymmetric VLAN = Disabled
   - NO crear VLAN adicionales
   - NO Auto Surveillance VLAN

2) Status → Port Statistics (nombre puede variar)
   En el puerto D-Link → Cudy FS1018 y en el puerto D-Link → TVT anote:
   Link Status, velocidad negociada, Rx/Tx Packets,
   Rx Errors, Tx Errors, CRC Errors, Drops, Collisions
   No cambie nada: solo lea y compare.

3) NO active ahora: Storm Control, IGMP Snooping, Jumbo Frames, RSTP raro.
"""

PING_PROOF = """
PRUEBA DE ORO (mientras ConfigTool marca ~7)
============================================
PC por CABLE al D-Link.

1) ping 192.168.1.126 -t   (o la IP de una camara que tarda en aparecer)
2) Abra ConfigTool

Si:
  ConfigTool = 7  y  ping .126 = Request timed out
  ↓ unos segundos
  ConfigTool encuentra mas  y  ping .126 empieza a responder

→ Las camaras quedan REALMENTE inaccesibles un rato (no es solo ConfigTool).
  Sospecha: Cudy VLAN ON, enlace D-Link↔Cudy con errores, o tormenta (luego mirror).
"""

TOPOLOGY_ASCII = """
TOPOLOGIA DE PRUEBA (plana, una sola VLAN)
==========================================
                 MOVISTAR 192.168.1.1
                    DHCP ON
                   /         \\
              NVR1(.62)    NVR2(.64) ...
                    \\         /
                     TVT PoE
                        │
                   D-LINK .1.2
                   /         \\
          Cudy FS1018PS1    Cudy M300 (WiFi)  [prueba: desconecte M300]
                 │
            camaras PoE

Prueba aislada: desconecte temporalmente Cudy M300 del D-Link.
Si entonces aparecen TODAS las camaras rapido → el problema suele ser
WiFi/M300 o trafico que el AP mete en la LAN.
"""

RESULT_ABC = """
DESPUES DE PONER VLAN OFF EN CUDY FS1018 — QUE ESPERAR
======================================================
A) Todas las camaras rapido + ping .126 continuo → causa muy probable era VLAN ON.
B) Mejora pero algunas siguen sin ping → VLAN era un problema; queda otro (enlace/errores).
C) Igual que antes → mirar contadores D-Link↔Cudy y luego Port Mirroring + Wireshark.
"""


def switch_l2_guide_text(
    devices: Optional[List[Device]] = None,
    net: Optional[NetInfo] = None,
) -> str:
    devices = devices or []
    lines = [
        "GUIA SWITCHES / SINTOMA «SOLO 7 CAMARAS»",
        "=" * 56,
        f"Generado: {now_str()}",
        "",
        "Respuesta corta: NO configure nada especial en Movistar (DHCP 192.168.1.1 ON).",
        "El fallo tipico esta en Cudy FS1018PS1 (VLAN ON) o en el enlace D-Link ↔ Cudy.",
        "",
        inventory_text(),
        "",
        TOPOLOGY_ASCII.strip(),
        "",
        CUDY_FS1018_TARGET.strip(),
        "",
        DLINK_CHECKS.strip(),
        "",
        PING_PROOF.strip(),
        "",
        RESULT_ABC.strip(),
        "",
        "NVR CONOCIDOS EN ESTA CASA (marque el principal ☑ = .62 si es el que graba)",
        "-" * 40,
    ]
    for ip, e in sorted(known_nvr_map().items(), key=lambda x: tuple(int(p) for p in x[0].split("."))):
        seen = next((d for d in devices if d.ip == ip), None)
        st = seen.status if seen else "no visto en escaneo"
        lines.append(f"  {ip}  {e.get('name')}  [{st}]")

    dlinks = [d for d in devices if "d-link" in (d.vendor or "").lower() or d.ip.endswith(".2")]
    cudys = [d for d in devices if "cudy" in (d.vendor or "").lower()]
    lines.append("")
    lines.append("EN EL ULTIMO ESCANEO")
    lines.append("-" * 40)
    if dlinks:
        for d in dlinks:
            lines.append(f"  Posible D-Link/gestion: {d.ip}  {d.vendor or '-'}  {d.hostname or '-'}")
    else:
        lines.append("  D-Link .1.2 no clasificado: entre por http://192.168.1.2 si esa es su IP.")
    if cudys:
        for d in cudys:
            lines.append(f"  Cudy visto: {d.ip}  {d.vendor or '-'}  {d.hostname or '-'}")
    else:
        lines.append("  Cudy no etiquetado en escaneo (el FS1018 es L2 y puede no tener IP de gestion).")
    if net and net.gateway:
        lines.append(f"  Gateway PC: {net.gateway}  DHCP: {net.dhcp_server or '-'}")
    lines.extend(
        [
            "",
            "ORDEN DE ACCIONES (una a una)",
            "1. Cudy FS1018: VLAN OFF, Extend OFF, Watchdog ON. Espere 1-2 min.",
            "2. ping -t a una camara 'lenta' + ConfigTool. Anote A/B/C.",
            "3. D-Link: solo VLAN 1 Untagged, PVID 1. Lea errores del puerto al Cudy y al TVT.",
            "4. Prueba: desconecte Cudy M300; si todo aparece rapido → enfoque WiFi/AP.",
            "5. Solo despues: Port Mirroring en D-Link + Wireshark (tormenta).",
            "6. Luego caudal/Extra-Sub en NVR (.62/.64/.76/.57) si ya hay ping estable a todas.",
        ]
    )
    return "\n".join(lines)
