"""
Test suite for string utility functions.
"""

import pytest
from markitect_utils.string_utils import (
    slugify,
    truncate,
    camel_to_snake,
    snake_to_camel,
    strip_ansi_codes,
)


class TestSlugify:
    """Test cases for the slugify function."""

    def test_basic_slugify(self):
        """Test basic string to slug conversion."""
        assert slugify("Hello World") == "hello-world"
        assert slugify("My Great Article") == "my-great-article"

    def test_special_characters(self):
        """Test handling of special characters."""
        assert slugify("Hello World!") == "hello-world"
        assert slugify("Test@#$%^&*()_+") == "test"  # underscore gets converted to separator
        assert slugify("Multiple---Dashes") == "multiple-dashes"

    def test_custom_separator(self):
        """Test custom separator."""
        assert slugify("Hello World", "_") == "hello_world"
        assert slugify("My Great Article", ".") == "my.great.article"

    def test_edge_cases(self):
        """Test edge cases."""
        assert slugify("") == ""
        assert slugify("   ") == ""
        assert slugify("---") == ""
        assert slugify("Single") == "single"

    def test_unicode_handling(self):
        """Test unicode character handling."""
        assert slugify("Café") == "cafe"
        assert slugify("naïve résumé") == "naive-resume"


class TestTruncate:
    """Test cases for the truncate function."""

    def test_basic_truncation(self):
        """Test basic string truncation."""
        text = "This is a long string that needs truncation"
        assert truncate(text, 20) == "This is a long st..."
        assert truncate(text, 10) == "This is..."

    def test_no_truncation_needed(self):
        """Test when no truncation is needed."""
        assert truncate("Short", 10) == "Short"
        assert truncate("Exact", 5) == "Exact"

    def test_custom_suffix(self):
        """Test custom suffix."""
        text = "Long text here"
        assert truncate(text, 10, "…") == "Long text…"
        assert truncate(text, 10, " [more]") == "Lon [more]"

    def test_edge_cases(self):
        """Test edge cases."""
        assert truncate("", 10) == ""
        assert truncate("Test", 3) == "..."
        assert truncate("Test", 2) == ".."
        assert truncate("Test", 1) == "."
        assert truncate("Test", 0) == ""


class TestCamelToSnake:
    """Test cases for the camel_to_snake function."""

    def test_basic_conversion(self):
        """Test basic camelCase to snake_case conversion."""
        assert camel_to_snake("camelCase") == "camel_case"
        assert camel_to_snake("PascalCase") == "pascal_case"
        assert camel_to_snake("simpleWord") == "simple_word"

    def test_multiple_words(self):
        """Test conversion with multiple words."""
        assert camel_to_snake("thisIsALongVariableName") == "this_is_a_long_variable_name"
        assert camel_to_snake("XMLHttpRequest") == "xml_http_request"
        assert camel_to_snake("JSONData") == "json_data"

    def test_edge_cases(self):
        """Test edge cases."""
        assert camel_to_snake("") == ""
        assert camel_to_snake("single") == "single"
        assert camel_to_snake("ALLCAPS") == "allcaps"
        assert camel_to_snake("A") == "a"


class TestSnakeToCamel:
    """Test cases for the snake_to_camel function."""

    def test_basic_conversion(self):
        """Test basic snake_case to camelCase conversion."""
        assert snake_to_camel("snake_case") == "snakeCase"
        assert snake_to_camel("simple_word") == "simpleWord"
        assert snake_to_camel("single") == "single"

    def test_pascal_case(self):
        """Test conversion to PascalCase."""
        assert snake_to_camel("snake_case", pascal_case=True) == "SnakeCase"
        assert snake_to_camel("simple_word", pascal_case=True) == "SimpleWord"
        assert snake_to_camel("single", pascal_case=True) == "Single"

    def test_multiple_underscores(self):
        """Test handling of multiple underscores."""
        assert snake_to_camel("this_is_a_long_name") == "thisIsALongName"
        assert snake_to_camel("this_is_a_long_name", pascal_case=True) == "ThisIsALongName"

    def test_edge_cases(self):
        """Test edge cases."""
        assert snake_to_camel("") == ""
        assert snake_to_camel("_") == ""
        assert snake_to_camel("__") == ""
        assert snake_to_camel("single") == "single"


class TestStripAnsiCodes:
    """Test cases for the strip_ansi_codes function."""

    def test_basic_ansi_removal(self):
        """Test basic ANSI code removal."""
        assert strip_ansi_codes("\033[31mRed text\033[0m") == "Red text"
        assert strip_ansi_codes("\033[32mGreen\033[0m text") == "Green text"

    def test_complex_ansi_codes(self):
        """Test complex ANSI escape sequences."""
        text_with_ansi = "\033[1;31;40mBold red on black\033[0m"
        assert strip_ansi_codes(text_with_ansi) == "Bold red on black"

    def test_no_ansi_codes(self):
        """Test text without ANSI codes."""
        plain_text = "Just plain text"
        assert strip_ansi_codes(plain_text) == plain_text

    def test_edge_cases(self):
        """Test edge cases."""
        assert strip_ansi_codes("") == ""
        assert strip_ansi_codes("\033[0m") == ""
        assert strip_ansi_codes("Start\033[31mMiddle\033[0mEnd") == "StartMiddleEnd"