"""
Genesis Nervous System — Interface Contracts
=============================================
All retrievers, orchestrators, injectors, and scorers implement these protocols.
PRD: _bmad-output/RLM_NERVOUS_SYSTEM_PRD.md (Story 2.1)
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional, Protocol, runtime_checkable


# ── Data classes ──────────────────────────────────────────────────────────────

@dataclass
class RetrievedChunk:
    """A single piece of knowledge retrieved from any source."""
    content: str
    source: str                          # e.g. "qdrant:genesis_memories", "pg:bloodstream", "kg:entities/foo.jsonl"
    relevance_score: float               # 0.0 – 1.0
    freshness_days: int = 0              # days since creation/update
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class RetrievalRequest:
    """Parameters for a knowledge retrieval query."""
    query: str
    top_k: int = 10
    sources: List[str] = field(default_factory=lambda: ["qdrant", "pg", "kg"])
    min_relevance: float = 0.3
    max_age_days: Optional[int] = None   # None = no age filter


@dataclass
class RetrievalResult:
    """Aggregated result from the retriever orchestrator."""
    chunks: List[RetrievedChunk]
    latency_ms: float
    sources_queried: List[str]
    sources_failed: List[str] = field(default_factory=list)

    @property
    def total_chunks(self) -> int:
        return len(self.chunks)


# ── Protocol interfaces ──────────────────────────────────────────────────────

@runtime_checkable
class IRetriever(Protocol):
    """A single knowledge retriever (Qdrant, PG, KG files, etc.)."""

    def retrieve(self, request: RetrievalRequest) -> List[RetrievedChunk]:
        """Retrieve relevant knowledge chunks for the given request."""
        ...

    def health_check(self) -> bool:
        """Return True if this retriever's backing store is reachable."""
        ...

    @property
    def source_name(self) -> str:
        """Unique name for this source (e.g. 'qdrant:genesis_memories')."""
        ...


@runtime_checkable
class IRetrieverOrchestrator(Protocol):
    """Fan-out query to multiple retrievers and merge results."""

    def query(self, request: RetrievalRequest) -> RetrievalResult:
        """Execute retrieval across all registered sources."""
        ...

    def register_retriever(self, retriever: IRetriever) -> None:
        """Register a retriever backend."""
        ...

    def health(self) -> Dict[str, bool]:
        """Return health status of all registered retrievers."""
        ...


@runtime_checkable
class IKnowledgeInjector(Protocol):
    """Injects retrieved knowledge into an agent's system prompt."""

    def inject(self, base_prompt: str, result: RetrievalResult) -> str:
        """Return an enriched prompt with knowledge context injected."""
        ...


@runtime_checkable
class IFreshnessScorer(Protocol):
    """Scores knowledge chunks by freshness (age-based decay)."""

    def score(self, chunk: RetrievedChunk) -> float:
        """Return freshness score 0.0 (stale) to 1.0 (fresh)."""
        ...
