"""Skeleton metadata model for ACMS context compression.

A ``SkeletonMetadata`` captures the auditable state of a skeleton
compression pass: the ratio applied, token counts before and after
compression, and the decision IDs whose context fragments were
compressed.  The model is frozen (immutable) so that once persisted
it cannot be accidentally mutated.

Based on ``docs/specification.md`` ACMS Skeleton section.
"""

from __future__ import annotations

from pydantic import BaseModel, ConfigDict, Field, field_validator


class SkeletonMetadata(BaseModel):
    """Immutable record of a skeleton compression pass.

    Persisted alongside the plan to provide full auditability of
    context inheritance between parent and child plans.

    Attributes:
        ratio: The skeleton_ratio applied (0.0 = no compression,
            1.0 = maximum compression).
        original_tokens: Total token count before compression.
        compressed_tokens: Total token count after compression.
        source_decision_ids: Decision ULIDs whose context fragments
            were included in the compression input.
    """

    ratio: float = Field(
        ...,
        ge=0.0,
        le=1.0,
        description=(
            "Skeleton compression ratio applied "
            "(0.0 = no compression, 1.0 = maximum compression)"
        ),
    )
    original_tokens: int = Field(
        ...,
        ge=0,
        description="Total token count before compression",
    )
    compressed_tokens: int = Field(
        ...,
        ge=0,
        description="Total token count after compression",
    )
    source_decision_ids: tuple[str, ...] = Field(
        default_factory=tuple,
        description=(
            "Decision ULIDs whose context fragments "
            "were included in the compression input"
        ),
    )

    @field_validator("compressed_tokens")
    @classmethod
    def compressed_not_greater_than_original(
        cls: type[SkeletonMetadata],
        v: int,
        info: object,
    ) -> int:
        """Ensure compressed tokens do not exceed original tokens."""
        # info.data contains already-validated fields at this point
        data = getattr(info, "data", {})
        original = data.get("original_tokens")
        if original is not None and v > original:
            raise ValueError(
                f"compressed_tokens ({v}) cannot exceed original_tokens ({original})"
            )
        return v

    model_config = ConfigDict(
        frozen=True,
        str_strip_whitespace=True,
    )
