"""Chat endpoints for conversational interactions."""

import json
import uuid
from typing import Annotated

from fastapi import APIRouter, Depends, Form, Request
from fastapi.responses import StreamingResponse
from pydantic import BaseModel

from pydanticai_multiagent.agents import router_agent
from pydanticai_multiagent.dependencies import SearchDeps, create_mock_search_deps
from pydanticai_multiagent.services.conversation import ConversationService

router = APIRouter(prefix="/chat")


class ChatRequest(BaseModel):
    """Request body for chat endpoint."""

    prompt: str
    conversation_id: str | None = None


class ChatResponse(BaseModel):
    """Response from chat endpoint."""

    response: str
    conversation_id: str


def get_conversation_service(request: Request) -> ConversationService:
    """Get conversation service from app state."""
    return request.app.state.conversation_service


def get_user_id(request: Request) -> str:
    """Get user ID from request state (set by AuthMiddleware)."""
    return getattr(request.state, "user_id", None) or "anonymous"


async def get_deps(request: Request) -> SearchDeps:
    """Get agent dependencies.

    Uses app.state resources when available, falls back to mocks.
    """
    if hasattr(request.app.state, "deps_configured") and request.app.state.deps_configured:
        return SearchDeps(
            http_client=request.app.state.http_client,
            db=request.app.state.db,
            cache=request.app.state.cache,
            vector_store=request.app.state.vector_store,
            search_api_key=request.app.state.search_api_key,
            user_id=get_user_id(request),
        )

    return create_mock_search_deps(user_id=get_user_id(request))


def generate_conversation_id() -> str:
    """Generate a unique conversation ID."""
    return f"conv_{uuid.uuid4().hex[:12]}"


@router.post("/", response_model=ChatResponse)
async def chat(
    request: Request,
    body: ChatRequest,
    deps: Annotated[SearchDeps, Depends(get_deps)],
) -> ChatResponse:
    """Send a message and get a response.

    This endpoint runs the router agent which delegates to
    specialized agents based on the request. Conversation history
    is automatically loaded and saved.
    """
    conversation_id = body.conversation_id or generate_conversation_id()
    user_id = get_user_id(request)
    service = get_conversation_service(request)

    # Use ConversationService for history management
    response = await service.chat_sync(
        conversation_id=conversation_id,
        user_id=user_id,
        prompt=body.prompt,
        agent=router_agent,
        deps=deps,
    )

    return ChatResponse(
        response=response,
        conversation_id=conversation_id,
    )


@router.post("/stream")
async def chat_stream(
    request: Request,
    prompt: Annotated[str, Form()],
    conversation_id: Annotated[str | None, Form()] = None,
    deps: Annotated[SearchDeps, Depends(get_deps)] = None,
) -> StreamingResponse:
    """Send a message and stream the response.

    Returns a stream of server-sent events (SSE) with response chunks.
    Conversation history is automatically loaded and saved.
    """
    conv_id = conversation_id or generate_conversation_id()
    user_id = get_user_id(request)
    service = get_conversation_service(request)

    # Ensure deps is set (Depends doesn't work well with Form in all cases)
    if deps is None:
        deps = await get_deps(request)

    async def event_stream():
        """Generate SSE events using ConversationService."""
        async for chunk in service.chat(
            conversation_id=conv_id,
            user_id=user_id,
            prompt=prompt,
            agent=router_agent,
            deps=deps,
        ):
            data = json.dumps({"chunk": chunk, "conversation_id": conv_id})
            yield f"data: {data}\n\n"

        # Send final message
        final_data = json.dumps({"done": True, "conversation_id": conv_id})
        yield f"data: {final_data}\n\n"

    return StreamingResponse(
        event_stream(),
        media_type="text/event-stream",
        headers={
            "Cache-Control": "no-cache",
            "Connection": "keep-alive",
        },
    )


@router.delete("/{conversation_id}")
async def clear_conversation(
    request: Request,
    conversation_id: str,
) -> dict[str, str]:
    """Clear conversation history."""
    service = get_conversation_service(request)
    deleted = await service.clear_conversation(conversation_id)

    return {
        "status": "cleared" if deleted else "not_found",
        "conversation_id": conversation_id,
    }


@router.get("/conversations")
async def list_conversations(
    request: Request,
    limit: int = 20,
) -> dict[str, list]:
    """List recent conversations for the current user."""
    user_id = get_user_id(request)
    service = get_conversation_service(request)
    conversations = await service.list_conversations(user_id, limit)

    return {"conversations": conversations}
