"""Type definitions for restate_saga."""

from __future__ import annotations

from dataclasses import dataclass, field
from datetime import timedelta
from typing import TYPE_CHECKING, Awaitable, Callable

if TYPE_CHECKING:
    import restate

# Error mapper: maps exception to TerminalError or None
ErrorMapper = Callable[[Exception], "restate.TerminalError | None"]

# Error class type for registration
ErrorClass = type[Exception]


@dataclass
class SagaContext:
    """Context passed to saga steps containing the Restate context and compensation stack."""

    ctx: restate.Context
    compensations: list[Callable[[], Awaitable[None]]] = field(default_factory=list)


@dataclass
class StepRetryPolicy:
    """Retry policy for step-level operations (ctx.run)."""

    max_retry_attempts: int | None = None
    max_retry_duration: timedelta | None = None
    initial_retry_interval: timedelta | None = None
    retry_interval_factor: float | None = None
    max_retry_interval: timedelta | None = None


@dataclass
class SagaStepOptions:
    """Options for individual saga steps."""

    retry: StepRetryPolicy | None = None
    compensation_retry: StepRetryPolicy | None = None
    as_terminal_error: ErrorMapper | None = None


@dataclass
class WorkflowRetryPolicy:
    """Retry policy for service/workflow level."""

    max_attempts: int | None = None
    on_max_attempts: str | None = None  # "pause" | "kill"
    initial_interval: timedelta | None = None
    exponentiation_factor: float | None = None
    max_interval: timedelta | None = None


@dataclass
class SagaWorkflowOptions:
    """Options for saga workflow (service-level)."""

    retry_policy: WorkflowRetryPolicy | None = None
    idempotency_retention: timedelta | None = None
    journal_retention: timedelta | None = None
    inactivity_timeout: timedelta | None = None
    abort_timeout: timedelta | None = None
    ingress_private: bool | None = None
