"""
Dream Domain Receipts

Receipt types for the dreaming subsystem — offline consolidation and learning.
All receipts track $0 cost local model inference during idle time.

---
feature:
  id: feature.dream_receipts
  name: Dream Domain Receipts
  kind: module
  summary: Receipt models for dream cycle events (phases, learnings, consolidation)
  owners: ["@codex"]
  stage: production
  tags: [receipts, organism, dreaming, mlx, p1]
  depends_on: [feature.receipt_writer, feature.dreaming_engine]
  inputs: [Dream cycle events]
  outputs: [Signed receipts in ledger]
  invariants:
    - All receipts are Ed25519-signed
    - Cost is always $0 (local models only)
    - Receipt IDs are globally unique
  risk_axes:
    unsigned_receipt: 0.0  # Enforced by writer
    cost_leak: 0.0        # Local models only
---
"""

from __future__ import annotations

import logging
from datetime import datetime, timezone
from typing import Any, Dict, List, Literal, Optional

from pydantic import Field

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

logger = logging.getLogger(__name__)


# =============================================================================
# Receipt Models
# =============================================================================

class DreamPhaseReceipt(BaseReceipt):
    """
    Receipt emitted for each phase of a dream cycle.

    Tracks individual dream operations (replay, analyze, synthesize, learn, heal).
    """

    receipt_type: str = Field(default="DreamPhaseReceipt", alias="type")
    domain: str = Field(default="dream")

    # Phase identifiers
    dream_id: str = Field(description="ID of the dream cycle this phase belongs to")
    phase: str = Field(description="Phase name (replay_analyze, synthesize_patterns, generate_learnings, consolidate)")

    # Model used
    model: str = Field(
        default="heuristic",
        description="Model used for this phase (e.g., 'llama3.2:3b', 'qwen2.5-coder:7b', 'heuristic')"
    )

    # Execution status
    success: bool = Field(default=False, description="Whether phase completed successfully")
    error: Optional[str] = Field(default=None, description="Error message if failed")

    # Token usage (even though cost is $0, we track for analysis)
    tokens_input: int = Field(default=0, description="Input tokens used")
    tokens_output: int = Field(default=0, description="Output tokens generated")

    # Results
    insights_count: int = Field(
        default=0,
        description="Number of insights/patterns/learnings generated"
    )

    # Timing
    duration_ms: float = Field(
        default=0.0,
        description="Time taken for this phase (ms)"
    )

    # Cost (always $0 for local models)
    cost_usd: float = Field(
        default=0.0,
        description="Cost in USD (always $0 for local dreaming)"
    )

    model_config = ConfigDictLike(json_schema_extra={
        "example": {
            "dream_id": "dream_abc123",
            "phase": "replay_analyze",
            "model": "llama3.2:3b",
            "success": True,
            "tokens_input": 250,
            "tokens_output": 180,
            "insights_count": 5,
            "duration_ms": 1250.5,
            "cost_usd": 0.0,
        }
    })


class DreamCycleReceipt(BaseReceipt):
    """
    Receipt emitted for a complete dream cycle.

    Links all phase receipts into a coherent session with overall metrics.
    """

    receipt_type: str = Field(default="DreamCycleReceipt", alias="type")
    domain: str = Field(default="dream")

    # Dream identifiers
    dream_id: str = Field(description="Unique ID for this dream cycle")
    dream_type: str = Field(
        default="failure_replay",
        description="Type of dream (failure_replay, success_reinforcement, pattern_discovery, etc.)"
    )

    # Phase tracking
    phases_completed: List[str] = Field(
        default_factory=list,
        description="List of completed phases in order"
    )
    phase_receipt_ids: List[str] = Field(
        default_factory=list,
        description="Receipt IDs for each phase"
    )

    # Source data
    source_receipt_count: int = Field(
        default=0,
        description="Number of receipts analyzed during replay"
    )
    failure_count: int = Field(
        default=0,
        description="Number of failures processed"
    )

    # Results
    learnings_generated: int = Field(
        default=0,
        description="Number of lessons learned"
    )
    patterns_discovered: int = Field(
        default=0,
        description="Number of patterns identified"
    )

    # Healing effects
    cortisol_reduction: float = Field(
        default=0.0,
        description="Cortisol reduction applied (0-1)"
    )
    serotonin_boost: float = Field(
        default=0.0,
        description="Serotonin boost applied (0-1)"
    )

    # Token usage (total across all phases)
    total_tokens_input: int = Field(default=0, description="Total input tokens")
    total_tokens_output: int = Field(default=0, description="Total output tokens")

    # Timing
    total_duration_ms: float = Field(
        default=0.0,
        description="Total dream cycle duration (ms)"
    )

    # Cost (always $0!)
    total_cost_usd: float = Field(
        default=0.0,
        description="Total cost in USD (always $0 for local dreaming)"
    )

    # Status
    success: bool = Field(default=False, description="Whether dream completed successfully")
    aborted: bool = Field(default=False, description="Whether dream was interrupted")
    abort_reason: Optional[str] = Field(default=None, description="Reason for interruption")

    model_config = ConfigDictLike(json_schema_extra={
        "example": {
            "dream_id": "dream_abc123",
            "dream_type": "failure_replay",
            "phases_completed": ["replay_analyze", "synthesize_patterns", "generate_learnings", "consolidate"],
            "phase_receipt_ids": ["phase_1", "phase_2", "phase_3", "phase_4"],
            "source_receipt_count": 10,
            "failure_count": 3,
            "learnings_generated": 2,
            "patterns_discovered": 4,
            "cortisol_reduction": 0.05,
            "serotonin_boost": 0.02,
            "total_tokens_input": 850,
            "total_tokens_output": 620,
            "total_duration_ms": 5234.7,
            "total_cost_usd": 0.0,
            "success": True,
        }
    })


class DreamLearningReceipt(BaseReceipt):
    """
    Receipt for a specific learning extracted during dreaming.

    Captures individual lessons that can be applied in future operations.
    """

    receipt_type: str = Field(default="DreamLearningReceipt", alias="type")
    domain: str = Field(default="dream")

    # Learning identifiers
    lesson_id: str = Field(description="Unique ID for this lesson")
    dream_id: str = Field(description="Dream cycle that generated this lesson")
    source_dream_type: str = Field(
        default="failure_replay",
        description="Type of dream that generated this"
    )

    # The lesson
    trigger_pattern: str = Field(
        description="What situation triggers this lesson (e.g., 'timeout error on network call')"
    )
    learned_insight: str = Field(
        description="What was learned (e.g., 'Network calls need retry logic')"
    )
    recommended_action: str = Field(
        description="What to do differently (e.g., 'Add exponential backoff retry')"
    )

    # Metadata
    confidence: float = Field(
        ge=0.0,
        le=1.0,
        default=0.5,
        description="Confidence in this lesson (0-1)"
    )
    domain_tags: List[str] = Field(
        default_factory=list,
        description="Domain tags (e.g., 'networking', 'timeout', 'resilience')"
    )

    # Application tracking
    times_applied: int = Field(
        default=0,
        description="Number of times this lesson was applied"
    )
    times_helpful: int = Field(
        default=0,
        description="Number of times it helped"
    )
    times_unhelpful: int = Field(
        default=0,
        description="Number of times it didn't help"
    )

    model_config = ConfigDictLike(json_schema_extra={
        "example": {
            "lesson_id": "lesson_xyz789",
            "dream_id": "dream_abc123",
            "source_dream_type": "failure_replay",
            "trigger_pattern": "timeout error on network call",
            "learned_insight": "Network calls need retry logic",
            "recommended_action": "Add exponential backoff retry",
            "confidence": 0.7,
            "domain_tags": ["networking", "timeout", "resilience"],
            "times_applied": 0,
            "times_helpful": 0,
            "times_unhelpful": 0,
        }
    })


class DreamSchedulerReceipt(BaseReceipt):
    """
    Receipt for dream scheduler events.

    Tracks when dreams are triggered by heartbeat idle detection.
    """

    receipt_type: str = Field(default="DreamSchedulerReceipt", alias="type")
    domain: str = Field(default="dream")

    # Event type
    event: str = Field(
        description="Scheduler event (dream_triggered, dream_completed, dream_aborted)"
    )

    # Context
    idle_time_seconds: float = Field(
        default=0.0,
        description="How long the organism was idle before dream trigger"
    )
    heartbeat_beat_number: int = Field(
        default=0,
        description="Heartbeat beat number when dream triggered"
    )

    # Dream reference (if applicable)
    dream_id: Optional[str] = Field(
        default=None,
        description="ID of the dream that was triggered/completed/aborted"
    )

    # Status
    success: bool = Field(default=True, description="Whether operation succeeded")
    error: Optional[str] = Field(default=None, description="Error message if failed")

    model_config = ConfigDictLike(json_schema_extra={
        "example": {
            "event": "dream_triggered",
            "idle_time_seconds": 35.2,
            "heartbeat_beat_number": 352,
            "dream_id": "dream_abc123",
            "success": True,
        }
    })


# =============================================================================
# Convenience constructors
# =============================================================================

def create_dream_phase_receipt(
    phase: str,
    model: str = "heuristic",
    success: bool = True,
    tokens_input: int = 0,
    tokens_output: int = 0,
    insights_count: int = 0,
    duration_ms: float = 0.0,
    dream_id: Optional[str] = None,
    error: Optional[str] = None,
    **kwargs
) -> DreamPhaseReceipt:
    """Create a dream phase receipt."""
    import uuid

    if dream_id is None:
        dream_id = f"dream_{uuid.uuid4().hex[:12]}"

    return DreamPhaseReceipt(
        receipt_id=f"dream_phase_{uuid.uuid4().hex[:16]}",
        dream_id=dream_id,
        phase=phase,
        model=model,
        success=success,
        tokens_input=tokens_input,
        tokens_output=tokens_output,
        insights_count=insights_count,
        duration_ms=duration_ms,
        cost_usd=0.0,  # Always $0
        error=error,
        **kwargs
    )


def create_dream_cycle_receipt(
    dream_id: str,
    dream_type: str = "failure_replay",
    phases_completed: Optional[List[str]] = None,
    phase_receipt_ids: Optional[List[str]] = None,
    learnings_generated: int = 0,
    patterns_discovered: int = 0,
    total_tokens_input: int = 0,
    total_tokens_output: int = 0,
    total_duration_ms: float = 0.0,
    success: bool = True,
    **kwargs
) -> DreamCycleReceipt:
    """Create a dream cycle receipt."""
    return DreamCycleReceipt(
        receipt_id=f"dream_cycle_{dream_id}",
        dream_id=dream_id,
        dream_type=dream_type,
        phases_completed=phases_completed or [],
        phase_receipt_ids=phase_receipt_ids or [],
        learnings_generated=learnings_generated,
        patterns_discovered=patterns_discovered,
        total_tokens_input=total_tokens_input,
        total_tokens_output=total_tokens_output,
        total_duration_ms=total_duration_ms,
        total_cost_usd=0.0,  # Always $0
        success=success,
        **kwargs
    )


def create_dream_learning_receipt(
    lesson_id: str,
    dream_id: str,
    trigger_pattern: str,
    learned_insight: str,
    recommended_action: str,
    confidence: float = 0.5,
    domain_tags: Optional[List[str]] = None,
    **kwargs
) -> DreamLearningReceipt:
    """Create a dream learning receipt."""
    return DreamLearningReceipt(
        receipt_id=f"dream_learning_{lesson_id}",
        lesson_id=lesson_id,
        dream_id=dream_id,
        trigger_pattern=trigger_pattern,
        learned_insight=learned_insight,
        recommended_action=recommended_action,
        confidence=confidence,
        domain_tags=domain_tags or [],
        **kwargs
    )


def create_dream_scheduler_receipt(
    event: str,
    idle_time_seconds: float = 0.0,
    heartbeat_beat_number: int = 0,
    dream_id: Optional[str] = None,
    success: bool = True,
    error: Optional[str] = None,
    **kwargs
) -> DreamSchedulerReceipt:
    """Create a dream scheduler receipt."""
    import uuid

    return DreamSchedulerReceipt(
        receipt_id=f"dream_scheduler_{uuid.uuid4().hex[:16]}",
        event=event,
        idle_time_seconds=idle_time_seconds,
        heartbeat_beat_number=heartbeat_beat_number,
        dream_id=dream_id,
        success=success,
        error=error,
        **kwargs
    )
