# #region TestTextCleaner [C:3] [TYPE Module] [SEMANTICS test, text, cleaner, whitespace, truncation]
# @BRIEF Verify text cleaning contracts — normalize_whitespace, truncate_text, clean_text.
# @RELATION BINDS_TO -> [TextCleaner]
# @TEST_EDGE  empty_string — empty/whitespace-only input returns ""
# @TEST_EDGE  whitespace_variants — multiple spaces, newlines, tabs all collapse to single space
# @TEST_EDGE  truncation_boundary — text shorter than, equal to, and longer than max_length
# @TEST_EDGE  clean_combined — clean_text correctly chains normalize + truncate
# @TEST_EDGE  zero_max_length — max_length=0 forces truncation on any non-empty text

from src.plugins.translate._text_cleaner import clean_text, normalize_whitespace, truncate_text


# region TestNormalizeWhitespace [TYPE Class]
# @BRIEF Test suite for normalize_whitespace.
class TestNormalizeWhitespace:

    # region test_empty_string [TYPE Function]
    # @BRIEF Empty string returns empty string.
    def test_empty_string(self):
        assert normalize_whitespace("") == ""
    # endregion test_empty_string

    # region test_whitespace_only [TYPE Function]
    # @BRIEF String with only whitespace returns empty string.
    def test_whitespace_only(self):
        assert normalize_whitespace("   ") == ""
        assert normalize_whitespace("\t") == ""
        assert normalize_whitespace("\n") == ""
    # endregion test_whitespace_only

    # region test_multiple_spaces [TYPE Function]
    # @BRIEF Multiple spaces between words are collapsed to single space.
    def test_multiple_spaces(self):
        assert normalize_whitespace("hello    world") == "hello world"
    # endregion test_multiple_spaces

    # region test_multiple_newlines [TYPE Function]
    # @BRIEF Multiple newlines are collapsed to single space.
    def test_multiple_newlines(self):
        assert normalize_whitespace("hello\n\n\nworld") == "hello world"
    # endregion test_multiple_newlines

    # region test_mixed_whitespace [TYPE Function]
    # @BRIEF Tabs, newlines, and spaces all collapse to single space.
    def test_mixed_whitespace(self):
        assert normalize_whitespace("hello\t  \n  world") == "hello world"
    # endregion test_mixed_whitespace

    # region test_leading_trailing_whitespace [TYPE Function]
    # @BRIEF Leading and trailing whitespace is trimmed.
    def test_leading_trailing_whitespace(self):
        assert normalize_whitespace("  hello world  ") == "hello world"
        assert normalize_whitespace("\nhello world\n") == "hello world"
    # endregion test_leading_trailing_whitespace

    # region test_already_clean [TYPE Function]
    # @BRIEF Already clean text is returned unchanged.
    def test_already_clean(self):
        assert normalize_whitespace("hello world") == "hello world"
    # endregion test_already_clean

    # region test_single_word [TYPE Function]
    # @BRIEF Single word with surrounding whitespace is trimmed to the word.
    def test_single_word(self):
        assert normalize_whitespace("  hello  ") == "hello"
    # endregion test_single_word

# endregion TestNormalizeWhitespace


# region TestTruncateText [TYPE Class]
# @BRIEF Test suite for truncate_text.
class TestTruncateText:

    # region test_empty_string [TYPE Function]
    # @BRIEF Empty string stays empty regardless of max_length.
    def test_empty_string(self):
        assert truncate_text("") == ""
        assert truncate_text("", max_length=0) == ""
    # endregion test_empty_string

    # region test_shorter_than_max [TYPE Function]
    # @BRIEF Text shorter than max_length is returned unchanged.
    def test_shorter_than_max(self):
        assert truncate_text("hi", max_length=5) == "hi"
    # endregion test_shorter_than_max

    # region test_exactly_at_max [TYPE Function]
    # @BRIEF Text exactly at max_length is returned unchanged (no "..." appended).
    def test_exactly_at_max(self):
        assert truncate_text("hello", max_length=5) == "hello"
    # endregion test_exactly_at_max

    # region test_longer_than_max [TYPE Function]
    # @BRIEF Text longer than max_length is truncated with "..." appended.
    def test_longer_than_max(self):
        result = truncate_text("hello world", max_length=5)
        assert result == "hello..."
        assert len(result) == 8  # 5 chars + "..."
    # endregion test_longer_than_max

    # region test_zero_max_length [TYPE Function]
    # @BRIEF max_length=0 truncates any non-empty text to "...".
    def test_zero_max_length(self):
        assert truncate_text("hello", max_length=0) == "..."
    # endregion test_zero_max_length

    # region test_default_max_length [TYPE Function]
    # @BRIEF Default max_length of 500 does not truncate short text.
    def test_default_max_length(self):
        text = "x" * 100
        assert truncate_text(text) == text
    # endregion test_default_max_length

    # region test_truncation_at_default_boundary [TYPE Function]
    # @BRIEF Text exactly 500 chars is unchanged; 501 chars is truncated.
    def test_truncation_at_default_boundary(self):
        text_500 = "x" * 500
        text_501 = "x" * 501
        assert truncate_text(text_500) == text_500
        result = truncate_text(text_501)
        assert result == "x" * 500 + "..."
        assert len(result) == 503
    # endregion test_truncation_at_default_boundary

# endregion TestTruncateText


# region TestCleanText [TYPE Class]
# @BRIEF Test suite for clean_text (combined normalize + truncate).
class TestCleanText:

    # region test_empty_string [TYPE Function]
    # @BRIEF Empty string returns empty string.
    def test_empty_string(self):
        assert clean_text("") == ""
    # endregion test_empty_string

    # region test_whitespace_only [TYPE Function]
    # @BRIEF Whitespace-only input returns empty string.
    def test_whitespace_only(self):
        assert clean_text("   \n  \t  ") == ""
    # endregion test_whitespace_only

    # region test_clean_and_short [TYPE Function]
    # @BRIEF Already clean, short text is returned unchanged.
    def test_clean_and_short(self):
        assert clean_text("hello world") == "hello world"
    # endregion test_clean_and_short

    # region test_normalize_then_truncate [TYPE Function]
    # @BRIEF Whitespace is normalized before truncation — counting clean chars.
    def test_normalize_then_truncate(self):
        # "hello   world" has 15 chars raw, normalized to "hello world" (11 chars)
        # With max_length=5, should truncate normalized text to "hello..."
        result = clean_text("hello   world", max_length=5)
        assert result == "hello..."
    # endregion test_normalize_then_truncate

    # region test_normalize_keeps_text_under_limit [TYPE Function]
    # @BRIEF Normalization reduces length enough that truncation is not needed.
    def test_normalize_keeps_text_under_limit(self):
        # "A  B" has 4 chars raw, normalizes to "A B" (3 chars), still under 5
        result = clean_text("A  B", max_length=5)
        assert result == "A B"
    # endregion test_normalize_keeps_text_under_limit

    # region test_leading_whitespace_then_truncate [TYPE Function]
    # @BRIEF Leading whitespace is removed before truncation, avoiding wasted chars.
    def test_leading_whitespace_then_truncate(self):
        # "   hello world" normalizes to "hello world" (11 chars)
        # With max_length=5: truncates to "hello..."
        result = clean_text("   hello world", max_length=5)
        assert result == "hello..."
    # endregion test_leading_whitespace_then_truncate

    # region test_default_max_length_passthrough [TYPE Function]
    # @BRIEF With default max_length=500, text under 500 after normalize is unchanged.
    def test_default_max_length_passthrough(self):
        text = "  hello   world  "
        expected = "hello world"
        assert clean_text(text) == expected
    # endregion test_default_max_length_passthrough

# endregion TestCleanText
# #endregion TestTextCleaner
