"""
fw_server/types.py — JSON-serializable request/response schemas for the MCP bridge.

All types here are plain dicts or Pydantic-free dataclasses so they serialise
cleanly across the MCP stdio boundary.  The authoritative rich types live in
bileshke.types; this module provides the thin wire format.

Design constraints:
  KV₇:  No shared mutable state between lenses — every request is stateless.
  AX56: Grade field never accepts "Hakkalyakîn".
  AX57: Every response carries a transparency block.
  T6/KV₄: Composite score < 1.0.
"""

from __future__ import annotations

from dataclasses import asdict, dataclass, field
from typing import Any, Dict, List, Optional


# ── Lens identifiers (string constants matching bileshke.types.LensId) ──

LENS_IDS = (
    "Ontoloji",
    "Mereoloji",
    "FOL",
    "Bayes",
    "OyunTeorisi",
    "KategoriTeorisi",
    "Topoloji + Holografik",
)

# ── Epistemic grades (ascending order) ──

VALID_GRADES = ("Tasavvur", "Tasdik", "İlmelyakîn")
# Note: "Hakkalyakîn" is intentionally excluded (AX56).


# ========================================================================
# Request schemas
# ========================================================================

@dataclass
class RunLensRequest:
    """Input for a single-lens execution."""
    lens_id: str            # Must be one of LENS_IDS
    params: Dict[str, Any] = field(default_factory=dict)
    # Lens-specific; adapters interpret these.
    # e.g. {"text": "...", "model": {...}} for FOL


@dataclass
class RunBileshkeRequest:
    """Input for the full composite pipeline."""
    lens_results: Optional[List[Dict[str, Any]]] = None
    # If None the engine runs all 7 lenses with defaults.
    weights: Optional[Dict[str, float]] = None
    ortam: Optional[List[int]] = None  # [1,1,1] = full coverage


@dataclass
class KavaidCheckRequest:
    """Input for a standalone kavaid evaluation."""
    composite_score: float = 0.0
    latife_bits: Optional[List[int]] = None   # 7-element list
    kavaid_overrides: Optional[Dict[str, bool]] = None


@dataclass
class InferenceChainRequest:
    """Input for inference chain verification."""
    chain_id: Optional[str] = None  # None → verify all
    text: Optional[str] = None       # For axiom reference extraction


@dataclass
class HCPIngestRequest:
    """Input for HCP context ingestion."""
    text: str = ""


@dataclass
class HCPQueryRequest:
    """Input for HCP retrieval."""
    question: str = ""
    keywords: Optional[List[str]] = None
    top_k: int = 5


# ========================================================================
# Response schemas
# ========================================================================

@dataclass
class LensResponse:
    """Output from a single lens."""
    lens_id: str
    score: float
    grade: str
    checks_passed: int = 0
    checks_total: int = 0
    detail: str = ""
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {k: v for k, v in asdict(self).items() if v is not None}


@dataclass
class BileshkeResponse:
    """Output from the composite engine."""
    composite_score: float = 0.0
    lens_results: List[Dict[str, Any]] = field(default_factory=list)
    kavaid_checks: Dict[str, bool] = field(default_factory=dict)
    latife_vektor: Dict[str, int] = field(default_factory=dict)
    ortam_vektor: Dict[str, int] = field(default_factory=dict)
    completeness: float = 0.0
    warnings: List[str] = field(default_factory=list)
    degree_distribution: Dict[str, str] = field(default_factory=dict)
    # AX57 transparency
    framework_disclosure: Dict[str, Any] = field(default_factory=dict)
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {k: v for k, v in asdict(self).items() if v is not None}


@dataclass
class KavaidResponse:
    """Output from kavaid evaluation."""
    checks: Dict[str, bool] = field(default_factory=dict)
    descriptions: Dict[str, str] = field(default_factory=dict)
    all_pass: bool = False
    composite_score: float = 0.0
    kv4_warning: Optional[str] = None
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {k: v for k, v in asdict(self).items() if v is not None}


@dataclass
class InferenceChainResponse:
    """Output from inference chain verification."""
    chains_verified: Dict[str, Dict[str, Any]] = field(default_factory=dict)
    hub_nodes: Dict[str, List[str]] = field(default_factory=dict)
    axiom_refs: Optional[Dict[str, List[str]]] = None
    all_valid: bool = False
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {k: v for k, v in asdict(self).items() if v is not None}


@dataclass
class HCPResponse:
    """Output from HCP operations."""
    action: str = ""  # "ingest" | "query" | "diagnostics"
    diagnostics: Optional[Dict[str, Any]] = None
    results: Optional[List[Dict[str, Any]]] = None
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {k: v for k, v in asdict(self).items() if v is not None}


@dataclass
class FrameworkSummaryResponse:
    """Output from framework_summary across all modules."""
    bileshke: Dict[str, Any] = field(default_factory=dict)
    fol: Dict[str, Any] = field(default_factory=dict)
    bayes: Dict[str, Any] = field(default_factory=dict)
    oyun_teorisi: Dict[str, Any] = field(default_factory=dict)
    kategori_teorisi: Dict[str, Any] = field(default_factory=dict)
    holografik: Dict[str, Any] = field(default_factory=dict)
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {k: v for k, v in asdict(self).items() if v is not None}
