import pytest

from nebula_cert_manager.lighthouses import (
    extract_lighthouses,
    resolve_lighthouses_for_client,
)
from nebula_cert_manager.models import (
    HostConfig,
    HostDefaults,
    HostsConfig,
    LighthouseConfig,
)


def test_extract_lighthouses():
    hosts_config = HostsConfig(
        defaults=HostDefaults(listen_port=44300),
        hosts={
            "server1": HostConfig(
                nebula_ip="10.43.0.1",
                public_endpoints=["203.0.113.1"],
            ),
            "server2": HostConfig(
                nebula_ip="10.43.0.2",
                public_endpoints=["203.0.113.2"],
            ),
            "laptop": HostConfig(nebula_ip="10.43.1.1"),
        },
    )
    lighthouses = extract_lighthouses(hosts_config)
    assert len(lighthouses) == 2
    assert "server1" in lighthouses
    assert "server2" in lighthouses
    assert "laptop" not in lighthouses
    assert lighthouses["server1"].nebula_ip == "10.43.0.1"
    assert lighthouses["server1"].public_endpoints == ["203.0.113.1"]
    assert lighthouses["server1"].listen_port == 44300


def test_extract_lighthouses_none():
    hosts_config = HostsConfig(
        hosts={
            "laptop": HostConfig(nebula_ip="10.43.1.1"),
        },
    )
    lighthouses = extract_lighthouses(hosts_config)
    assert len(lighthouses) == 0


def test_extract_lighthouses_per_host_listen_port():
    hosts_config = HostsConfig(
        defaults=HostDefaults(listen_port=44300),
        hosts={
            "server1": HostConfig(
                nebula_ip="10.43.0.1",
                public_endpoints=["203.0.113.1"],
                listen_port=5555,
            ),
        },
    )
    lighthouses = extract_lighthouses(hosts_config)
    assert lighthouses["server1"].listen_port == 5555


def test_extract_lighthouses_no_listen_port_raises():
    hosts_config = HostsConfig(
        hosts={
            "server1": HostConfig(
                nebula_ip="10.43.0.1",
                public_endpoints=["203.0.113.1"],
            ),
        },
    )
    with pytest.raises(ValueError, match="no listen_port configured"):
        extract_lighthouses(hosts_config)


def test_resolve_regular_client():
    lighthouses = {
        "server1": LighthouseConfig(
            nebula_ip="10.43.0.1", public_endpoints=["203.0.113.1"], listen_port=44300
        ),
    }
    am_lighthouse, filtered = resolve_lighthouses_for_client("laptop", lighthouses)
    assert am_lighthouse is False
    assert len(filtered) == 1
    assert filtered[0].nebula_ip == "10.43.0.1"


def test_resolve_lighthouse_self_exclusion():
    lighthouses = {
        "server1": LighthouseConfig(
            nebula_ip="10.43.0.1", public_endpoints=["203.0.113.1"], listen_port=44300
        ),
        "server2": LighthouseConfig(
            nebula_ip="10.43.0.2", public_endpoints=["203.0.113.2"], listen_port=44300
        ),
    }
    am_lighthouse, filtered = resolve_lighthouses_for_client("server1", lighthouses)
    assert am_lighthouse is True
    assert len(filtered) == 1
    assert filtered[0].nebula_ip == "10.43.0.2"


def test_resolve_multi_lighthouse():
    lighthouses = {
        "server1": LighthouseConfig(
            nebula_ip="10.43.0.1", public_endpoints=["203.0.113.1"], listen_port=44300
        ),
        "server2": LighthouseConfig(
            nebula_ip="10.43.0.2", public_endpoints=["203.0.113.2"], listen_port=44300
        ),
        "server3": LighthouseConfig(
            nebula_ip="10.43.0.3", public_endpoints=["203.0.113.3"], listen_port=44300
        ),
    }
    am_lighthouse, filtered = resolve_lighthouses_for_client("server2", lighthouses)
    assert am_lighthouse is True
    assert len(filtered) == 2
    ips = [lh.nebula_ip for lh in filtered]
    assert "10.43.0.1" in ips
    assert "10.43.0.3" in ips
    assert "10.43.0.2" not in ips
