"""Domain repository protocol for lifecycle actions.

Defines the ``ActionRepositoryProtocol`` — the port that the application
layer uses to persist and retrieve v3 lifecycle actions.  Infrastructure
adapters (e.g. the SQLAlchemy-backed ``ActionRepository``) must satisfy
this protocol.

Based on the clean architecture principle described in the specification:
adapters live at the edge; the domain layer defines the contracts.
"""

from __future__ import annotations

from typing import Protocol, runtime_checkable

from cleveragents.domain.models.core.action import Action


@runtime_checkable
class ActionRepositoryProtocol(Protocol):
    """Port for v3 lifecycle action persistence.

    All methods that mutate state flush but do **not** commit; the caller
    or a Unit-of-Work wrapper is responsible for committing the transaction.
    """

    def create(self, action: Action) -> Action:
        """Persist a new action and return it.

        Args:
            action: An ``Action`` domain model instance.

        Returns:
            The same ``Action`` after persistence (identity pass-through).
        """
        ...

    def get_by_id(self, action_name: str) -> Action | None:
        """Retrieve an action by its namespaced name (primary key).

        Args:
            action_name: The namespaced name string (e.g. ``"local/my-action"``).

        Returns:
            The ``Action`` domain object, or ``None`` if not found.
        """
        ...

    def get_by_name(self, name: str) -> Action | None:
        """Retrieve an action by its full namespaced name string.

        Args:
            name: Full ``namespace/name`` string.

        Returns:
            The ``Action`` domain object, or ``None`` if not found.
        """
        ...

    def get_by_namespace(
        self,
        namespace: str,
        state: str | None = None,
    ) -> list[Action]:
        """List actions in a namespace, optionally filtered by state.

        Args:
            namespace: The namespace to filter by (e.g. ``"local"``).
            state: Optional ``ActionState`` value string to filter by.

        Returns:
            List of ``Action`` domain objects ordered by name.
        """
        ...

    def list_all(self) -> list[Action]:
        """List all persisted actions, ordered by namespace then name.

        Returns:
            List of ``Action`` domain objects.
        """
        ...

    def get_by_state(self, state: str) -> list[Action]:
        """List actions by state, ordered by ``updated_at`` DESC.

        Args:
            state: An ``ActionState`` value string (e.g. ``"available"``).

        Returns:
            List of ``Action`` domain objects.
        """
        ...

    def list_available(self, namespace: str | None = None) -> list[Action]:
        """List all actions in ``available`` state.

        Args:
            namespace: Optional namespace filter.

        Returns:
            List of ``Action`` domain objects ordered by namespace then name.
        """
        ...

    def update(self, action: Action) -> Action:
        """Update all mutable fields of an existing action.

        Args:
            action: The ``Action`` domain model with updated fields.

        Returns:
            The same ``Action`` after persistence.
        """
        ...

    def delete(self, action_name: str) -> bool:
        """Delete an action by namespaced name.

        Args:
            action_name: The namespaced name string of the action to delete.

        Returns:
            ``True`` if the action was deleted, ``False`` if not found.
        """
        ...
