content: from typing import AsyncGenerator, List
  
  from fastapi import HTTPException
  from sqlalchemy import select
  from sqlalchemy.orm import Session
  from sqlalchemy.ext.asyncio import AsyncSession
  from .conversation_store import ConversationStore
  from ..message.message_store import MessageStore
  
  from app.modules.conversations.conversation.conversation_schema import (
      ChatMessageResponse,
      ConversationInfoResponse,
      CreateConversationRequest,
      CreateConversationResponse,
  )
  from app.modules.conversations.conversation.conversation_service import (
      AccessTypeNotFoundError,
      AccessTypeReadError,
      ConversationNotFoundError,
      ConversationService,
      ConversationServiceError,
  )
  from app.modules.conversations.message.message_model import MessageType
  from app.modules.conversations.message.message_schema import (
      MessageRequest,
      MessageResponse,
      NodeContext,
  )
  from app.modules.users.user_schema import UserConversationListResponse
  from app.modules.intelligence.agents.custom_agents.custom_agent_model import CustomAgent
  
  
  class ConversationController:
      def __init__(
          self, db: Session, async_db: AsyncSession, user_id: str, user_email: str
      ):
          self.user_email = user_email
          self.user_id = user_id
          self.db = db
          self.async_db = async_db
  
          conversation_store = ConversationStore(db, async_db)
          message_store = MessageStore(db, async_db)
  
          self.service = ConversationService.create(
              conversation_store=conversation_store,
              message_store=message_store,
              db=self.db,
              user_id=self.user_id,
              user_email=self.user_email,
          )
  
      async def create_conversation(
          self, conversation: CreateConversationRequest, hidden: bool = False
      ) -> CreateConversationResponse:
          try:
              conversation_id, message = await self.service.create_conversation(
                  conversation, self.user_id, hidden
              )
              return CreateConversationResponse(
                  message=message, conversation_id=conversation_id
              )
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def delete_conversation(self, conversation_id: str) -> dict:
          try:
              return await self.service.delete_conversation(conversation_id, self.user_id)
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except AccessTypeReadError as e:
              raise HTTPException(status_code=401, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def get_conversation_info(
          self, conversation_id: str
      ) -> ConversationInfoResponse:
          try:
              result = await self.service.get_conversation_info(
                  conversation_id, self.user_id
              )
              return result
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except AccessTypeNotFoundError as e:
              raise HTTPException(status_code=401, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def get_conversation_messages(
          self, conversation_id: str, start: int, limit: int
      ) -> List[MessageResponse]:
          try:
              result = await self.service.get_conversation_messages(
                  conversation_id, start, limit, self.user_id
              )
              return result
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except AccessTypeNotFoundError as e:
              raise HTTPException(status_code=401, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def post_message(
          self, conversation_id: str, message: MessageRequest, stream: bool = True
      ) -> AsyncGenerator[ChatMessageResponse, None]:
          try:
              async for chunk in self.service.store_message(
                  conversation_id, message, MessageType.HUMAN, self.user_id, stream
              ):
                  yield chunk
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except AccessTypeReadError as e:
              raise HTTPException(status_code=403, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def regenerate_last_message(
          self,
          conversation_id: str,
          node_ids: List[NodeContext] = [],
          stream: bool = True,
      ) -> AsyncGenerator[ChatMessageResponse, None]:
          try:
              async for chunk in self.service.regenerate_last_message(
                  conversation_id, self.user_id, node_ids, stream
              ):
                  yield chunk
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except AccessTypeReadError as e:
              raise HTTPException(status_code=403, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def stop_generation(
          self, conversation_id: str, session_id: str = None
      ) -> dict:
          try:
              return await self.service.stop_generation(
                  conversation_id, self.user_id, session_id
              )
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def rename_conversation(self, conversation_id: str, new_title: str) -> dict:
          try:
              return await self.service.rename_conversation(
                  conversation_id, new_title, self.user_id
              )
          except ConversationNotFoundError as e:
              raise HTTPException(status_code=404, detail=str(e))
          except AccessTypeReadError as e:
              raise HTTPException(status_code=403, detail=str(e))
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def get_last_human_message(self, conversation_id: str):
          """Get the last human message for regeneration purposes"""
          try:
              return await self.service._get_last_human_message(conversation_id)
          except ConversationNotFoundError:
              raise HTTPException(status_code=404, detail="Conversation not found")
          except AccessTypeReadError:
              raise HTTPException(status_code=403, detail="Access denied")
          except ConversationServiceError as e:
              raise HTTPException(status_code=500, detail=str(e))
  
      async def get_conversations_for_user(
          self,
          start: int,
          limit: int,
          sort: str = "updated_at",
          order: str = "desc",
      ) -> List[UserConversationListResponse]:
          try:
              conversations = await self.service.get_conversations_with_projects_for_user(
                  self.user_id, start, limit, sort, order
              )
              response = []
              agent_ids = [
                  conversation.agent_ids[0]
                  for conversation in conversations
                  if conversation.agent_ids
              ]
  
              custom_agents = {}
              stmt = select(CustomAgent).where(CustomAgent.id.in_(agent_ids))
              result = await self.async_db.execute(stmt)
  
              agents = result.scalars().all()
              custom_agents = {agent.id: agent.role for agent in agents}
  
              for conversation in conversations:
                  projects = conversation.projects
                  repo_name = projects[0].repo_name if projects else None
                  branch_name = projects[0].branch_name if projects else None
  
                  agent_id = conversation.agent_ids[0] if conversation.agent_ids else None
                  display_agent_id = custom_agents.get(agent_id, agent_id)
  
                  response.append(
                      UserConversationListResponse(
                          id=conversation.id,
                          title=conversation.title,
                          status=conversation.status,
                          project_ids=conversation.project_ids,
                          repository=repo_name,
                          branch=branch_name,
                          agent_id=display_agent_id,
                          created_at=conversation.created_at.isoformat(),
                          updated_at=conversation.updated_at.isoformat(),
                      )
                  )
  
              return response
          except Exception as e:
              raise HTTPException(status_code=500, detail=str(e))
  