"""Service protocols — typed interfaces for swappable services.

Only protocols that enable real extensibility (multiple implementations or
testing with mocks) live here.  Everything else uses concrete types directly.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, runtime_checkable

if TYPE_CHECKING:
    from core.common import JsonObject, JSONValue
    from core.pathways.context import Context
    from core.pathways.nodes.execution import PathwayRecord
    from core.pathways.pathway import Pathway
    from core.pathways.session import PathwaySession
    from core.types.state import ThreadState

# =============================================================================
# PATHWAY VM — the graph execution engine interface
# =============================================================================


@runtime_checkable
class PathwayVMLike(Protocol):
    """Protocol for the PathwayVM — graph execution engine.

    Kept as a protocol because:
    - Consumer code holds a reference without importing the full VM module
    - Tests can provide a mock VM
    """

    ctx: Context

    async def execute(
        self,
        pathway: Pathway,
        inputs: JsonObject | None = None,
        *,
        execution_id: str | None = None,
        timeout: float | None = None,
        run_state: object | None = None,
    ) -> PathwayRecord: ...

    async def execute_stateful(
        self,
        pathway: Pathway,
        session: PathwaySession,
        inputs: JsonObject | None = None,
        *,
        execution_id: str | None = None,
        timeout: float | None = None,
    ) -> PathwayRecord: ...


# =============================================================================
# STATE STORE — swappable storage backend
# =============================================================================


@runtime_checkable
class StateStoreLike(Protocol):
    """Protocol for state storage (threads + shared memory).

    Kept as a protocol because users may swap FileStateStore for
    Redis, Postgres, or other backends.
    """

    async def load_thread(self, agent_id: str, thread_id: str) -> ThreadState: ...

    async def save_thread(self, state: ThreadState) -> None: ...

    async def delete_thread(self, agent_id: str, thread_id: str) -> bool: ...

    async def list_threads(
        self,
        *,
        agent_id: str | None = None,
        limit: int = 100,
    ) -> list[ThreadState]: ...

    async def get_shared(
        self,
        key: str,
        namespace: str = "default",
    ) -> JSONValue: ...

    async def set_shared(
        self,
        key: str,
        value: JSONValue,
        namespace: str = "default",
    ) -> None: ...

    async def delete_shared(
        self,
        key: str,
        namespace: str = "default",
    ) -> bool: ...

    async def list_shared(
        self,
        namespace: str = "default",
    ) -> dict[str, JSONValue]: ...


__all__ = [
    "PathwayVMLike",
    "StateStoreLike",
]
