from __future__ import annotations

"""Outcomes resource — outcome tracking via the Nexure API."""

from datetime import datetime
from typing import Any

from nexure.models import (
    BatchOutcomeResult,
    DecisionOutcomes,
    OutcomeRecord,
    OutcomeStats,
    OutcomeTypeInfo,
    OutcomeTypeList,
    OverrideOutcomes,
    ReviewerOutcomes,
)
from nexure.resources._base import BaseResource


class OutcomesResource(BaseResource):
    """nx.outcomes — outcome tracking and analytics."""

    # ── Outcome Types ──────────────────────────────────────────

    def list_types(self, *, decision_type: str | None = None) -> OutcomeTypeList:
        """List outcome type definitions.

        Args:
            decision_type: Filter by decision type.
        """
        params: dict[str, Any] = {}
        if decision_type is not None:
            params["decision_type"] = decision_type
        data = self._get("/outcome-types", params=params or None)
        return OutcomeTypeList(**data)

    def create_type(
        self,
        *,
        decision_type: str,
        code: str,
        label: str,
        sentiment: str,
        description: str | None = None,
        display_order: int = 0,
        is_terminal: bool = True,
    ) -> OutcomeTypeInfo:
        """Create an outcome type definition.

        Args:
            decision_type: Decision type this applies to.
            code: Unique code (e.g. "default_30d").
            label: Human-readable label.
            sentiment: positive, negative, or neutral.
            description: Optional longer description.
            display_order: Sort order (default 0).
            is_terminal: Whether this is a final outcome (default True).
        """
        payload: dict[str, Any] = {
            "decision_type": decision_type,
            "code": code,
            "label": label,
            "sentiment": sentiment,
            "display_order": display_order,
            "is_terminal": is_terminal,
        }
        if description is not None:
            payload["description"] = description
        data = self._post("/outcome-types", json=payload)
        return OutcomeTypeInfo(**data)

    def update_type(
        self,
        outcome_type_id: str,
        **kwargs: Any,
    ) -> OutcomeTypeInfo:
        """Update an outcome type.

        Args:
            outcome_type_id: The outcome type ID.
            **kwargs: Fields to update (label, description, etc.).
        """
        data = self._put(f"/outcome-types/{outcome_type_id}", json=kwargs)
        return OutcomeTypeInfo(**data)

    def delete_type(self, outcome_type_id: str) -> None:
        """Delete an outcome type."""
        self._delete(f"/outcome-types/{outcome_type_id}")

    # ── Outcomes ───────────────────────────────────────────────

    def record(
        self,
        *,
        decision_id: str,
        outcome_code: str,
        outcome_date: datetime | str,
        outcome_value: float | None = None,
        outcome_metadata: dict[str, Any] | None = None,
        source_reference: str | None = None,
    ) -> OutcomeRecord:
        """Record a single outcome for a decision.

        Args:
            decision_id: The decision this outcome is for.
            outcome_code: Outcome type code (e.g. "default_30d").
            outcome_date: When the outcome occurred.
            outcome_value: Optional financial value.
            outcome_metadata: Optional metadata.
            source_reference: Optional external reference.
        """
        date_str = outcome_date.isoformat() if isinstance(outcome_date, datetime) else outcome_date
        payload: dict[str, Any] = {
            "decision_id": decision_id,
            "outcome_code": outcome_code,
            "outcome_date": date_str,
        }
        if outcome_value is not None:
            payload["outcome_value"] = outcome_value
        if outcome_metadata is not None:
            payload["outcome_metadata"] = outcome_metadata
        if source_reference is not None:
            payload["source_reference"] = source_reference
        data = self._post("/outcomes", json=payload)
        return OutcomeRecord(**data)

    def batch(self, items: list[dict[str, Any]]) -> BatchOutcomeResult:
        """Import outcomes in batch (up to 1000).

        Args:
            items: List of outcome dicts with keys:
                decision_id, outcome_code, outcome_date,
                and optionally outcome_value, outcome_metadata,
                source_reference.
        """
        data = self._post("/outcomes/batch", json={"items": items})
        return BatchOutcomeResult(**data)

    def for_decision(self, decision_id: str) -> DecisionOutcomes:
        """Get all outcomes for a decision.

        Args:
            decision_id: The decision ID.
        """
        data = self._get(f"/decisions/{decision_id}/outcomes")
        return DecisionOutcomes(**data)

    # ── Analytics ──────────────────────────────────────────────

    def stats(self, *, decision_type: str) -> OutcomeStats:
        """Get outcome statistics.

        Args:
            decision_type: Decision type to analyze.
        """
        data = self._get(
            "/analytics/outcomes",
            params={"decision_type": decision_type},
        )
        return OutcomeStats(**data)

    def by_reviewer(self, *, decision_type: str) -> ReviewerOutcomes:
        """Get outcome stats broken down by reviewer.

        Args:
            decision_type: Decision type to analyze.
        """
        data = self._get(
            "/analytics/outcomes/reviewers",
            params={"decision_type": decision_type},
        )
        return ReviewerOutcomes(**data)

    def by_override(self, *, decision_type: str) -> OverrideOutcomes:
        """Get outcome stats comparing overridden vs non-overridden.

        Args:
            decision_type: Decision type to analyze.
        """
        data = self._get(
            "/analytics/outcomes/overrides",
            params={"decision_type": decision_type},
        )
        return OverrideOutcomes(**data)
