"""Typed, privacy-minimized values emitted by the historical importer."""

from __future__ import annotations

from dataclasses import asdict, dataclass
from typing import NewType


CanonicalDay = NewType("CanonicalDay", int)


@dataclass(frozen=True, slots=True)
class SourceRecord:
    """One immutable source explicitly authorized by the raw-history manifest."""

    source_path: str
    sha256: str
    range_label: str


@dataclass(frozen=True, slots=True)
class BaselineEntry:
    """One date-keyed, structured historical measurement without source prose."""

    day: CanonicalDay
    recorded_date: str
    source_path: str
    source_sha256: str
    section_anchor: str
    weight_kg: float | None
    sleep_hours: float | None
    calories_kcal: int | None
    training_tokens: tuple[str, ...]
    digestion_status: str | None
    pain_tokens: tuple[str, ...]

    def to_storage_dict(self) -> dict[str, str | int | float | None | tuple[str, ...]]:
        """Produce the exact structured values permitted in profile-local storage."""
        return asdict(self)


@dataclass(frozen=True, slots=True)
class DuplicateDay:
    """Auditable repeated day anchors, without retaining their narrative headings."""

    day: CanonicalDay
    source_anchors: tuple[str, ...]
    conflicting_fields: tuple[str, ...]

    def to_storage_dict(self) -> dict[str, int | tuple[str, ...]]:
        """Serialize only canonical anchors and field names, never source content."""
        return asdict(self)


@dataclass(frozen=True, slots=True)
class Reconciliation:
    """Overlap and conflict details required to audit canonical selection."""

    duplicate_days: tuple[DuplicateDay, ...]

    def to_storage_dict(self) -> dict[str, tuple[dict[str, int | tuple[str, ...]], ...]]:
        """Serialize reconciliation evidence without free text."""
        return {"duplicate_days": tuple(item.to_storage_dict() for item in self.duplicate_days)}


@dataclass(frozen=True, slots=True)
class Coverage:
    """Observed daily-record coverage and per-metric gaps."""

    first_observed_day: CanonicalDay
    last_observed_day: CanonicalDay
    missing_days: tuple[CanonicalDay, ...]
    days_without_measurements: tuple[CanonicalDay, ...]
    days_with_weight: tuple[CanonicalDay, ...]
    days_with_sleep: tuple[CanonicalDay, ...]

    def to_storage_dict(self) -> dict[str, int | tuple[int, ...]]:
        """Serialize coverage as canonical day tokens only."""
        return asdict(self)


@dataclass(frozen=True, slots=True)
class Baseline:
    """Full parser result before it is committed as append-only profile events."""

    entries: tuple[BaselineEntry, ...]
    coverage: Coverage
    reconciliation: Reconciliation

    def to_storage_dict(self) -> dict[str, object]:
        """Return a reproducible, prose-free baseline storage payload."""
        return {
            "storage_version": "1.0",
            "entries": tuple(item.to_storage_dict() for item in self.entries),
            "coverage": self.coverage.to_storage_dict(),
            "reconciliation": self.reconciliation.to_storage_dict(),
        }
