"""Atom meta — memory_scope · disclosure · provenance（v0.5 schema）。"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Literal

MemoryScope = Literal["subject", "object"]
TrustTier = Literal["curated", "web", "user_paste", "guest_reference"]


@dataclass
class DisclosureMeta:
    told_to: list[str] = field(default_factory=list)
    entities: list[str] = field(default_factory=list)
    source_user: str | None = None

    @classmethod
    def from_dict(cls, raw: dict[str, Any] | None) -> DisclosureMeta:
        if not isinstance(raw, dict):
            return cls()
        told = raw.get("told_to")
        entities = raw.get("entities")
        return cls(
            told_to=[str(x) for x in told if isinstance(x, str)] if isinstance(told, list) else [],
            entities=[str(x) for x in entities if isinstance(x, str)] if isinstance(entities, list) else [],
            source_user=str(raw["source_user"]) if raw.get("source_user") is not None else None,
        )


@dataclass
class ProvenanceMeta:
    type: str | None = None
    url: str | None = None
    trust_tier: TrustTier | None = None
    reality_anchor: str | None = None

    @classmethod
    def from_dict(cls, raw: dict[str, Any] | None) -> ProvenanceMeta:
        if not isinstance(raw, dict):
            return cls()
        tier = raw.get("trust_tier")
        return cls(
            type=str(raw["type"]) if raw.get("type") is not None else None,
            url=str(raw["url"]) if raw.get("url") is not None else None,
            trust_tier=tier if tier in ("curated", "web", "user_paste", "guest_reference") else None,
            reality_anchor=str(raw["reality_anchor"]) if raw.get("reality_anchor") is not None else None,
        )


@dataclass
class AtomMeta:
    memory_scope: MemoryScope = "subject"
    object_anchor: str | None = None
    disclosure: DisclosureMeta = field(default_factory=DisclosureMeta)
    subject_eligible: bool = True
    provenance: ProvenanceMeta = field(default_factory=ProvenanceMeta)

    @classmethod
    def from_dict(cls, raw: dict[str, Any] | None) -> AtomMeta:
        if not isinstance(raw, dict):
            return cls()
        scope = raw.get("memory_scope")
        memory_scope: MemoryScope = "object" if scope == "object" else "subject"
        anchor = raw.get("object_anchor")
        eligible = raw.get("subject_eligible")
        return cls(
            memory_scope=memory_scope,
            object_anchor=str(anchor) if anchor is not None else None,
            disclosure=DisclosureMeta.from_dict(raw.get("disclosure")),
            subject_eligible=bool(eligible) if eligible is not None else memory_scope == "subject",
            provenance=ProvenanceMeta.from_dict(raw.get("provenance")),
        )

    def to_dict(self) -> dict[str, Any]:
        out: dict[str, Any] = {
            "memory_scope": self.memory_scope,
            "subject_eligible": self.subject_eligible,
        }
        if self.object_anchor is not None:
            out["object_anchor"] = self.object_anchor
        if self.disclosure.told_to or self.disclosure.entities or self.disclosure.source_user:
            out["disclosure"] = {
                "told_to": list(self.disclosure.told_to),
                "entities": list(self.disclosure.entities),
            }
            if self.disclosure.source_user:
                out["disclosure"]["source_user"] = self.disclosure.source_user
        prov = {}
        if self.provenance.type:
            prov["type"] = self.provenance.type
        if self.provenance.url:
            prov["url"] = self.provenance.url
        if self.provenance.trust_tier:
            prov["trust_tier"] = self.provenance.trust_tier
        if self.provenance.reality_anchor:
            prov["reality_anchor"] = self.provenance.reality_anchor
        if prov:
            out["provenance"] = prov
        return out


def parse_atom_meta(raw: dict[str, Any] | None) -> AtomMeta:
    return AtomMeta.from_dict(raw)
