"""
Chat functionality for the Dialectic API.

Provides the agentic_chat function for answering queries about peers
using the DialecticAgent.
"""

import logging
from collections.abc import AsyncIterator

from src import crud, schemas
from src.config import ReasoningLevel
from src.dependencies import tracked_db
from src.dialectic.core import DialecticAgent
from src.utils.config_helpers import get_configuration

logger = logging.getLogger(__name__)


async def agentic_chat(
    workspace_name: str,
    session_name: str | None,
    query: str,
    observer: str,
    observed: str,
    reasoning_level: ReasoningLevel = "low",
) -> str:
    """
    Answer a query about a peer using the agentic dialectic.

    Args:
        workspace_name: Workspace identifier
        session_name: Session identifier (may be None for global queries)
        query: The question to answer about the peer
        observer: The peer making the query
        observed: The peer being queried about
        reasoning_level: Level of reasoning to apply

    Returns:
        The synthesized answer string
    """
    # Short-lived DB session for validation + config
    async with tracked_db("dialectic.preflight") as db:
        await crud.get_peer(db, workspace_name, schemas.PeerCreate(name=observer))
        if observer != observed:
            await crud.get_peer(db, workspace_name, schemas.PeerCreate(name=observed))

        session = None
        if session_name:
            session = await crud.get_session(
                db, workspace_name=workspace_name, session_name=session_name
            )
        workspace = await crud.get_workspace(db, workspace_name=workspace_name)
        configuration = get_configuration(None, session, workspace)

        observer_peer_card = None
        observed_peer_card = None
        if configuration.peer_card.use:
            observer_peer_card = await crud.get_peer_card(
                db, workspace_name, observer=observer, observed=observer
            )
            if observer != observed:
                observed_peer_card = await crud.get_peer_card(
                    db, workspace_name, observer=observer, observed=observed
                )
    # DB session closed — agent runs without holding a connection

    agent = DialecticAgent(
        workspace_name=workspace_name,
        session_name=session_name,
        observer=observer,
        observed=observed,
        observer_peer_card=observer_peer_card,
        observed_peer_card=observed_peer_card,
        reasoning_level=reasoning_level,
    )

    return await agent.answer(query)


async def agentic_chat_stream(
    workspace_name: str,
    session_name: str | None,
    query: str,
    observer: str,
    observed: str,
    reasoning_level: ReasoningLevel = "low",
) -> AsyncIterator[str]:
    """
    Stream an answer to a query about a peer using the agentic dialectic.

    Args:
        workspace_name: Workspace identifier
        session_name: Session identifier (may be None for global queries)
        query: The question to answer about the peer
        observer: The peer making the query
        observed: The peer being queried about
        reasoning_level: Level of reasoning to apply

    Yields:
        Chunks of the response text as they are generated
    """
    # Short-lived DB session for validation + config
    async with tracked_db("dialectic.preflight") as db:
        await crud.get_peer(db, workspace_name, schemas.PeerCreate(name=observer))
        if observer != observed:
            await crud.get_peer(db, workspace_name, schemas.PeerCreate(name=observed))

        session = None
        if session_name:
            session = await crud.get_session(
                db, workspace_name=workspace_name, session_name=session_name
            )
        workspace = await crud.get_workspace(db, workspace_name=workspace_name)
        configuration = get_configuration(None, session, workspace)

        observer_peer_card = None
        observed_peer_card = None
        if configuration.peer_card.use:
            observer_peer_card = await crud.get_peer_card(
                db, workspace_name, observer=observer, observed=observer
            )
            if observer != observed:
                observed_peer_card = await crud.get_peer_card(
                    db, workspace_name, observer=observer, observed=observed
                )
    # DB session closed — agent streams without holding a connection

    agent = DialecticAgent(
        workspace_name=workspace_name,
        session_name=session_name,
        observer=observer,
        observed=observed,
        observer_peer_card=observer_peer_card,
        observed_peer_card=observed_peer_card,
        reasoning_level=reasoning_level,
    )

    async for chunk in agent.answer_stream(query):
        yield chunk
