import dataclasses
import enum
from collections.abc import Iterable
from typing import Generic, Self, TypeVar

T = TypeVar("T")
NGrams = dict[int, list[str]]


class Order(enum.Enum):
    ASC = "asc"
    DESC = "desc"


class OrderBy(enum.Enum):
    TIMES_PLAYED = "times_played"
    LAST_PLAYED = "last_played"


@dataclasses.dataclass(frozen=True)
class OrderParams:
    order_by: OrderBy
    order: Order


@dataclasses.dataclass(order=True)
class SearchMatch:
    distance: float
    ngram: str

    @classmethod
    def combine_matches(cls, matches: Iterable[Self]) -> Self:
        ngrams, distances = zip(*((match.ngram, match.distance) for match in matches))
        return cls(
            ngram=', '.join(ngrams),
            distance=sum(distances)/len(distances)
        )


@dataclasses.dataclass
class QueryResult(Generic[T]):
    result: T
    distance: float
    ngram: str
