"""Network module — offline (no real pings, no real nmcli/NetworkManager calls)."""
import subprocess

from modules.network import backend as net


def test_primary_connection_returns_expected_shape():
    conn = net.primary_connection()
    assert set(conn.keys()) == {"interface", "ip", "type"}
    assert conn["type"] in ("wifi", "ethernet", "offline")


def test_vpn_status_unavailable_when_nmcli_missing(monkeypatch):
    monkeypatch.setattr(net, "_nmcli_available", lambda: False)
    assert net.vpn_status() == {"available": False}


def test_vpn_status_configured_but_disconnected(monkeypatch):
    monkeypatch.setattr(net, "_nmcli_available", lambda: True)
    monkeypatch.setattr(net, "_nmcli", lambda *a: "wgs_client:wireguard:disconnected")
    status = net.vpn_status()
    assert status == {"available": True, "configured": True, "name": "wgs_client", "connected": False}


def test_vpn_status_connected(monkeypatch):
    monkeypatch.setattr(net, "_nmcli_available", lambda: True)
    monkeypatch.setattr(net, "_nmcli", lambda *a: "wgs_client:wireguard:activated")
    status = net.vpn_status()
    assert status["connected"] is True


def test_vpn_toggle_raises_without_a_configured_tunnel(monkeypatch):
    monkeypatch.setattr(net, "vpn_status", lambda: {"available": True, "configured": False, "name": None, "connected": False})
    try:
        net.vpn_toggle(True)
        assert False, "expected RuntimeError"
    except RuntimeError:
        pass


def test_target_crud_roundtrip(tmp_path, monkeypatch):
    monkeypatch.setattr(net, "_TARGETS_FILE", tmp_path / "targets.json")

    assert net.list_targets() == []
    t = net.add_target("Router", "192.168.50.1")
    assert t["label"] == "Router" and t["host"] == "192.168.50.1"

    targets = net.list_targets()
    assert len(targets) == 1
    assert targets[0]["id"] == t["id"]

    net.delete_target(t["id"])
    assert net.list_targets() == []


def test_ping_parses_latency_on_success(monkeypatch):
    monkeypatch.setattr(subprocess, "check_output", lambda *a, **k: "64 bytes from 1.1.1.1: icmp_seq=1 ttl=56 time=12.3 ms")
    result = net.ping("1.1.1.1")
    assert result["ok"] is True
    assert result["latency_ms"] == 12.3


def test_ping_reports_failure(monkeypatch):
    def raise_failed(*a, **k):
        raise subprocess.CalledProcessError(1, "ping")
    monkeypatch.setattr(subprocess, "check_output", raise_failed)
    result = net.ping("10.255.255.1")
    assert result == {"ok": False, "latency_ms": None}


def test_ping_targets_merges_target_and_result(tmp_path, monkeypatch):
    monkeypatch.setattr(net, "_TARGETS_FILE", tmp_path / "targets.json")
    net.add_target("Router", "192.168.50.1")
    monkeypatch.setattr(net, "ping", lambda host: {"ok": True, "latency_ms": 5.0})

    results = net.ping_targets()
    assert len(results) == 1
    assert results[0]["host"] == "192.168.50.1"
    assert results[0]["ok"] is True
    assert results[0]["latency_ms"] == 5.0
