from typing import Protocol
from collections.abc import Awaitable, Callable

from app.schemas.changeset import ChangeItem
from app.schemas.chat import TaskResultType


class AgentRunResult(Protocol):
    result_type: TaskResultType
    answer: str | None
    changeset: list[ChangeItem]
    meta: dict


class AgentRunner(Protocol):
    async def run(
        self,
        *,
        task_id: str,
        dialog_session_id: str,
        rag_session_id: str,
        mode: str,
        message: str,
        attachments: list[dict],
        files: list[dict],
        progress_cb: Callable[[str, str, str, dict | None], Awaitable[None] | None] | None = None,
    ) -> AgentRunResult: ...


class RagRetriever(Protocol):
    async def retrieve(self, rag_session_id: str, query: str) -> list[dict]: ...


class RagIndexer(Protocol):
    async def index_snapshot(
        self,
        rag_session_id: str,
        files: list[dict],
        progress_cb: Callable[[int, int, str], Awaitable[None] | None] | None = None,
    ) -> tuple[int, int, int, int]: ...

    async def index_changes(
        self,
        rag_session_id: str,
        changed_files: list[dict],
        progress_cb: Callable[[int, int, str], Awaitable[None] | None] | None = None,
    ) -> tuple[int, int, int, int]: ...
