"""Extraction schema — the contract between extraction backends and consumers.

These types define what any extraction backend must produce.
Importable without pulling in spaCy or any specific backend.
"""

from __future__ import annotations

from dataclasses import dataclass, field

from aurora_lens.pef.span import Span


@dataclass
class ExtractedClaim:
    """A claim extracted from text before PEF integration."""
    subject: str
    relation: str           # Canonical
    obj: str                # Object text (entity name or literal)
    span: Span
    negated: bool
    evidence: str           # Source text

    provenance: str = "user_input"       # user_input | pre_populated | llm_output | system
    extractor_backend: str = "unknown"  # spacy | llm | rule | manual | unknown
    document_id: str | None = None
    document_locator: str | None = None


@dataclass
class ComparativeAmbiguity:
    """A comparative adjective whose comparand cannot be uniquely determined.

    Produced when a JJR/RBR token modifies "be" and 2+ eligible comparands
    exist in PEF.  Exactly 1 candidate → forced collapse (not reported).
    Zero candidates → ungrounded assertion (not reported).
    """
    adjective: str          # Surface form: "bigger"
    noun: str               # Thing being compared: "stick"
    candidates: list[str]   # Eligible comparands: ["Richard", "Lucy"]


@dataclass
class ExtractionResult:
    """Result of extracting from a single text input."""
    claims: list[ExtractedClaim] = field(default_factory=list)
    entity_mentions: list[str] = field(default_factory=list)
    span: Span = Span.PRESENT
    pronoun_candidates: dict[str, str] = field(default_factory=dict)
        # "she@token_5" -> best-guess entity name
    ambiguous_referents: list[str] = field(default_factory=list)
        # Possessive pronouns that cannot be uniquely resolved (2+ same-category antecedents)
    comparative_ambiguities: list[ComparativeAmbiguity] = field(default_factory=list)
        # Comparative adjectives whose comparand cannot be uniquely determined
    extraction_error: dict | None = None
        # When set: parse failed (e.g. JSON_DECODE_ERROR). Keys: reason, snippet, raw_preview.
