from typing import List
from typing import Optional


def get_unique_substrings(
    strings: List[str],
    min_length: Optional[int] = None,
    max_length: Optional[int] = None,
    on_equal: str = "ignore",
) -> List[str]:
    """Get the unique starting substring for a list of strings;
    this method is useful for hash values, when you want to reduce
    their size without losing context of which hash they are.

    min_length is the minimum length desired for the substrings to
    be returned

    on_equal specifies what to do in case of equal strings; the
    default behaviour is to 'ignore' the problem, otherwise an error
    can also be raised with 'raise'"""

    on_equal = on_equal.lower()
    if on_equal not in ("ignore", "raise"):
        raise ValueError("Invalid on_equal value provided!")

    max_len = min(len(s) for s in strings)
    if max_len < 1:
        raise ValueError("Cannot get unique substrings for empty strings")
    characters_needed = 1
    substrings = [s[:characters_needed] for s in strings]

    while len(substrings) != len(set(substrings)) and characters_needed <= max_len:
        characters_needed += 1
        substrings = [s[:characters_needed] for s in strings]

    if characters_needed > max_len and on_equal == "raise":
        raise ValueError("Strings are equal!")

    if not min_length:
        min_length = 0
    if not max_length:
        max_length = max_len

    if max_length < min_length:
        min_length, max_length = max_length, min_length

    if characters_needed < min_length:
        limit = min_length
    elif characters_needed > max_length:
        limit = max_length
    else:  # min_length <= characters_needed <= max_length
        limit = characters_needed

    substrings = [s[:limit] for s in strings]
    return substrings