"""Saga compensation pattern for Pipeline execution"""

import logging
from dataclasses import dataclass, field
from typing import Any, Awaitable, Callable

logger = logging.getLogger(__name__)


@dataclass
class CompletedStep:
    """Record of a completed step with its compensation"""

    step_name: str
    result: Any
    compensate_action: str | None = None


@dataclass
class CompensationResult:
    """Result of compensation execution"""

    step_name: str
    success: bool
    error: str | None = None


class SagaOrchestrator:
    """Orchestrates LIFO compensation for failed pipelines"""

    def __init__(
        self, execute_skill_func: Callable[..., Awaitable[Any]] | None = None
    ):
        """
        Args:
            execute_skill_func: Async function to execute a skill by name
                               signature: async (skill_name, input_data) -> dict
        """
        self._execute_skill = execute_skill_func
        self._completed_steps: list[CompletedStep] = []

    def record_completed(
        self,
        step_name: str,
        result: Any,
        compensate_action: str | None = None,
    ):
        """Record a completed step for potential compensation"""
        self._completed_steps.append(
            CompletedStep(
                step_name=step_name,
                result=result,
                compensate_action=compensate_action,
            )
        )

    async def compensate(self) -> list[CompensationResult]:
        """Execute compensation in LIFO order for all completed steps"""
        results: list[CompensationResult] = []
        for step in reversed(self._completed_steps):
            if step.compensate_action is None:
                logger.info(
                    f"No compensation for step '{step.step_name}', skipping"
                )
                results.append(
                    CompensationResult(
                        step_name=step.step_name,
                        success=True,
                        error="no_compensation_needed",
                    )
                )
                continue

            try:
                if self._execute_skill is not None:
                    await self._execute_skill(step.compensate_action, step.result)
                logger.info(f"Compensation for step '{step.step_name}' succeeded")
                results.append(
                    CompensationResult(
                        step_name=step.step_name,
                        success=True,
                    )
                )
            except Exception as e:
                logger.error(
                    f"Compensation for step '{step.step_name}' failed: {e}"
                )
                results.append(
                    CompensationResult(
                        step_name=step.step_name,
                        success=False,
                        error=str(e),
                    )
                )
                # Don't interrupt other compensations

        return results

    def clear(self):
        """Clear completed steps"""
        self._completed_steps.clear()

    @property
    def completed_steps(self) -> list[CompletedStep]:
        return list(self._completed_steps)
