"""StepResponse class for saga steps."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Generic, TypeVar

Output = TypeVar("Output")
CompensationData = TypeVar("CompensationData")

_UNSET = object()


@dataclass
class StepResponse(Generic[Output, CompensationData]):
    """Response object for saga steps.

    Usage::

        # compensation_data defaults to output when omitted
        StepResponse(output={"order_id": "123"})

        # explicit compensation_data
        StepResponse(output={"order_id": "123"}, compensation_data={"order_id": "123", "extra": True})

        # no compensation data (e.g. validation step)
        StepResponse(output={"valid": True}, compensation_data=None)

        # permanent failure
        StepResponse.permanent_failure("Capture failed", {"auth_id": "abc"})
    """

    output: Output
    compensation_data: CompensationData = _UNSET  # type: ignore[assignment]
    failed: bool = False
    error_message: str | None = None

    def __post_init__(self) -> None:
        if self.compensation_data is _UNSET:
            self.compensation_data = self.output  # type: ignore[assignment]

    @classmethod
    def permanent_failure(
        cls, message: str, compensation_data: CompensationData
    ) -> StepResponse:
        """Create a permanent failure response with compensation data.

        Use when a step partially completes and needs to pass information
        about what succeeded to the compensation function.
        """
        return cls(
            output=None,  # type: ignore[arg-type]
            compensation_data=compensation_data,
            failed=True,
            error_message=message,
        )
