import re 
import unittest





class StringCalculator:
    def add(self, numbers: str) -> int:
         #Feature 1: Leerer String ergibt 0
        if not numbers:
          return 0
        
        

        # Vorbereitung für weiter features 
        delimiters = [",", "\n"]
        if numbers.startswith("//"):
            delimiter_end_index = numbers.index("\n")
            delimiter_section = numbers[2:delimiter_end_index]
            numbers = numbers[delimiter_end_index + 1:]

         # Feature 7: Delimiter beliebiger Länge im Format //[***]
            if delimiter_section.startswith("[") and delimiter_section.endswith("]"):
                delimiter = re.escape(delimiter_section[1:-1])
            else:
                delimiter = re.escape(delimiter_section)

            delimiters.append(delimiter)

        # Feature 3: Erlaube Zeilenumbrüche als Trenner
        split_pattern = "|".join(delimiters)
        number_list = re.split(split_pattern, numbers)


        

        # Feature 4: Negativzahlen abfangen
        negatives = []
        for num in number_list:
            if num.strip() != "":
                value = int(num)
                if value < 0:
                    negatives.append(value)

        # Exception bei negativen Zahlen
        if negatives:
            raise ValueError(f"Negative numbers are not allowed: {', '.join(map(str, negatives))}")

         #Feature 2: Beliebig viele Zahlen summieren
        return sum(int(n) for n in number_list if n.strip() != "" and int(n) <= 1000)



class TestStringCalculator(unittest.TestCase):
    """Test suite for the StringCalculator class."""

    def setUp(self):
        """neue Instanz des StringCalculators vor jedem Test"""
        self.calculator = StringCalculator()

    def test_empty_string_returns_zero(self):
        """Feature 1: Leerer String soll 0 ergeben"""
        self.assertEqual(self.calculator.add(""), 0)

    def test_single_number_returns_value(self):
        """Ein einzelner Wert soll zurückgegeben werden"""
        self.assertEqual(self.calculator.add("1"), 1)

    def test_two_numbers_return_sum(self):
        """Zwei Zahlen sollen summiert werden"""
        self.assertEqual(self.calculator.add("1,2"), 3)

    def test_add_multiple_numbers(self):
        """Feature 2: Mehrere Zahlen summieren"""
        self.assertEqual(self.calculator.add("1,2,3,4,5"), 15)

    def test_add_numbers_with_newlines(self):
        """Feature 3: Zeilenumbrüche als Trennzeichen"""
        self.assertEqual(self.calculator.add("1\n2\n3"), 6)

    def test_add_negative_numbers(self):
        """Feature 4: Negative Zahlen sollen Fehler werfen"""
        with self.assertRaises(ValueError) as e:
            self.calculator.add("-1,2,-3")
        self.assertEqual(str(e.exception), "Negative numbers are not allowed: -1, -3")

    def test_add_numbers_with_custom_delimiter(self):
        """Feature 5: Benutzerdefiniertes Trennzeichen"""
        self.assertEqual(self.calculator.add("//;\n1;2;3"), 6)    

    def test_add_numbers_with_custom_delimiter_different_symbol(self):
        """Feature 5: Benutzerdefiniertes Trennzeichen mit anderem Symbol"""
        self.assertEqual(self.calculator.add("//#\n4#5#6"), 15)

    def test_custom_delimiter_with_multiple_numbers(self):
        """
        Kombinierter Test für:
        feature 5 und feature 2
        Erwartet wird die korrekte Addition von sechs durch ein benutzerdefiniertes Zeichen getrennten Zahlen.
        """
        self.assertEqual(self.calculator.add("//:\n1:2:3:4:5:6"), 21)    

    def test_add_numbers_greater_than_1000(self):
        """Feature6 test"""
        self.assertEqual(self.calculator.add("1,1001,2,3"), 6)

    def test_add_numbers_with_newlines_and_ignore_above_1000(self):
        """Feature 3 und 6 test Zeilenumbruch als trenner, Zahlen>1000 ignorieren"""
        self.assertEqual(self.calculator.add("1\n2\n1000\n1001"), 1003)
    
    def test_add_numbers_with_custom_delimiter_long_length(self):
        """Benutzerdefinierte Trennzeichen beliebig lang """
        self.assertEqual(self.calculator.add("//[***]\n1***2***3"), 6)

    def test_custom_long_delimiter_with_large_number_ignored(self):
        """FEature 6 und 7 test Benutzerdefinierte Delimiter Länge und zahl über 1000 wird ignoriert"""
        self.assertEqual(self.calculator.add("//[***]\n1***1001***2"), 3) 
        
    def test_custom_long_delimiter_with_negative_numbers(self):
        """Feature 4 und 7: Benutzerdefinierter Delimiter beliebiger Länge + negative Zahlen"""
        with self.assertRaises(ValueError) as e:
             self.calculator.add("//[***]\n1***-2***3***-4")
        self.assertEqual(str(e.exception), "Negative numbers are not allowed: -2, -4")
    
    



if __name__ == '__main__':
    unittest.main()