"""Utilities for working with hashed identifiers in boxology models."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Iterable, Union

from bclearer_orchestration_services.identification_services.hash_service.hash_creator import (
    create_hash,
)


@dataclass(frozen=True, slots=True)
class ObjectHashes:
    """Represents the hashed identity of a boxology element."""

    value: str

    @classmethod
    def from_string(cls, identifier: str) -> ObjectHashes:
        """Create a hash from a single identifier string."""

        return cls.from_components([identifier])

    @classmethod
    def from_components(cls, components: Iterable[object]) -> ObjectHashes:
        """Create a hash from one or more components."""

        hashed_value = create_hash(inputs=[str(component) for component in components])
        return cls(value=hashed_value)

    @classmethod
    def from_hash(cls, hash_value: str) -> ObjectHashes:
        """Wrap an already hashed value without modification."""

        return cls(value=hash_value)

    def __str__(self) -> str:  # pragma: no cover - trivial representation
        return self.value


ObjectHashLike = Union[ObjectHashes, str]


def normalise_object_hash(identifier: ObjectHashLike) -> ObjectHashes:
    """Ensure the provided identifier is represented as an ``ObjectHashes`` instance."""

    if isinstance(identifier, ObjectHashes):
        return identifier

    return ObjectHashes.from_string(identifier)


__all__ = ["ObjectHashes", "ObjectHashLike", "normalise_object_hash"]

