"""Define domain ports for conversation."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Generator

from app.domain.retrieval.models import RetrievedChunk

from .models import AnswerResult, ConversationSession
# Keep domain contracts explicit so adapters can swap implementations cleanly.



class AnswerGenerator(ABC):
    """Represent the Answer Generator type."""
    @abstractmethod
    def generate(
        self,
        *,
        query: str,
        retrieved_chunks: list[RetrievedChunk],
        history: list[dict[str, str]] | None = None,
        provider: str | None = None,
        model: str | None = None,
        prompt_template: str | None = None,
    ) -> AnswerResult:
        """Handle generate for the Answer Generator instance."""
        pass

    @abstractmethod
    def stream_generate(
        self,
        *,
        query: str,
        retrieved_chunks: list[RetrievedChunk],
        history: list[dict[str, str]] | None = None,
        provider: str | None = None,
        model: str | None = None,
        prompt_template: str | None = None,
    ) -> Generator[dict, None, AnswerResult]:
        """Stream generate for the Answer Generator instance."""
        pass


class ConversationStore(ABC):
    """Provide the Conversation Store store implementation."""
    @abstractmethod
    def create_session(self, metadata: dict | None = None) -> ConversationSession:
        """Create session for the Conversation Store instance."""
        pass

    @abstractmethod
    def get_session(self, session_id: str) -> ConversationSession | None:
        """Return session for the Conversation Store instance."""
        pass

    @abstractmethod
    def save_message(
        self,
        session_id: str,
        *,
        role: str,
        content: str,
        sources: list[dict] | None = None,
    ) -> ConversationSession | None:
        """Save message for the Conversation Store instance."""
        pass

    @abstractmethod
    def delete_session(self, session_id: str) -> bool:
        """Delete session for the Conversation Store instance."""
        pass

    @abstractmethod
    def list_sessions(self) -> list[dict]:
        """List sessions for the Conversation Store instance."""
        pass
