"""Core protocols — contracts for dependency injection.

Use these for type hints when accepting dependencies,
so implementations can be swapped in tests or future backends.
"""
from __future__ import annotations

from typing import Any, Dict, List, Optional, Protocol, runtime_checkable


@runtime_checkable
class StorageProtocol(Protocol):
    """Database / storage backend contract."""

    async def connect(self) -> None: ...
    async def close(self) -> None: ...

    # Messages
    async def save_message(self, role: str, content: str, session_id: str, **kwargs) -> int: ...
    async def get_messages(self, session_id: str, limit: int = 50) -> List[Dict[str, Any]]: ...
    async def count_messages(self, session_id: str) -> int: ...

    # Sessions
    async def create_session(self, session_id: str, agent_name: str) -> None: ...
    async def get_session(self, session_id: str) -> Optional[Dict[str, Any]]: ...
    async def get_active_session(self, agent_name: str) -> Optional[Dict[str, Any]]: ...
    async def update_session(self, session_id: str, **kwargs) -> None: ...

    # Agents
    async def save_agent(self, name: str, scope: str, **kwargs) -> None: ...
    async def get_agent(self, name: str) -> Optional[Dict[str, Any]]: ...
    async def list_agents(self, scope: Optional[str] = None, status: str = "active") -> List[Dict[str, Any]]: ...
    async def update_agent_status(self, name: str, status: str) -> None: ...

    # Usage
    async def log_usage(self, agent_name: str, model: str, **kwargs) -> None: ...
    async def get_usage_today(self) -> float: ...


@runtime_checkable
class AgentRunnerProtocol(Protocol):
    """Agent execution contract."""

    @property
    def active_count(self) -> int: ...

    async def run(self, config: Any, prompt: str) -> Any: ...
    async def run_streaming(self, config: Any, prompt: str, on_chunk: Any) -> Any: ...
    async def kill_all(self) -> None: ...


@runtime_checkable
class MemoryProtocol(Protocol):
    """Memory system contract."""

    def load_all(self) -> list: ...
    def search(self, query: str) -> list: ...
    def save(self, name: str, content: str, **kwargs) -> None: ...
    def delete(self, filename: str) -> None: ...
    def get_index(self) -> str: ...
