"""
BiasClear client response models.

Typed dataclasses that map API JSON responses to Python objects.
"""

from __future__ import annotations

from dataclasses import dataclass, field
from typing import Any


# ── Scan ─────────────────────────────────────────────────────────────

@dataclass
class Flag:
    """A single bias detection flag."""
    category: str
    pattern_id: str
    matched_text: str
    pit_tier: int
    severity: str
    principle: str = ""
    correction_instruction: str = ""
    correction_confidence: float = 0.0


@dataclass
class ScanResult:
    """Response from POST /scan."""
    text: str
    truth_score: int
    knowledge_type: str
    bias_detected: bool
    bias_types: list[str]
    pit_tier: str
    pit_detail: str
    severity: str
    confidence: float
    explanation: str
    flags: list[Flag]
    impact_projection: Any
    scan_mode: str
    source: str
    core_version: str

    @classmethod
    def from_dict(cls, data: dict) -> ScanResult:
        flags = [
            Flag(**{k: v for k, v in f.items() if k in Flag.__dataclass_fields__})
            for f in data.get("flags", [])
        ]
        return cls(
            text=data.get("text", ""),
            truth_score=data.get("truth_score", 0),
            knowledge_type=data.get("knowledge_type", ""),
            bias_detected=data.get("bias_detected", False),
            bias_types=data.get("bias_types", []),
            pit_tier=data.get("pit_tier", ""),
            pit_detail=data.get("pit_detail", ""),
            severity=data.get("severity", ""),
            confidence=data.get("confidence", 0.0),
            explanation=data.get("explanation", ""),
            flags=flags,
            impact_projection=data.get("impact_projection"),
            scan_mode=data.get("scan_mode", ""),
            source=data.get("source", ""),
            core_version=data.get("core_version", ""),
        )


# ── Correction ───────────────────────────────────────────────────────

@dataclass
class DiffSpan:
    """A single diff span from correction."""
    type: str
    text: str


@dataclass
class CorrectionResult:
    """Response from POST /correct."""
    corrected: bool
    original_text: str
    corrected_text: str | None
    truth_score_before: int | None
    truth_score_after: int | None
    diff_spans: list[DiffSpan]
    changes_made: list[str]
    iterations: int | None
    reason: str | None

    @classmethod
    def from_dict(cls, data: dict) -> CorrectionResult:
        spans = [
            DiffSpan(**s) for s in data.get("diff_spans", []) or []
        ]
        return cls(
            corrected=data.get("corrected", False),
            original_text=data.get("original_text", ""),
            corrected_text=data.get("corrected_text"),
            truth_score_before=data.get("truth_score_before"),
            truth_score_after=data.get("truth_score_after"),
            diff_spans=spans,
            changes_made=data.get("changes_made", []) or [],
            iterations=data.get("iterations"),
            reason=data.get("reason"),
        )


# ── Patterns ─────────────────────────────────────────────────────────

@dataclass
class PatternInfo:
    """A frozen or learned pattern summary."""
    id: str
    name: str
    description: str
    pit_tier: int
    severity: str
    source: str = "frozen"


@dataclass
class RingStats:
    """Learning ring statistics."""
    total_patterns: int = 0
    staging: int = 0
    active: int = 0
    deactivated: int = 0
    activation_threshold: int = 0
    fp_limit: int = 0


@dataclass
class PatternsResult:
    """Response from GET /patterns."""
    domain: str
    core_version: str
    frozen_patterns: list[dict]
    learned_patterns: list[PatternInfo]
    frozen_count: int
    learned_count: int
    learning_ring: RingStats

    @classmethod
    def from_dict(cls, data: dict) -> PatternsResult:
        learned = [
            PatternInfo(
                id=p.get("pattern_id", p.get("id", "")),
                name=p.get("name", ""),
                description=p.get("description", ""),
                pit_tier=p.get("pit_tier", 0),
                severity=p.get("severity", ""),
                source=p.get("source", "learning_ring"),
            )
            for p in data.get("learned_patterns", [])
        ]
        ring_data = data.get("learning_ring", {})
        ring = RingStats(
            total_patterns=ring_data.get("total_patterns", 0),
            staging=ring_data.get("staging", 0),
            active=ring_data.get("active", 0),
            deactivated=ring_data.get("deactivated", 0),
            activation_threshold=ring_data.get("activation_threshold", 0),
            fp_limit=ring_data.get("fp_limit", 0),
        )
        return cls(
            domain=data.get("domain", ""),
            core_version=data.get("core_version", ""),
            frozen_patterns=data.get("frozen_patterns", []),
            learned_patterns=learned,
            frozen_count=data.get("frozen_count", 0),
            learned_count=data.get("learned_count", 0),
            learning_ring=ring,
        )


# ── Audit ────────────────────────────────────────────────────────────

@dataclass
class AuditEntry:
    """A single audit chain entry."""
    id: str
    hash: str
    prev_hash: str
    event_type: str
    data: dict
    timestamp: str
    core_version: str


@dataclass
class ChainIntegrity:
    """Audit chain integrity verification result."""
    verified: bool
    entries_checked: int
    broken_links: list[str]


@dataclass
class AuditResult:
    """Response from GET /audit."""
    entries: list[AuditEntry]
    count: int
    total_entries: int
    chain_integrity: ChainIntegrity
    core_version: str

    @classmethod
    def from_dict(cls, data: dict) -> AuditResult:
        entries = [
            AuditEntry(**{k: v for k, v in e.items() if k in AuditEntry.__dataclass_fields__})
            for e in data.get("entries", [])
        ]
        integrity_data = data.get("chain_integrity", {})
        integrity = ChainIntegrity(
            verified=integrity_data.get("verified", False),
            entries_checked=integrity_data.get("entries_checked", 0),
            broken_links=integrity_data.get("broken_links", []),
        )
        return cls(
            entries=entries,
            count=data.get("count", 0),
            total_entries=data.get("total_entries", 0),
            chain_integrity=integrity,
            core_version=data.get("core_version", ""),
        )
