"""Server client protocol stubs for remote server communication.

Defines three Protocol interfaces (``ServerClient``, ``RemoteExecutionClient``,
``AuthClient``) and their stub implementations that raise
:class:`NotImplementedError`.  When server mode is implemented as a separate
project the concrete clients will replace these stubs.
"""

from __future__ import annotations

from typing import Any, Protocol, runtime_checkable

# ---------------------------------------------------------------------------
# Protocol definitions
# ---------------------------------------------------------------------------


@runtime_checkable
class ServerClient(Protocol):
    """Protocol for server health and version negotiation."""

    def health_check(self) -> bool:
        """Check server health.

        Returns:
            ``True`` when the server is healthy and reachable.
        """
        ...

    def get_version(self) -> str:
        """Get server version string.

        Returns:
            The semantic version reported by the server.
        """
        ...


@runtime_checkable
class RemoteExecutionClient(Protocol):
    """Protocol for remote plan execution."""

    def execute_plan(self, plan_id: str) -> dict[str, Any]:
        """Submit a plan for remote execution.

        Args:
            plan_id: Identifier of the plan to execute.

        Returns:
            Execution metadata including status and any server-assigned ID.
        """
        ...

    def get_plan_status(self, plan_id: str) -> dict[str, Any]:
        """Query the status of a remotely-executing plan.

        Args:
            plan_id: Identifier of the plan.

        Returns:
            Status metadata including phase, progress, and elapsed time.
        """
        ...

    def cancel_plan(self, plan_id: str) -> bool:
        """Request cancellation of a remotely-executing plan.

        Args:
            plan_id: Identifier of the plan to cancel.

        Returns:
            ``True`` if the cancellation request was accepted.
        """
        ...


@runtime_checkable
class AuthClient(Protocol):
    """Protocol for authentication with the server."""

    def authenticate(self, token: str) -> bool:
        """Authenticate with the server using a bearer token.

        Args:
            token: Authentication token.

        Returns:
            ``True`` when authentication succeeds.
        """
        ...

    def validate_token(self, token: str) -> bool:
        """Validate that a token is still valid without a full auth flow.

        Args:
            token: Token to validate.

        Returns:
            ``True`` when the token is valid and not expired.
        """
        ...


# ---------------------------------------------------------------------------
# Stub implementations — raise NotImplementedError for all operations
# ---------------------------------------------------------------------------

_STUB_MSG = "Server client is not yet implemented"


class StubServerClient:
    """Stub implementation of :class:`ServerClient`.

    All methods raise :class:`NotImplementedError`.
    """

    def health_check(self) -> bool:
        """Raise :class:`NotImplementedError`."""
        raise NotImplementedError(_STUB_MSG)

    def get_version(self) -> str:
        """Raise :class:`NotImplementedError`."""
        raise NotImplementedError(_STUB_MSG)


class StubRemoteExecutionClient:
    """Stub implementation of :class:`RemoteExecutionClient`.

    All methods raise :class:`NotImplementedError`.
    """

    def execute_plan(self, plan_id: str) -> dict[str, Any]:
        """Raise :class:`NotImplementedError`.

        Args:
            plan_id: Identifier of the plan to execute.
        """
        if not plan_id or not isinstance(plan_id, str):
            raise ValueError("plan_id must be a non-empty string")
        raise NotImplementedError(_STUB_MSG)

    def get_plan_status(self, plan_id: str) -> dict[str, Any]:
        """Raise :class:`NotImplementedError`.

        Args:
            plan_id: Identifier of the plan.
        """
        if not plan_id or not isinstance(plan_id, str):
            raise ValueError("plan_id must be a non-empty string")
        raise NotImplementedError(_STUB_MSG)

    def cancel_plan(self, plan_id: str) -> bool:
        """Raise :class:`NotImplementedError`.

        Args:
            plan_id: Identifier of the plan to cancel.
        """
        if not plan_id or not isinstance(plan_id, str):
            raise ValueError("plan_id must be a non-empty string")
        raise NotImplementedError(_STUB_MSG)


class StubAuthClient:
    """Stub implementation of :class:`AuthClient`.

    All methods raise :class:`NotImplementedError`.
    """

    def authenticate(self, token: str) -> bool:
        """Raise :class:`NotImplementedError`.

        Args:
            token: Authentication token.
        """
        if not token or not isinstance(token, str):
            raise ValueError("token must be a non-empty string")
        raise NotImplementedError(_STUB_MSG)

    def validate_token(self, token: str) -> bool:
        """Raise :class:`NotImplementedError`.

        Args:
            token: Token to validate.
        """
        if not token or not isinstance(token, str):
            raise ValueError("token must be a non-empty string")
        raise NotImplementedError(_STUB_MSG)


__all__ = [
    "AuthClient",
    "RemoteExecutionClient",
    "ServerClient",
    "StubAuthClient",
    "StubRemoteExecutionClient",
    "StubServerClient",
]
