"""Base class for execution engines."""

from abc import ABC, abstractmethod
from collections.abc import Callable

from messirve.models.config import MessirveConfig
from messirve.models.task import Task


class EngineResult:
    """Result from running an engine."""

    def __init__(
        self,
        success: bool,
        output: str,
        exit_code: int = 0,
        tokens_used: int = 0,
        cost_usd: float = 0.0,
        error: str | None = None,
    ) -> None:
        """Initialize the engine result.

        Args:
            success: Whether execution was successful.
            output: Output from the engine.
            exit_code: Exit code from the process.
            tokens_used: Number of tokens used (if applicable).
            cost_usd: Cost in USD (if applicable).
            error: Error message if execution failed.
        """
        self.success = success
        self.output = output
        self.exit_code = exit_code
        self.tokens_used = tokens_used
        self.cost_usd = cost_usd
        self.error = error


class Engine(ABC):
    """Abstract base class for execution engines.

    Engines are responsible for executing tasks using various backends
    (Claude Code, other AI assistants, etc.).
    """

    @abstractmethod
    def execute(
        self,
        task: Task,
        config: MessirveConfig,
        output_callback: Callable[[str], None] | None = None,
    ) -> EngineResult:
        """Execute a task.

        Args:
            task: The task to execute.
            config: Messirve configuration.
            output_callback: Optional callback for streaming output.

        Returns:
            EngineResult with execution details.
        """
        pass

    @abstractmethod
    def build_prompt(self, task: Task, config: MessirveConfig) -> str:
        """Build the prompt for the engine.

        Args:
            task: The task to build a prompt for.
            config: Messirve configuration.

        Returns:
            Complete prompt string.
        """
        pass

    @abstractmethod
    def is_available(self) -> bool:
        """Check if the engine is available.

        Returns:
            True if the engine can be used, False otherwise.
        """
        pass
