# retoor <retoor@molodetz.nl>

import random

from devplacepy.services.bot.config import SEARCH_TERMS
from devplacepy.services.bot.handles import (
    MAX_HANDLE_LEN,
    MIN_HANDLE_LEN,
    apply_leet,
    make_handle,
    sanitize_handle,
)

SAMPLE_COUNT = 300


def _is_valid_username(handle: str) -> bool:
    return (
        handle.isascii()
        and bool(handle)
        and all(character.isalnum() or character in ("-", "_") for character in handle)
    )


def test_make_handle_only_valid_username_characters():
    generator = random.Random(1)
    for _ in range(SAMPLE_COUNT):
        handle = make_handle([], generator)
        assert _is_valid_username(handle), handle


def test_make_handle_never_contains_dot():
    generator = random.Random(2)
    for _ in range(SAMPLE_COUNT):
        handle = make_handle(["first app", "raspberry pi"], generator)
        assert "." not in handle


def test_make_handle_respects_length_bounds():
    generator = random.Random(3)
    for _ in range(SAMPLE_COUNT):
        handle = make_handle([], generator)
        assert MIN_HANDLE_LEN <= len(handle) <= MAX_HANDLE_LEN


def test_make_handle_valid_for_every_persona():
    generator = random.Random(4)
    for persona, interests in SEARCH_TERMS.items():
        for _ in range(SAMPLE_COUNT):
            handle = make_handle(interests, generator)
            assert _is_valid_username(handle), (persona, handle)
            assert MIN_HANDLE_LEN <= len(handle) <= MAX_HANDLE_LEN


def test_make_handle_is_deterministic_for_seeded_rng():
    first = [make_handle(["rust", "kubernetes"], random.Random(99)) for _ in range(20)]
    second = [make_handle(["rust", "kubernetes"], random.Random(99)) for _ in range(20)]
    assert first == second


def test_make_handle_produces_variety():
    generator = random.Random(5)
    handles = {make_handle([], generator) for _ in range(SAMPLE_COUNT)}
    assert len(handles) > SAMPLE_COUNT // 2


def test_sanitize_handle_strips_dots_and_invalid_characters():
    assert sanitize_handle("john.smith.dev!!") == "johnsmithdev"
    assert sanitize_handle("hello world") == "helloworld"
    assert sanitize_handle("a@b#c$d") == "abcd"


def test_sanitize_handle_collapses_and_trims_separators():
    assert sanitize_handle("__null__byte__") == "null_byte"
    assert sanitize_handle("--seg--fault--") == "seg-fault"


def test_sanitize_handle_caps_length():
    assert len(sanitize_handle("a" * 50)) == MAX_HANDLE_LEN


def test_sanitize_handle_empty_input():
    assert sanitize_handle("...") == ""
    assert sanitize_handle("") == ""


def test_apply_leet_only_substitutes_mapped_characters():
    generator = random.Random(7)
    result = apply_leet("xyzq", generator)
    assert result == "xyzq"


def test_apply_leet_can_substitute_known_characters():
    always = random.Random(0)
    seen = {apply_leet("aeiost", always) for _ in range(50)}
    assert any(character.isdigit() for handle in seen for character in handle)
