# ============================================================
# src/accountable_record/stage_030_sources/model.py
# ============================================================
"""Source-material model for Accountable Record stage 030.

WHY:
    Stage 030 establishes the repository's declared source materials: the
    traceable files or directories later stages may reference. This module
    defines the passive data structures used by source loading, validation, and
    pipeline state.

OBS:
    Source records are structural only. They record an identifier, a
    repository-relative path, an optional role label, and whether the path is
    present. They do not parse source contents, interpret meaning, assert truth,
    or assign authority.

REQ:
    Models are frozen dataclasses, matching the plain @dataclass(frozen=True)
    style used across pipeline artifacts.
"""

from dataclasses import dataclass

__all__ = ["SourceRecord", "SourceRegistry", "SourcesArtifact"]


@dataclass(frozen=True)
class SourceRecord:
    """One declared source material, described structurally.

    Attributes:
        source_id: Stable identifier for the source. Unique within a registry.
        rel_path: Repository-relative path to the source material.
        role: Optional structural role label. This is only a label; it asserts
            no interpretation of content.
        present: Whether the path exists under the target repository root.
    """

    source_id: str
    rel_path: str
    role: str | None
    present: bool


@dataclass(frozen=True)
class SourceRegistry:
    """The set of declared sources, indexed by identifier."""

    records: tuple[SourceRecord, ...] = ()

    def by_id(self) -> dict[str, SourceRecord]:
        """Return a mapping of source identifier to record."""
        return {record.source_id: record for record in self.records}

    @property
    def count(self) -> int:
        """Return the number of source records."""
        return len(self.records)


@dataclass(frozen=True)
class SourcesArtifact:
    """Resolved source-material artifact produced by stage 030.

    Attributes:
        target_root: Repository root sources were validated under.
        registry: Declared source records.
    """

    target_root: str
    registry: SourceRegistry
