"""
Prophecy Domain Receipts

Receipt types for the Prophecy Engine (temporal causal graph over operation history).

All prophecy receipts are Ed25519-signed, JCS-canonical, and linked to the operations
they predict/evaluated.

---
feature:
  id: feature.prophecy_receipts
  name: Prophecy Domain Receipts
  kind: module
  summary: Receipt models for prophecy engine events (prediction, evaluation, learning)
  owners: ["@haiku"]
  stage: experimental
  tags: [receipts, prophecy, temporal, learning]
  depends_on: [feature.receipt_writer, feature.prophecy_engine]
  inputs: [Prophecy.predict() calls, operation outcomes]
  outputs: [Signed prophecy receipts in ledger]
  invariants:
    - All prophecy receipts are Ed25519-signed
    - Each prophecy is linked to the plan it evaluated
    - Outcome updates form a causal chain
---
"""

from __future__ import annotations

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

from pydantic import Field

from receipts.base import BaseReceipt

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------


def _normalize_ts(value: Optional[datetime]) -> Optional[datetime]:
    """Normalize timestamp to UTC with milliseconds trimmed."""
    if value is None:
        return None
    if value.tzinfo is None:
        value = value.replace(tzinfo=timezone.utc)
    else:
        value = value.astimezone(timezone.utc)
    if value.microsecond:
        value = value.replace(microsecond=(value.microsecond // 1000) * 1000)
    return value

# =============================================================================
# Enums
# =============================================================================


class PredictionRiskLevel(str, Enum):
    """Historical risk assessment."""
    SAFE = "safe"
    CAUTION = "caution"
    DANGER = "danger"
    UNKNOWN = "unknown"


class CoherenceBandLabel(str, Enum):
    """Coherence quantization band."""
    CRITICAL = "critical"
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"
    PERFECT = "perfect"


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


class ProphecyReceipt(BaseReceipt):
    """
    Receipt emitted when Prophecy Engine makes a prediction.

    Answers: "Given this plan, what does history predict?"
    Links prediction → final outcome for learning.
    """

    receipt_type: str = Field(default="ProphecyReceipt", alias="type")
    domain: str = Field(default="prophecy")

    # Prediction identity
    prophecy_id: str = Field(description="Unique ID for this prophecy")
    plan_id: Optional[str] = Field(default=None, description="Plan this prophecy evaluated")

    # The pattern being predicted
    glyph_sequence: List[str] = Field(description="Glyphs in the planned operation")
    operation_domain: str = Field(description="Domain (organism, healthcare, etc.)")
    operation_type: str = Field(description="Type of operation (plan_execution, recovery, etc.)")
    coherence_band: CoherenceBandLabel = Field(description="Coherence quantization band")
    symbiosis_state: str = Field(description="Task symbiosis state at prediction time")

    # Historical statistics
    pattern_observation_count: int = Field(description="How many times we've seen this pattern")
    pattern_success_count: int = Field(description="How many succeeded")
    pattern_failure_count: int = Field(description="How many failed")

    # The prediction
    expected_success_rate: float = Field(description="Predicted probability of success (0.0–1.0)")
    expected_value: float = Field(description="Expected value if succeeds")
    expected_roi: float = Field(description="Expected return on investment")

    # Risk assessment
    risk_level: PredictionRiskLevel = Field(description="SAFE / CAUTION / DANGER / UNKNOWN")
    confidence: float = Field(description="Confidence in prediction (0.0–1.0)")

    # Guardian guidance
    suggested_strictness_modifier: float = Field(
        description="Multiply Guardian's dignity floor by this (0.8–1.5)"
    )
    coherence_minimum_safe: float = Field(
        description="Recommendation: don't execute this below this coherence"
    )

    # Diagnosis
    dominant_failure_mode: Optional[str] = Field(
        default=None, description="Most common failure reason from history"
    )
    risk_notes: List[str] = Field(
        default_factory=list, description="Diagnostic notes about the pattern"
    )

    # Link to outcome (filled in later when operation completes)
    outcome_id: Optional[str] = Field(default=None, description="ProphecyOutcomeReceipt ID (once known)")
    outcome_matched_prediction: Optional[bool] = Field(
        default=None, description="Did the actual outcome match the prediction?"
    )


class ProphecyOutcomeReceipt(BaseReceipt):
    """
    Receipt emitted when a prophesied operation completes.

    Links back to ProphecyReceipt for evaluation of prediction accuracy.
    Allows learning: "Was our prophecy right?"
    """

    receipt_type: str = Field(default="ProphecyOutcomeReceipt", alias="type")
    domain: str = Field(default="prophecy")

    # Linkage
    prophecy_id: str = Field(description="ID of the prophecy this evaluated")
    operation_id: str = Field(description="ID of the operation that executed")
    plan_id: Optional[str] = Field(default=None, description="Plan that was executed")

    # Actual outcome
    success: bool = Field(description="Did the operation succeed?")
    value_realized: float = Field(description="Actual value achieved")
    cost_realized: float = Field(description="Actual cost incurred")
    roi_realized: float = Field(description="Actual ROI (value / cost)")

    # Context at execution
    coherence_at_execution: float = Field(description="Actual coherence during execution")
    symbiosis_state_at_execution: str = Field(description="Actual symbiosis state")

    # Failure details (if failed)
    failure_reason: Optional[str] = Field(default=None, description="Why did it fail?")
    failure_is_expected: bool = Field(
        default=False, description="Was this failure mode predicted?"
    )

    # Prediction accuracy assessment
    predicted_success_rate: float = Field(description="What the prophecy predicted")
    was_prediction_accurate: bool = Field(
        description="Did the outcome match prediction thresholds?"
    )
    prediction_error: Optional[str] = Field(
        default=None,
        description="If inaccurate, what went wrong? (e.g., 'over-optimistic', 'high variance')",
    )

    # Learning signal
    update_prophecy_index: bool = Field(
        default=True, description="Should this outcome update the prophecy index?"
    )

    # Optional linkage back to future snapshot for evaluation
    prophecy_future_snapshot_id: Optional[str] = Field(
        default=None,
        description="Future snapshot ID this outcome evaluates (if emitted)",
    )


class ProphecyCalibrationReport(BaseReceipt):
    """
    Periodic report on prophecy engine calibration.

    Answers: "How well are our prophecies performing?"
    """

    receipt_type: str = Field(default="ProphecyCalibrationReport", alias="type")
    domain: str = Field(default="prophecy")

    # Reporting period
    report_id: str = Field(description="Unique ID for this report")
    period_start: datetime = Field(description="Start of observation window")
    period_end: datetime = Field(description="End of observation window")
    observations_count: int = Field(description="Number of prophecies issued in period")

    # Overall performance
    predictions_total: int = Field(description="Total prophecies made")
    predictions_accurate: int = Field(description="Predictions that matched outcome")
    calibration_score: float = Field(description="0.0–1.0 accuracy score")

    # By risk level
    predictions_safe: int = Field(default=0)
    safe_accuracy: float = Field(default=0.0)

    predictions_caution: int = Field(default=0)
    caution_accuracy: float = Field(default=0.0)

    predictions_danger: int = Field(default=0)
    danger_accuracy: float = Field(default=0.0)

    predictions_unknown: int = Field(default=0)
    unknown_accuracy: float = Field(default=0.0)

    # Insights
    overconfident_patterns: List[str] = Field(
        default_factory=list,
        description="Patterns we were overconfident about",
    )
    underconfident_patterns: List[str] = Field(
        default_factory=list,
        description="Patterns we were too cautious about",
    )
    emerging_trends: List[str] = Field(
        default_factory=list,
        description="New patterns or regime changes detected",
    )

    # Recommendations
    recommended_strictness_adjustments: Dict[str, float] = Field(
        default_factory=dict,
        description="Pattern key -> suggested strictness modifier",
    )


class PatternStatsSnapshot(BaseReceipt):
    """
    Snapshot of prophecy index statistics for archival.

    Useful for debugging, auditing, and long-term trend analysis.
    """

    receipt_type: str = Field(default="PatternStatsSnapshot", alias="type")
    domain: str = Field(default="prophecy")

    # Metadata
    snapshot_id: str = Field(description="Unique ID for this snapshot")
    patterns_observed: int = Field(description="Number of unique patterns in index")
    total_observations: int = Field(description="Total observations across all patterns")

    # Top performers
    safest_patterns: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="Top 10 safest patterns (highest success rate)",
    )
    most_valuable_patterns: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="Top 10 highest-ROI patterns",
    )

    # Most risky
    most_dangerous_patterns: List[Dict[str, Any]] = Field(
        default_factory=list,
        description="Top 10 most dangerous patterns (lowest success rate)",
    )

    # Coherence analysis
    coherence_band_performance: Dict[str, float] = Field(
        default_factory=dict,
        description="Average success rate per coherence band",
    )

    # Symbiosis analysis
    symbiosis_performance: Dict[str, float] = Field(
        default_factory=dict,
        description="Average success rate per symbiosis state",
    )

    # Failure mode distribution
    top_failure_modes: Dict[str, int] = Field(
        default_factory=dict,
        description="Most common failure reasons (count)",
    )


class ProphecyFutureSnapshotReceipt(BaseReceipt):
    """
    Snapshot of the *expected* future state implied by a prophecy.

    Bridges ProphecyReceipt ("what we think will happen") to an auditable
    future-world description that can be compared against the eventual outcome.
    """

    receipt_type: str = Field(default="ProphecyFutureSnapshotReceipt", alias="type")
    domain: str = Field(default="prophecy")

    # Linkage
    snapshot_id: str = Field(description="Unique ID for this future snapshot")
    prophecy_id: str = Field(description="ID of the prophecy that produced this snapshot")
    plan_id: Optional[str] = Field(default=None, description="Plan this snapshot is about")
    operation_domain: str = Field(description="Domain (organism, healthcare, etc.)")
    operation_type: str = Field(description="Type of operation (plan_execution, recovery, etc.)")

    # Time horizon for which this snapshot is claimed to be valid
    target_window_start: datetime = Field(
        description="Earliest time this snapshot is expected to hold"
    )
    target_window_end: datetime = Field(
        description="Latest time this snapshot is expected to hold"
    )

    # Projected performance / risk geometry
    projected_success_rate: float = Field(
        description="Projected probability of success (0.0–1.0)"
    )
    projected_value: float = Field(
        description="Projected value if the plan is executed within the target window"
    )
    projected_roi: float = Field(
        description="Projected ROI (value / cost) within the target window"
    )
    projected_risk_level: PredictionRiskLevel = Field(
        description="Risk band implied by this future snapshot"
    )
    projected_coherence_band: CoherenceBandLabel = Field(
        description="Expected coherence band during execution"
    )

    # Assumptions / regime hints
    key_assumptions: List[str] = Field(
        default_factory=list,
        description="Explicit assumptions this snapshot depends on",
    )
    regime_shift_warning: bool = Field(
        default=False,
        description="True if the engine believes regime shift risk is high",
    )
    regime_shift_notes: List[str] = Field(
        default_factory=list,
        description="Notes on possible regime shifts that could invalidate this snapshot",
    )

    # Linkage for later evaluation (filled in when outcomes arrive)
    outcome_id: Optional[str] = Field(
        default=None,
        description="ProphecyOutcomeReceipt ID once the outcome is known",
    )
    snapshot_held: Optional[bool] = Field(
        default=None,
        description="Did the observed future match this snapshot within the target window?",
    )
    snapshot_deviation_notes: List[str] = Field(
        default_factory=list,
        description="If it did not hold, what deviated and why?",
    )
