"""Shared utilities for therismos modules.

This module provides common utilities used across expression, sorting, and
grouping modules to reduce code duplication while maintaining separation of concerns.
"""

from __future__ import annotations

from collections.abc import Callable, Iterable
from dataclasses import dataclass
from typing import Generic, TypeVar

T = TypeVar("T")
ItemT = TypeVar("ItemT")


@dataclass(frozen=True)
class OptimizationRecord(Generic[T]):
    """Record of an optimization transformation.

    Generic optimization record that can be used for any type of optimization
    (expressions, sorting, grouping).

    :ivar before: The object before optimization.
    :vartype before: T
    :ivar after: The resulting object after optimization.
    :vartype after: T
    :ivar reason: A description of the optimization rule that was applied.
    :vartype reason: str
    """

    before: T
    after: T
    reason: str


def keep_last_occurrence(items: Iterable[ItemT], key_func: Callable[[ItemT], str]) -> list[ItemT]:
    """Keep only the last occurrence of each item based on a key function.

    When multiple items have the same key, only the last (rightmost) occurrence
    is kept. This is useful for removing redundant specifications where later
    occurrences override earlier ones.

    :param items: The items to filter.
    :type items: Iterable[ItemT]
    :param key_func: Function to extract the key from each item.
    :type key_func: Callable[[ItemT], str]
    :return: List containing only the last occurrence of each key.
    :rtype: list[ItemT]

    Example:
        >>> items = [("a", 1), ("b", 2), ("a", 3), ("c", 4)]
        >>> keep_last_occurrence(items, lambda x: x[0])
        [('b', 2), ('a', 3), ('c', 4)]
    """
    items_list = list(items)

    seen_keys: dict[str, int] = {}
    for i, item in enumerate(items_list):
        seen_keys[key_func(item)] = i

    return [item for i, item in enumerate(items_list) if seen_keys[key_func(item)] == i]


__all__ = [
    "OptimizationRecord",
    "keep_last_occurrence",
]
