"""Base command protocol and utilities for chat commands.

Commands encapsulate async operations, making them:
- Testable in isolation with mocked dependencies
- Reusable across different contexts (UI, CLI, scripts)
- Single-responsibility focused
"""

from dataclasses import dataclass
from typing import Generic, Protocol, TypeVar

T = TypeVar("T")
U = TypeVar("U")


class Command(Protocol[T]):
    """Protocol for chat commands.

    Commands are dataclasses that encapsulate all dependencies needed
    to execute an async operation. They return a CommandResult with
    the outcome.

    Example:
        @dataclass
        class SendMessageCommand:
            client: ApiClient
            store: ChatStore
            session_id: UUID
            message: str

            async def execute(self) -> CommandResult[str]:
                # ... implementation
    """

    async def execute(self) -> "CommandResult[T]":
        """Execute the command and return result."""
        ...


@dataclass(frozen=True)
class CommandResult(Generic[T]):
    """Result wrapper for command execution.

    Provides a consistent way to handle success/failure without exceptions
    bubbling up to the UI layer.

    Attributes:
        success: Whether the command succeeded.
        data: The result data if successful.
        error: Error message if failed.
    """

    success: bool
    data: T | None = None
    error: str | None = None

    @classmethod
    def ok(cls: type["CommandResult[U]"], data: U) -> "CommandResult[U]":
        """Create a successful result."""
        return cls(success=True, data=data)

    @classmethod
    def fail(cls: type["CommandResult[U]"], error: str) -> "CommandResult[U]":
        """Create a failed result."""
        return cls(success=False, error=error)
