from __future__ import annotations

"""
Receipt types for the Memory Organ.

These receipts make compression and principle updates auditable without
requiring every raw event to persist indefinitely.

Kairos Integration:
- CompressionReceipt captures kairos_start and kairos_end for the window
- Enables cycle-based analysis of compression events
- Bridges working memory to cycle-aware Guardian gating
"""

from datetime import datetime
from typing import Any, Dict, List, Optional, TYPE_CHECKING

from receipts.base import BaseReceipt, Domain
from receipts.compat.pyd import Field

if TYPE_CHECKING:
    from src.organs.kairos_engine import KairosStamp


class CompressionReceipt(BaseReceipt):
    """Represents a Tier 1 -> Tier 2 compression event."""

    receipt_type: str = "CompressionReceipt"

    # Memory Organ scope
    space: str = Field(description="Logical space (e.g., cockpit, labs:loomlabs2).")
    scope_type: str = Field(default="component", description="Scope classification (component, commitment, space).")
    scope_id: str = Field(default="global", description="Identifier for the scope (e.g., governor, guardian).")

    # Time window
    time_start: datetime = Field(description="Window start (inclusive).")
    time_end: datetime = Field(description="Window end (inclusive).")

    # Aggregates
    total_events: int = Field(description="Number of working-memory events processed.")
    counts: Dict[str, int] = Field(default_factory=dict, description="Counts by event_type or category.")
    aggregates: Dict[str, float] = Field(default_factory=dict, description="Numeric aggregates (means, mins, maxes).")

    # Preservation and importance
    notable_events: List[Dict[str, Any]] = Field(
        default_factory=list, description="High-importance events preserved at higher fidelity."
    )
    importance_mean: float = Field(description="Mean importance for the compression window.")
    importance_max: float = Field(description="Max importance for the compression window.")

    # Drift and tempo
    drift: Dict[str, float] = Field(default_factory=dict, description="Drift deltas for tracked principles.")
    tempo: Optional[Dict[str, Any]] = Field(
        default=None, description="Event rate / activity classification for the window."
    )

    # Strategy and bookkeeping
    compression_strategy: str = Field(default="v0", description="Compression strategy identifier.")
    events_compressed: int = Field(description="Events included in compression (typically == total_events).")
    events_preserved: int = Field(description="Events preserved in notable_events.")

    # Tri-temporal bookkeeping (optional to populate)
    observed_at: Optional[datetime] = Field(default=None, description="When the compression was observed.")
    transaction_time: Optional[datetime] = Field(default=None, description="When the compression was recorded.")

    # Kairos cycle information
    kairos_start: Optional["KairosStamp"] = Field(
        default=None, description="Kairos stamp at window start (earliest event)."
    )
    kairos_end: Optional["KairosStamp"] = Field(
        default=None, description="Kairos stamp at window end (latest event)."
    )

    # Domain defaults to governance unless explicitly set by caller
    domain: str = Field(default=Domain.GOVERNANCE.value, description="Receipt domain for routing.")


class PrincipleUpdateReceipt(BaseReceipt):
    """Represents a Tier 2 -> Tier 3 principle update (semantic identity)."""

    receipt_type: str = "PrincipleUpdateReceipt"

    space: str = Field(description="Logical space (e.g., cockpit, labs:loomlabs2).")
    principle: str = Field(description="Principle identifier (e.g., honesty, safety).")

    old_weight: float = Field(description="Previous principle weight.")
    new_weight: float = Field(description="Updated principle weight.")
    drift: float = Field(description="Delta applied (new_weight - old_weight).")

    evidence: Dict[str, Any] = Field(default_factory=dict, description="Evidence supporting the update.")
    compression_ids: List[str] = Field(
        default_factory=list, description="CompressionReceipt IDs considered during this update."
    )

    updated_at: datetime = Field(description="Timestamp when the principle update was applied.")

    # Tri-temporal bookkeeping (optional to populate)
    observed_at: Optional[datetime] = Field(default=None, description="When the update was observed.")
    transaction_time: Optional[datetime] = Field(default=None, description="When the update was recorded.")

    # Domain defaults to governance unless explicitly set by caller
    domain: str = Field(default=Domain.GOVERNANCE.value, description="Receipt domain for routing.")


# Rebuild models after all imports are complete to resolve forward references
def _rebuild_models():
    """Rebuild Pydantic models to resolve forward references."""
    try:
        from src.organs.kairos_engine import KairosStamp
        CompressionReceipt.model_rebuild()
    except ImportError:
        pass  # KairosStamp may not be available in all contexts


_rebuild_models()
