"""
Data processing utilities for working with lists and numbers.
"""

from typing import Dict, List, Union

Number = Union[int, float]


def filter_even(numbers: List[int]) -> List[int]:
    """
    Filter even numbers from a list.

    Args:
        numbers: List of integers

    Returns:
        List containing only even numbers

    Example:
        >>> filter_even([1, 2, 3, 4, 5, 6])
        [2, 4, 6]
        >>> filter_even([1, 3, 5])
        []
    """
    return [num for num in numbers if num % 2 == 0]


def sum_list(numbers: List[Number]) -> Number:
    """
    Calculate the sum of numbers in a list.

    Args:
        numbers: List of numbers

    Returns:
        Sum of all numbers

    Example:
        >>> sum_list([1, 2, 3, 4, 5])
        15
        >>> sum_list([1.5, 2.5, 3.0])
        7.0
    """
    return sum(numbers)


def get_statistics(numbers: List[Number]) -> Dict[str, Number]:
    """
    Calculate basic statistics for a list of numbers.

    Args:
        numbers: List of numbers

    Returns:
        Dictionary containing min, max, mean, and sum

    Raises:
        ValueError: If the list is empty

    Example:
        >>> stats = get_statistics([1, 2, 3, 4, 5])
        >>> stats['mean']
        3.0
        >>> stats['max']
        5
    """
    if not numbers:
        raise ValueError("Cannot calculate statistics for an empty list")

    return {
        "min": min(numbers),
        "max": max(numbers),
        "mean": sum(numbers) / len(numbers),
        "sum": sum(numbers),
        "count": len(numbers),
    }


def find_median(numbers: List[Number]) -> float:
    """
    Find the median value in a list of numbers.

    Args:
        numbers: List of numbers

    Returns:
        Median value

    Raises:
        ValueError: If the list is empty

    Example:
        >>> find_median([1, 2, 3, 4, 5])
        3.0
        >>> find_median([1, 2, 3, 4])
        2.5
        >>> find_median([5, 1, 3, 2, 4])
        3.0
    """
    if not numbers:
        raise ValueError("Cannot find median of an empty list")

    sorted_numbers = sorted(numbers)
    n = len(sorted_numbers)

    if n % 2 == 0:
        # Even number of elements: average of middle two
        return (sorted_numbers[n // 2 - 1] + sorted_numbers[n // 2]) / 2
    else:
        # Odd number of elements: middle element
        return float(sorted_numbers[n // 2])


def remove_duplicates(items: List) -> List:
    """
    Remove duplicate items from a list while preserving order.

    Args:
        items: List of items (can be any hashable type)

    Returns:
        List with duplicates removed

    Example:
        >>> remove_duplicates([1, 2, 2, 3, 3, 3, 4])
        [1, 2, 3, 4]
        >>> remove_duplicates(['a', 'b', 'a', 'c', 'b'])
        ['a', 'b', 'c']
        >>> remove_duplicates([])
        []
    """
    seen = set()
    result = []
    for item in items:
        if item not in seen:
            seen.add(item)
            result.append(item)
    return result
