"""Tests for harp library."""

from unittest.mock import patch

import harp


class TestGenerateName:
    """Tests for generate_name function."""

    def test_returns_string(self):
        name = harp.generate_name()
        assert isinstance(name, str)

    def test_default_has_three_components(self):
        name = harp.generate_name()
        parts = name.split("-")
        assert len(parts) == 3

    def test_produces_different_results(self):
        names = {harp.generate_name() for _ in range(10)}
        assert len(names) > 1


class TestGenerateNameWithOptions:
    """Tests for generate_name_with_options function."""

    def test_two_components(self):
        name = harp.generate_name_with_options(components=2)
        parts = name.split("-")
        assert len(parts) == 2

    def test_four_components(self):
        name = harp.generate_name_with_options(components=4)
        parts = name.split("-")
        assert len(parts) == 4

    def test_sixteen_components(self):
        name = harp.generate_name_with_options(components=16)
        parts = name.split("-")
        assert len(parts) == 16

    def test_components_clamped_to_minimum(self):
        name = harp.generate_name_with_options(components=1)
        parts = name.split("-")
        assert len(parts) == 2

    def test_components_clamped_to_maximum(self):
        name = harp.generate_name_with_options(components=20)
        parts = name.split("-")
        assert len(parts) == 16

    def test_custom_separator(self):
        name = harp.generate_name_with_options(separator="_")
        assert "_" in name
        assert "-" not in name

    def test_max_element_length(self):
        name = harp.generate_name_with_options(max_element_length=4)
        for part in name.split("-"):
            assert len(part) <= 4


class TestVersion:
    """Tests for version function."""

    def test_returns_string(self):
        v = harp.version()
        assert isinstance(v, str)

    def test_is_semver_format(self):
        v = harp.version()
        parts = v.split(".")
        assert len(parts) >= 2
        assert all(p.isdigit() for p in parts[:2])


class TestWordLists:
    """Tests for word list loading."""

    def test_adjectives_loaded(self):
        adjectives = harp._load_adjectives()
        assert len(adjectives) > 1000

    def test_nouns_loaded(self):
        nouns = harp._load_nouns()
        assert len(nouns) > 4000

    def test_no_empty_words(self):
        adjectives = harp._load_adjectives()
        nouns = harp._load_nouns()
        assert all(adj.strip() for adj in adjectives)
        assert all(noun.strip() for noun in nouns)


class TestEdgeCases:
    """Tests for edge cases."""

    def test_empty_adjectives(self):
        with patch.object(harp, "_load_adjectives", return_value=()):
            name = harp.generate_name_with_options(components=3)
            # Only noun should be present
            assert name != ""

    def test_empty_nouns(self):
        with patch.object(harp, "_load_nouns", return_value=()):
            name = harp.generate_name_with_options(components=3)
            # Only adjectives should be present
            parts = name.split("-")
            assert len(parts) == 2

    def test_empty_both(self):
        with patch.object(harp, "_load_adjectives", return_value=()):
            with patch.object(harp, "_load_nouns", return_value=()):
                name = harp.generate_name_with_options(components=3)
                assert name == ""


class TestSeed:
    """Tests for deterministic seed generation."""

    def test_same_seed_produces_same_name(self):
        name1 = harp.generate_name_with_options(seed=42)
        name2 = harp.generate_name_with_options(seed=42)
        assert name1 == name2

    def test_different_seeds_produce_different_names(self):
        name1 = harp.generate_name_with_options(seed=42)
        name2 = harp.generate_name_with_options(seed=43)
        assert name1 != name2

    def test_seed_with_options(self):
        name1 = harp.generate_name_with_options(components=2, separator="_", seed=42)
        name2 = harp.generate_name_with_options(components=2, separator="_", seed=42)
        assert name1 == name2
        assert "_" in name1

    def test_generate_name_with_seed(self):
        name1 = harp.generate_name(seed=42)
        name2 = harp.generate_name(seed=42)
        assert name1 == name2

    def test_none_seed_is_random(self):
        names = {harp.generate_name_with_options(seed=None) for _ in range(10)}
        assert len(names) > 1
