from __future__ import annotations

"""Decisions resource — record, get, list, forensics."""

from datetime import datetime
from typing import Any

from nexure.models import DecisionList, DecisionRecord, ForensicReport
from nexure.resources._base import BaseResource


class DecisionsResource(BaseResource):
    """nx.decisions — record, retrieve, and list decisions."""

    def record(
        self,
        *,
        decision_type: str,
        evidence: dict[str, Any],
        action: str,
        decided_by: str,
        package_id: str | None = None,
        brief_id: str | None = None,
        subject: dict[str, Any] | None = None,
        conditions: str | None = None,
        reasoning: str | None = None,
        override_reason: str | None = None,
        policy_context: dict[str, Any] | None = None,
        model_output: dict[str, Any] | None = None,
        source_system: str | None = None,
        source_agent: str | None = None,
        decided_at: datetime | None = None,
        trust_score: int | None = None,
        classification: str | None = None,
        metadata: dict[str, Any] | None = None,
    ) -> DecisionRecord:
        """Record a new decision.

        Args:
            package_id: Reuse an existing package instead of creating one.
            brief_id: Link an existing brief (enables overrode_brief detection).
        """
        payload: dict[str, Any] = {
            "decision_type": decision_type,
            "evidence": evidence,
            "action": action,
            "decided_by": decided_by,
        }
        if package_id is not None:
            payload["package_id"] = package_id
        if brief_id is not None:
            payload["brief_id"] = brief_id
        if subject is not None:
            payload["subject"] = subject
        if conditions is not None:
            payload["conditions"] = conditions
        if reasoning is not None:
            payload["reasoning"] = reasoning
        if override_reason is not None:
            payload["override_reason"] = override_reason
        if policy_context is not None:
            payload["policy_context"] = policy_context
        if model_output is not None:
            payload["model_output"] = model_output
        if source_system is not None:
            payload["source_system"] = source_system
        if source_agent is not None:
            payload["source_agent"] = source_agent
        if decided_at is not None:
            payload["decided_at"] = decided_at.isoformat()
        if trust_score is not None:
            payload["trust_score"] = trust_score
        if classification is not None:
            payload["classification"] = classification
        if metadata is not None:
            payload["metadata"] = metadata

        data = self._post("/decisions", json=payload)
        return DecisionRecord(**data)

    def get(self, decision_id: str) -> DecisionRecord:
        """Get a decision record by ID."""
        data = self._get(f"/decisions/{decision_id}")
        return DecisionRecord(**data)

    def forensics(self, decision_id: str) -> ForensicReport:
        """Full forensic reconstruction of a decision."""
        data = self._get(f"/decisions/{decision_id}/forensics")
        return ForensicReport(**data)

    def list(
        self,
        *,
        limit: int = 50,
        offset: int = 0,
        decision_type: str | None = None,
        action: str | None = None,
        decided_by: str | None = None,
        overrides_only: bool = False,
        start_date: str | None = None,
        end_date: str | None = None,
    ) -> DecisionList:
        """List decision records with optional filters.

        Args:
            limit: Maximum number of records (1-200, default 50).
            offset: Number of records to skip (default 0).
            decision_type: Filter by decision type.
            action: Filter by action (approve, deny, etc.).
            decided_by: Filter by reviewer.
            overrides_only: If True, only return overridden decisions.
            start_date: Filter from this date (ISO format string).
            end_date: Filter until this date (ISO format string).
        """
        params: dict[str, Any] = {"limit": limit, "offset": offset}
        if decision_type:
            params["decision_type"] = decision_type
        if action:
            params["action"] = action
        if decided_by:
            params["decided_by"] = decided_by
        if overrides_only:
            params["overrode_model"] = "true"
        if start_date:
            params["start_date"] = start_date
        if end_date:
            params["end_date"] = end_date

        data = self._get("/decisions", params=params)
        return DecisionList(**data)

    def export(
        self,
        *,
        format: str = "csv",
        decision_type: str | None = None,
        action: str | None = None,
        decided_by: str | None = None,
        start_date: str | None = None,
        end_date: str | None = None,
        overrides_only: bool = False,
    ) -> bytes:
        """Export decisions as CSV or JSON bytes (Pro tier).

        Args:
            format: Export format — "csv" or "json".
            decision_type: Filter by decision type.
            action: Filter by action.
            decided_by: Filter by reviewer.
            start_date: Filter from this date (ISO format string).
            end_date: Filter until this date (ISO format string).
            overrides_only: If True, only export overridden decisions.

        Returns:
            Raw bytes of the exported file content.
        """
        params: dict[str, Any] = {"format": format}
        if decision_type:
            params["decision_type"] = decision_type
        if action:
            params["action"] = action
        if decided_by:
            params["decided_by"] = decided_by
        if overrides_only:
            params["overrode_model"] = "true"
        if start_date:
            params["start_date"] = start_date
        if end_date:
            params["end_date"] = end_date

        resp = self._client.get("/decisions/export", params=params)
        if resp.status_code >= 400:
            from nexure.exceptions import _handle_response

            body = resp.json() if resp.content else {}
            _handle_response(resp.status_code, body, dict(resp.headers))
        return resp.content
