from app.modules.agent.module import AgentModule
from app.modules.agent.repository import AgentRepository
from app.modules.agent.story_context_repository import StoryContextRepository, StoryContextSchemaRepository
from app.modules.chat.direct_service import CodeExplainChatService
from app.modules.chat.dialog_store import DialogSessionStore
from app.modules.chat.repository import ChatRepository
from app.modules.chat.module import ChatModule
from app.modules.chat.session_resolver import ChatSessionResolver
from app.modules.chat.task_store import TaskStore
from app.modules.rag.persistence.repository import RagRepository
from app.modules.rag.explain import CodeExplainRetrieverV2, CodeGraphRepository, LayeredRetrievalGateway
from app.modules.rag.module import RagModule, RagRepoModule
from app.modules.shared.bootstrap import bootstrap_database
from app.modules.shared.event_bus import EventBus
from app.modules.shared.retry_executor import RetryExecutor


class ModularApplication:
    def __init__(self) -> None:
        self.events = EventBus()
        self.retry = RetryExecutor()
        self.rag_repository = RagRepository()
        self.chat_repository = ChatRepository()
        self.agent_repository = AgentRepository()
        self.story_context_schema_repository = StoryContextSchemaRepository()
        self.story_context_repository = StoryContextRepository()
        self.chat_tasks = TaskStore()

        self.rag = RagModule(event_bus=self.events, retry=self.retry, repository=self.rag_repository)
        self.rag_repo = RagRepoModule(
            story_context_repository=self.story_context_repository,
            rag_repository=self.rag_repository,
        )
        self.code_explain_retriever = CodeExplainRetrieverV2(
            gateway=LayeredRetrievalGateway(self.rag_repository, self.rag.embedder),
            graph_repository=CodeGraphRepository(),
        )
        self.agent = AgentModule(
            rag_retriever=self.rag.rag,
            agent_repository=self.agent_repository,
            story_context_repository=self.story_context_repository,
            code_explain_retriever=self.code_explain_retriever,
        )
        self.direct_chat = CodeExplainChatService(
            retriever=self.code_explain_retriever,
            llm=self.agent.llm,
            session_resolver=ChatSessionResolver(
                dialogs=DialogSessionStore(self.chat_repository),
                rag_session_exists=lambda rag_session_id: self.rag.sessions.get(rag_session_id) is not None,
            ),
            task_store=self.chat_tasks,
            message_sink=self.chat_repository.add_message,
        )
        self.chat = ChatModule(
            agent_runner=self.agent.runtime,
            event_bus=self.events,
            retry=self.retry,
            rag_sessions=self.rag.sessions,
            repository=self.chat_repository,
            direct_chat=self.direct_chat,
            task_store=self.chat_tasks,
        )

    def startup(self) -> None:
        bootstrap_database(
            self.rag_repository,
            self.chat_repository,
            self.agent_repository,
            self.story_context_schema_repository,
        )
