"""Data models for A2RAG."""
from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
import time


@dataclass
class Decision:
    """Result of a decide() call."""
    decision_id:        str
    action:             str           # "answer" | "clarify" | "abstain"
    confidence:         float         # 0-1
    explanation:        str
    recommended_action: str
    query_type:         str           # "generic_policy" | "instance_specific"
    language:           str           # "en" | "he" | "ar" | ...
    latency_ms:         float

    # Clarification (when action="clarify")
    clarification:      Optional[str] = None
    missing_fields:     List[str] = field(default_factory=list)

    # Evidence signals
    signals:            Dict[str, float] = field(default_factory=dict)
    reason_codes:       List[str] = field(default_factory=list)

    # Local metadata (never sent to API)
    metadata:           Optional[Dict] = None
    timestamp:          float = field(default_factory=time.time)

    # ── Convenience properties ────────────────────────────────────

    @property
    def should_answer(self) -> bool:
        return self.action == "answer"

    @property
    def should_clarify(self) -> bool:
        return self.action == "clarify"

    @property
    def should_abstain(self) -> bool:
        return self.action == "abstain"

    @property
    def evidence_score(self) -> float:
        return self.signals.get("evidence", 0.0)

    @property
    def completeness_score(self) -> float:
        return self.signals.get("completeness", 1.0)

    @property
    def is_high_confidence(self) -> bool:
        return self.confidence >= 0.80

    @property
    def is_low_confidence(self) -> bool:
        return self.confidence < 0.50

    @classmethod
    def _from_api(cls, data: dict, latency_ms: float = 0, metadata=None) -> "Decision":
        return cls(
            decision_id        = data.get("decision_id", ""),
            action             = data["action"],
            confidence         = data["confidence"],
            explanation        = data.get("explanation", ""),
            recommended_action = data.get("recommended_action", ""),
            query_type         = data.get("query_type", "unknown"),
            language           = data.get("signals", {}).get("language", "en"),
            latency_ms         = latency_ms,
            clarification      = data.get("clarification"),
            missing_fields     = data.get("missing_fields", []),
            signals            = data.get("signals", {}),
            reason_codes       = data.get("reason_codes", []),
            context_hint       = data.get("context_hint"),
            metadata           = metadata,
        )

    def __repr__(self):
        return (f"Decision(action={self.action!r}, "
                f"confidence={self.confidence:.2f}, "
                f"query_type={self.query_type!r})")


@dataclass
class Metrics:
    """Aggregated metrics from local decision history."""
    total:              int
    period_days:        int

    # Action distribution
    answer_count:       int = 0
    clarify_count:      int = 0
    abstain_count:      int = 0

    # Key metrics
    answer_rate:        float = 0.0   # % decisions that resulted in answer
    clarify_rate:       float = 0.0
    abstain_rate:       float = 0.0
    coverage:           float = 0.0   # same as answer_rate

    # Quality metrics (requires feedback)
    uar:                float = 0.0   # Unsafe Answer Rate (lower=better)
    abstain_precision:  float = 1.0   # when abstain, were we right?
    clarify_success:    float = 0.0   # clarifications that led to answer

    # Performance
    avg_latency_ms:     float = 0.0
    p95_latency_ms:     float = 0.0
    avg_confidence:     float = 0.0

    # Confidence distribution
    high_confidence_rate: float = 0.0  # confidence >= 0.80
    low_confidence_rate:  float = 0.0  # confidence < 0.50

    # Feedback
    feedback_count:     int = 0
    positive_feedback:  float = 0.0   # % positive feedback

    # ORS — Overall Reliability Score
    @property
    def ors(self) -> float:
        """Overall Reliability Score = Coverage × (1-UAR) × AbstainPrecision"""
        return self.coverage * (1 - self.uar) * self.abstain_precision

    def __repr__(self):
        return (f"Metrics(total={self.total}, answer={self.answer_rate:.1%}, "
                f"UAR={self.uar:.1%}, ORS={self.ors:.1%})")


@dataclass
class CalibrationResult:
    """Result of calibrate() call."""
    domain:             str
    tau_evidence:       float
    tau_completeness:   float
    tau_abstain:        float
    expected_accuracy:  float
    expected_uar:       float
    expected_ors:       float
    dataset_size:       int
    recommendation:     str
