"""Immutable similarity result dataclass.

This module defines :class:`SimilarityResult`, the output of
:class:`~similarity.engine.SimilarityEngine.compare()`.
"""

from __future__ import annotations

from collections.abc import Mapping
from dataclasses import dataclass, field
from types import MappingProxyType


@dataclass(frozen=True)
class SimilarityResult:
    """Immutable result of comparing two MusicDNAVector objects.

    Attributes:
        track_a: UUID of the first track.
        track_b: UUID of the second track.
        metric: Name of the metric used (e.g. ``"cosine"``).
        similarity_score: Overall similarity in [0.0, 1.0].
        distance: Raw distance value (metric-dependent).
        confidence: Confidence score in [0.0, 1.0].  Initial
            implementation always returns 1.0.
        per_category_scores: Immutable mapping of category name to
            similarity score in [0.0, 1.0].
        top_contributors: Ordered list of feature identifiers with
            the largest contribution to the difference.
        vector_dimension: Dimension of the compared vectors (512).
        schema_version: Music DNA schema version (e.g. ``"1.0"``).
    """

    track_a: str
    track_b: str
    metric: str
    similarity_score: float
    distance: float
    confidence: float
    per_category_scores: Mapping[str, float] = field(
        default_factory=lambda: MappingProxyType({})
    )
    top_contributors: list[str] = field(default_factory=list)
    vector_dimension: int = 512
    schema_version: str = "1.0"

    def __post_init__(self) -> None:
        """Freeze the per_category_scores mapping."""
        if not isinstance(self.per_category_scores, MappingProxyType):
            object.__setattr__(
                self,
                "per_category_scores",
                MappingProxyType(dict(self.per_category_scores)),
            )
