"""
Lightweight data contracts for AgenticResult outputs.

These are minimal implementations to standardize return shapes across commands.
They avoid heavy dependencies and keep serialization straightforward.
"""

from __future__ import annotations

import uuid
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import Any, Dict, List, Optional


def _utc_timestamp() -> str:
    return datetime.now(timezone.utc).isoformat()


@dataclass
class AgenticWarning:
    code: str
    message: str
    severity: str = "info"

    def to_dict(self) -> Dict[str, Any]:
        return {
            "code": self.code,
            "message": self.message,
            "severity": self.severity,
        }


@dataclass
class BatchOutcome:
    """Per-item batch outcome with partial success support."""

    succeeded: List[Dict[str, Any]] = field(default_factory=list)
    failed: List[Dict[str, Any]] = field(default_factory=list)
    retryable_failed: List[Dict[str, Any]] = field(default_factory=list)

    @property
    def status(self) -> str:
        if not self.failed and not self.retryable_failed:
            return "success"
        if not self.succeeded:
            return "fail"
        return "partial"

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "BatchOutcome/v1",
            "succeeded": self.succeeded,
            "failed": self.failed,
            "retryable_failed": self.retryable_failed,
            "summary": f"{len(self.succeeded)} succeeded, {len(self.failed)} failed ({len(self.retryable_failed)} retryable)",
        }


@dataclass
class CapabilityCheck:
    name: str
    status: str
    detail: str = ""

    def to_dict(self) -> Dict[str, Any]:
        return {
            "name": self.name,
            "status": self.status,
            "detail": self.detail,
        }


@dataclass
class DoctorResult:
    provider: str
    checks: List[CapabilityCheck]
    identity: Dict[str, Any]
    overall_status: str

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "DoctorResult/v1",
            "provider": self.provider,
            "overall_status": self.overall_status,
            "identity": self.identity,
            "checks": [check.to_dict() for check in self.checks],
        }


@dataclass
class DeltaSummary:
    """Minimal delta summary placeholder; filled in by mutation commands."""

    entities_affected: Optional[Dict[str, Any]] = None
    by_object: Optional[Dict[str, Any]] = None
    top_changes: Optional[List[Dict[str, Any]]] = None
    samples_shown: Optional[int] = None
    samples_redacted: Optional[bool] = None
    risk_flags: Optional[Dict[str, Any]] = None

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "DeltaSummary/v1",
            "entities_affected": self.entities_affected,
            "by_object": self.by_object,
            "top_changes": self.top_changes,
            "samples_shown": self.samples_shown,
            "samples_redacted": self.samples_redacted,
            "risk_flags": self.risk_flags,
        }


@dataclass
class ChartSpec:
    chart_type: str
    data_range: Optional[str]
    x_col: Optional[str]
    y_col: Optional[str]
    series_cols: Optional[List[str]]
    title: Optional[str]
    anchor_cell: str = "E1"
    replace: bool = False

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "ChartSpec/v1",
            "chart_type": self.chart_type,
            "data_range": self.data_range,
            "x_col": self.x_col,
            "y_col": self.y_col,
            "series_cols": self.series_cols,
            "title": self.title,
            "anchor_cell": self.anchor_cell,
            "replace": self.replace,
        }


@dataclass
class ChartResult:
    success: bool
    chart_id: Optional[int] = None
    title: Optional[str] = None
    anchor: Optional[str] = None
    replaced: bool = False
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "ChartResult/v1",
            "success": self.success,
            "chart_id": self.chart_id,
            "title": self.title,
            "anchor": self.anchor,
            "replaced": self.replaced,
            "error": self.error,
        }


@dataclass
class DeckResult:
    success: bool
    presentation_id: Optional[str] = None
    charts_created: int = 0
    charts_replaced: int = 0
    slides_updated: int = 0
    error: Optional[str] = None

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "DeckResult/v1",
            "success": self.success,
            "presentation_id": self.presentation_id,
            "charts_created": self.charts_created,
            "charts_replaced": self.charts_replaced,
            "slides_updated": self.slides_updated,
            "error": self.error,
        }


@dataclass
class AgenticResult:
    command: str
    status: str
    dry_run: bool
    result: Dict[str, Any]
    correlation_id: str = field(default_factory=lambda: str(uuid.uuid4()))
    confidence_score: float = 1.0
    confidence_blocked: bool = False
    warnings: List[AgenticWarning] = field(default_factory=list)
    delta_summary: Optional[DeltaSummary] = None
    batch_outcome: Optional[BatchOutcome] = None
    provenance: Optional[Dict[str, Any]] = None
    error: Optional[str] = None
    timestamp: str = field(default_factory=_utc_timestamp)

    def to_dict(self) -> Dict[str, Any]:
        return {
            "$schema": "AgenticResult/v1",
            "correlation_id": self.correlation_id,
            "command": self.command,
            "status": self.status,
            "dry_run": self.dry_run,
            "confidence_score": self.confidence_score,
            "confidence_blocked": self.confidence_blocked,
            "warnings": [w.to_dict() for w in self.warnings],
            "delta_summary": self.delta_summary.to_dict() if self.delta_summary else None,
            "provenance": self.provenance,
            "result": self.result,
            "batch_outcome": self.batch_outcome.to_dict() if self.batch_outcome else None,
            "error": self.error,
            "timestamp": self.timestamp,
        }
