"""
Mycelium Receipts - Audit trail for the Memory Mycelium.

These receipts track:
    - When hyphae are published to the Mycelium
    - When hyphae bloom to MemoryGraph
    - When hyphae are composted
    - Gossip events between agents
    - Semantic deduplication events

Part of the Memory Mycelium system that enables cross-agent
shared knowledge with full constitutional audit.
"""

from __future__ import annotations

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

from receipts.base import BaseReceipt


class HyphaPublishedReceipt(BaseReceipt):
    """
    Emitted when a hypha is published to the Mycelium.

    This marks the origin of a piece of shared knowledge.
    """

    receipt_type: str = "HyphaPublishedReceipt"
    domain: str = "organism"
    organ: str = "mycelium"

    # Hypha identity
    hypha_id: str
    content_hash: str

    # Content (truncated for receipt)
    content_preview: str  # First 200 chars
    topic: str

    # Source
    source_agent_id: str
    source_goal_id: Optional[str] = None

    # Metrics
    chi: float
    was_deduplicated: bool = False
    dedup_target_id: Optional[str] = None  # If deduplicated, which hypha absorbed it

    def __init__(
        self,
        *,
        hypha_id: str,
        content_hash: str,
        content_preview: str,
        topic: str,
        source_agent_id: str,
        chi: float,
        source_goal_id: Optional[str] = None,
        was_deduplicated: bool = False,
        dedup_target_id: Optional[str] = None,
        ts: Optional[datetime] = None,
        parent_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        ts = ts or datetime.now(timezone.utc)
        receipt_id = f"hypha_published_{hypha_id}_{ts.strftime('%Y%m%d%H%M%S')}"
        super().__init__(
            receipt_id=receipt_id,
            hypha_id=hypha_id,
            content_hash=content_hash,
            content_preview=content_preview[:200],
            topic=topic,
            source_agent_id=source_agent_id,
            source_goal_id=source_goal_id,
            chi=chi,
            was_deduplicated=was_deduplicated,
            dedup_target_id=dedup_target_id,
            ts=ts,
            parent_ids=parent_ids or [],
            **kwargs,
        )


class HyphaBloomedReceipt(BaseReceipt):
    """
    Emitted when a high-χ hypha blooms to MemoryGraph.

    This marks the transition from ephemeral shared memory
    to permanent knowledge graph storage.
    """

    receipt_type: str = "HyphaBloomedReceipt"
    domain: str = "organism"
    organ: str = "mycelium"

    # Hypha identity
    hypha_id: str
    content_hash: str

    # MemoryGraph destination
    memory_graph_node_id: str
    memory_graph_node_type: str = "THREADSTONE"  # Most bloomed hyphae become threadstones

    # Metrics at bloom time
    chi: float
    nutrient_value: float
    access_count: int
    merge_count: int

    # Lineage
    parent_hypha_ids: List[str]  # Merged-from hyphae

    def __init__(
        self,
        *,
        hypha_id: str,
        content_hash: str,
        memory_graph_node_id: str,
        chi: float,
        nutrient_value: float,
        access_count: int,
        merge_count: int,
        parent_hypha_ids: Optional[List[str]] = None,
        memory_graph_node_type: str = "THREADSTONE",
        ts: Optional[datetime] = None,
        parent_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        ts = ts or datetime.now(timezone.utc)
        receipt_id = f"hypha_bloomed_{hypha_id}_{ts.strftime('%Y%m%d%H%M%S')}"
        super().__init__(
            receipt_id=receipt_id,
            hypha_id=hypha_id,
            content_hash=content_hash,
            memory_graph_node_id=memory_graph_node_id,
            memory_graph_node_type=memory_graph_node_type,
            chi=chi,
            nutrient_value=nutrient_value,
            access_count=access_count,
            merge_count=merge_count,
            parent_hypha_ids=parent_hypha_ids or [],
            ts=ts,
            parent_ids=parent_ids or [],
            **kwargs,
        )


class HyphaCompostedReceipt(BaseReceipt):
    """
    Emitted when a hypha is composted (removed from active memory).

    This creates an audit trail of what knowledge was discarded and why.
    """

    receipt_type: str = "HyphaCompostedReceipt"
    domain: str = "organism"
    organ: str = "mycelium"

    # Hypha identity
    hypha_id: str
    content_hash: str

    # Compost reason
    compost_reason: str  # "expired", "low_chi", "manual", "merged"
    topic: str

    # Final metrics
    chi: float
    nutrient_value: float
    access_count: int
    age_hours: float  # How long it lived

    def __init__(
        self,
        *,
        hypha_id: str,
        content_hash: str,
        compost_reason: str,
        topic: str,
        chi: float,
        nutrient_value: float,
        access_count: int,
        age_hours: float,
        ts: Optional[datetime] = None,
        parent_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        ts = ts or datetime.now(timezone.utc)
        receipt_id = f"hypha_composted_{hypha_id}_{ts.strftime('%Y%m%d%H%M%S')}"
        super().__init__(
            receipt_id=receipt_id,
            hypha_id=hypha_id,
            content_hash=content_hash,
            compost_reason=compost_reason,
            topic=topic,
            chi=chi,
            nutrient_value=nutrient_value,
            access_count=access_count,
            age_hours=age_hours,
            ts=ts,
            parent_ids=parent_ids or [],
            **kwargs,
        )


class MyceliumGossipReceipt(BaseReceipt):
    """
    Emitted for significant gossip events.

    This tracks cross-agent communication through the gossip bus.
    """

    receipt_type: str = "MyceliumGossipReceipt"
    domain: str = "organism"
    organ: str = "mycelium"

    # Gossip details
    gossip_id: str
    hypha_id: str
    topic: str
    summary: str

    # Source and recipients
    source_agent_id: str
    subscriber_count: int  # How many agents received this

    # Priority
    priority: int  # 0=high, 1=normal, 2=low

    def __init__(
        self,
        *,
        gossip_id: str,
        hypha_id: str,
        topic: str,
        summary: str,
        source_agent_id: str,
        subscriber_count: int = 0,
        priority: int = 1,
        ts: Optional[datetime] = None,
        parent_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        ts = ts or datetime.now(timezone.utc)
        receipt_id = f"mycelium_gossip_{gossip_id}"
        super().__init__(
            receipt_id=receipt_id,
            gossip_id=gossip_id,
            hypha_id=hypha_id,
            topic=topic,
            summary=summary[:200],
            source_agent_id=source_agent_id,
            subscriber_count=subscriber_count,
            priority=priority,
            ts=ts,
            parent_ids=parent_ids or [],
            **kwargs,
        )


class MyceliumQueryReceipt(BaseReceipt):
    """
    Emitted for significant queries to the Mycelium.

    Tracks what knowledge was accessed and by whom.
    """

    receipt_type: str = "MyceliumQueryReceipt"
    domain: str = "organism"
    organ: str = "mycelium"

    # Query details
    query_text_preview: str  # First 100 chars
    topic_filter: Optional[str] = None
    agent_filter: Optional[str] = None

    # Results
    result_count: int
    top_result_ids: List[str]  # Top 3 hypha IDs returned
    top_result_scores: List[float]  # Similarity scores

    # Requester
    requester_agent_id: Optional[str] = None

    def __init__(
        self,
        *,
        query_text_preview: str,
        result_count: int,
        top_result_ids: List[str],
        top_result_scores: List[float],
        topic_filter: Optional[str] = None,
        agent_filter: Optional[str] = None,
        requester_agent_id: Optional[str] = None,
        ts: Optional[datetime] = None,
        parent_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        ts = ts or datetime.now(timezone.utc)
        receipt_id = f"mycelium_query_{ts.strftime('%Y%m%d%H%M%S%f')}"
        super().__init__(
            receipt_id=receipt_id,
            query_text_preview=query_text_preview[:100],
            topic_filter=topic_filter,
            agent_filter=agent_filter,
            result_count=result_count,
            top_result_ids=top_result_ids[:3],
            top_result_scores=top_result_scores[:3],
            requester_agent_id=requester_agent_id,
            ts=ts,
            parent_ids=parent_ids or [],
            **kwargs,
        )


class MyceliumCompactionReceipt(BaseReceipt):
    """
    Emitted after each compaction pass.

    Records what was cleaned up from the Mycelium.
    """

    receipt_type: str = "MyceliumCompactionReceipt"
    domain: str = "organism"
    organ: str = "mycelium"

    # Compaction stats
    expired_count: int
    low_chi_count: int
    finalized_count: int
    total_removed: int

    # State after compaction
    remaining_hyphae: int
    remaining_topics: int

    def __init__(
        self,
        *,
        expired_count: int,
        low_chi_count: int,
        finalized_count: int,
        remaining_hyphae: int,
        remaining_topics: int,
        ts: Optional[datetime] = None,
        parent_ids: Optional[List[str]] = None,
        **kwargs: Any,
    ):
        ts = ts or datetime.now(timezone.utc)
        receipt_id = f"mycelium_compaction_{ts.strftime('%Y%m%d%H%M%S')}"
        total_removed = expired_count + low_chi_count + finalized_count
        super().__init__(
            receipt_id=receipt_id,
            expired_count=expired_count,
            low_chi_count=low_chi_count,
            finalized_count=finalized_count,
            total_removed=total_removed,
            remaining_hyphae=remaining_hyphae,
            remaining_topics=remaining_topics,
            ts=ts,
            parent_ids=parent_ids or [],
            **kwargs,
        )


__all__ = [
    "HyphaPublishedReceipt",
    "HyphaBloomedReceipt",
    "HyphaCompostedReceipt",
    "MyceliumGossipReceipt",
    "MyceliumQueryReceipt",
    "MyceliumCompactionReceipt",
]
