"""Structured representation of boxology stereotypes."""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Iterable, Iterator, List, Union


@dataclass(slots=True)
class Stereotypes:
    """Captures a reusable semantic qualifier for boxology elements."""

    name: str
    description: str | None = None
    properties: dict[str, Any] = field(default_factory=dict)

    def matches(self, candidate: str) -> bool:
        """Return ``True`` when the stereotype name matches the candidate."""

        return self.name == candidate


StereotypeLike = Union[Stereotypes, str]


def _iter_normalised(
    stereotypes: Iterable[StereotypeLike] | None,
) -> Iterator[Stereotypes]:
    for stereotype in stereotypes or []:
        if isinstance(stereotype, Stereotypes):
            yield stereotype
        else:
            yield Stereotypes(name=stereotype)


def normalise_stereotypes(
    stereotypes: Iterable[StereotypeLike] | None,
) -> List[Stereotypes]:
    """Return stereotypes converted into :class:`Stereotypes` instances."""

    return list(_iter_normalised(stereotypes))


def stereotypes_include(
    stereotypes: Iterable[Stereotypes], candidate: str
) -> bool:
    """Check whether any stereotype matches the provided candidate."""

    return any(stereotype.matches(candidate) for stereotype in stereotypes)

