"""
Organism Health Receipts

Receipts that capture cognitive + constitutional health snapshots for the organism.
These are meta-level vitals that describe how Mycelium (lineage), MemoryGraph
(semantic physics), and the trust/learning layer are behaving over a window.

The intent is to treat "organism health" as just another constitutional fact:
it is receipt-backed, tri-temporal, and can be queried like any other event.
"""

from __future__ import annotations

from typing import Any, Dict, Optional
from datetime import datetime, timezone

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


class MyceliumHealth(BaseModel):
    """
    Summary of the lineage / MyceliumGraph "nervous system" over a time window.
    """

    window_hours: int = Field(
        ge=1,
        description="Sliding window used for active thread / flow metrics.",
    )

    node_count: int = Field(
        ge=0,
        description="Total receipts in the MyceliumGraph.",
    )
    edge_count: int = Field(
        ge=0,
        description="Total causal edges in the MyceliumGraph.",
    )
    root_count: int = Field(
        ge=0,
        description="Receipts with depth == 0 (roots).",
    )
    max_depth: int = Field(
        ge=0,
        description="Maximum causal chain depth.",
    )

    cross_machine_edge_count: int = Field(
        ge=0,
        description="Number of edges crossing machines (origin_machine mismatch).",
    )

    active_thread_count: int = Field(
        ge=0,
        description="Number of active threads (task/case) in the window.",
    )
    active_cross_machine_thread_count: int = Field(
        ge=0,
        description="Number of active threads that span >1 machine in the window.",
    )


class MemoryGraphHealth(BaseModel):
    """
    High-level semantic physics + size metrics for MemoryGraph.

    The physics fields are optional so they can be rolled out incrementally.
    """

    node_count: int = Field(
        ge=0,
        description="Total nodes in MemoryGraph.",
    )
    edge_count: int = Field(
        ge=0,
        description="Total edges in MemoryGraph.",
    )

    avg_curvature: Optional[float] = Field(
        default=None,
        description="Average curvature (χ) across active nodes, if available.",
    )
    curvature_p95: Optional[float] = Field(
        default=None,
        description="95th percentile curvature, if available.",
    )

    contradiction_cluster_count: Optional[int] = Field(
        default=None,
        description="Number of high-contradiction clusters detected by SemanticPhysics.",
    )
    black_hole_candidate_count: Optional[int] = Field(
        default=None,
        description="Number of semantic black-hole candidates.",
    )


class TrustHealth(BaseModel):
    """
    Trust / attestation / learning health signal.
    """

    profile_count: int = Field(
        ge=0,
        description="Number of tracked trust/learning profiles in this env.",
    )
    profiles_by_tier: Dict[str, int] = Field(
        default_factory=dict,
        description="Counts keyed by learning_tier (none/offline_only/low/high/... ).",
    )

    attested_profile_count: Optional[int] = Field(
        default=None,
        description="Profiles with recent, valid attestation/proofs.",
    )

    shadow_disagreement_count: Optional[int] = Field(
        default=None,
        description="Total decisions where a shadow/normative agent disagreed.",
    )
    override_count: Optional[int] = Field(
        default=None,
        description="Total human/operator overrides applied in the window.",
    )

    dignity_floor_violations: Optional[int] = Field(
        default=None,
        description="Count of decisions that violated the dignity floor.",
    )
    ece_bound_violations: Optional[int] = Field(
        default=None,
        description="Count of calibration (ECE) bound violations.",
    )


class CognitiveConstitutionalHealthReceipt(BaseReceipt):
    """
    Periodic 'vitals' snapshot: cognitive + constitutional health merged.

    Domain is GOVERNANCE; organ is 'organism' to make clear this is a cross-cutting
    system-level receipt, not tied to a single product domain.
    """

    receipt_type: str = "CognitiveConstitutionalHealthReceipt"
    domain: Domain = Domain.GOVERNANCE
    organ: str = "organism"

    # Where this health snapshot was computed
    machine_id: str = Field(description="Machine or body identifier emitting the snapshot.")
    tenant_id: Optional[str] = Field(
        default=None,
        description="Tenant identifier for multi-tenant isolates (if applicable).",
    )

    # Schema version for forwards-compatible evolution
    health_version: str = Field(
        default="v0.1",
        description="Version tag for the health payload structure.",
    )

    # Tie into Ωᴴ gating bands (see docs/OMEGA_H_GATING_PLAN.md)
    omega_h_band: Optional[str] = Field(
        default=None,
        description="Current Ωᴴ band: STABLE, ELEVATED_TENSION, or CRITICAL.",
    )

    mycelium: MyceliumHealth = Field(
        description="MyceliumGraph / lineage health snapshot.",
    )
    memorygraph: MemoryGraphHealth = Field(
        description="MemoryGraph semantic/structural health snapshot.",
    )
    trust: TrustHealth = Field(
        description="TrustProfile / learning / attestation health snapshot.",
    )

    notes: Optional[str] = Field(
        default=None,
        description="Optional human-readable annotations or warnings.",
    )

    def __init__(
        self,
        *,
        machine_id: str,
        tenant_id: Optional[str] = None,
        mycelium: MyceliumHealth,
        memorygraph: MemoryGraphHealth,
        trust: TrustHealth,
        omega_h_band: Optional[str] = None,
        health_version: str = "v0.1",
        notes: Optional[str] = None,
        ts: Optional[datetime] = None,
        valid_time: Optional[datetime] = None,
        parent_ids: Optional[list[str]] = None,
        **kwargs: Any,
    ):
        """
        Construct a health receipt with a synthetic, time-stamped receipt_id.

        The ID is derived from machine_id and the transaction timestamp so that
        multiple health snapshots are easy to identify and sort by time.
        """
        ts = ts or datetime.now(timezone.utc)
        valid_time = valid_time or ts
        receipt_id = f"org_health_{machine_id}_{ts.strftime('%Y%m%d%H%M%S')}"
        super().__init__(
            receipt_id=receipt_id,
            machine_id=machine_id,
            tenant_id=tenant_id,
            mycelium=mycelium,
            memorygraph=memorygraph,
            trust=trust,
            omega_h_band=omega_h_band,
            health_version=health_version,
            notes=notes,
            ts=ts,
            valid_time=valid_time,
            parent_ids=parent_ids or [],
            **kwargs,
        )
