"""
Tests for decnet/templates/instance_seed.py — the per-instance stealth
seeding helper. These tests pin NODE_NAME to assert determinism of the
seeded functions, and sweep NODE_NAMEs to assert cross-fleet divergence.
"""

import asyncio
import importlib.util
import sys
import time
from unittest.mock import patch


def _load_seed(node_name: str):
    sys.modules.pop("instance_seed", None)
    spec = importlib.util.spec_from_file_location(
        "instance_seed", "decnet/templates/instance_seed.py"
    )
    mod = importlib.util.module_from_spec(spec)
    with patch.dict("os.environ", {"NODE_NAME": node_name}, clear=False):
        spec.loader.exec_module(mod)
    return mod


def test_same_nodename_yields_stable_uuid():
    a = _load_seed("deckie-42").instance_uuid("x")
    b = _load_seed("deckie-42").instance_uuid("x")
    assert a == b


def test_different_nodename_yields_different_uuid():
    a = _load_seed("deckie-alpha").instance_uuid("x")
    b = _load_seed("deckie-beta").instance_uuid("x")
    assert a != b


def test_pick_is_deterministic_per_instance():
    choices = ["a", "b", "c", "d", "e"]
    m1 = _load_seed("hostX")
    m2 = _load_seed("hostX")
    assert m1.pick(choices) == m2.pick(choices)


def test_pick_varies_across_fleet():
    """For a reasonable fleet size, pick should land on at least 2 distinct
    values. Anything less means the seed isn't actually diversifying output."""
    choices = list("abcdefghij")
    picks = {_load_seed(f"host{i}").pick(choices) for i in range(20)}
    assert len(picks) >= 3


def test_uptime_monotonic_across_calls():
    mod = _load_seed("uptime-host")
    u1 = mod.uptime_seconds()
    time.sleep(0.02)
    u2 = mod.uptime_seconds()
    assert u2 >= u1


def test_uptime_includes_boot_offset():
    """uptime should be > a few minutes even at process start — deckies
    should not look like they just booted."""
    mod = _load_seed("fresh-host")
    assert mod.uptime_seconds() > 600


def test_fresh_bytes_is_not_deterministic():
    """fresh_bytes is per-connection randomness, not seeded — otherwise
    two MySQL handshakes to the same decky would present identical salts."""
    mod = _load_seed("host")
    assert mod.fresh_bytes(16) != mod.fresh_bytes(16)


def test_random_bytes_is_deterministic():
    """random_bytes is the *seeded* variant — used for stable per-instance
    identifiers like cluster UUIDs."""
    a = _load_seed("h").random_bytes(16, "ns")
    b = _load_seed("h").random_bytes(16, "ns")
    assert a == b


def test_jitter_sleeps_in_range():
    mod = _load_seed("jh")

    async def run():
        start = time.perf_counter()
        await mod.jitter(10, 30)
        return time.perf_counter() - start

    elapsed = asyncio.run(run())
    assert 0.005 <= elapsed <= 0.200  # generous upper bound for CI jitter
