from typing import TYPE_CHECKING

from analogai.deepthink.startup.factories.domain_service_factory import DomainServiceFactory

if TYPE_CHECKING:
    from analogai.deepthink.application.usecases.learning.make_direct_statement.ports import MakeStatementOutputPort
    from analogai.deepthink.application.usecases.learning.learn_statement.learn_statement_usecase import MakeStatementUseCase
from analogai.deepthink.application.usecases.learning.make_direct_statement.states.common.response_builder import LearnerResponseBuilder
from analogai.deepthink.application.usecases.learning.make_direct_statement.states.context.learner_context import LearnerContext
from analogai.deepthink.application.usecases.learning.make_direct_statement.states.context.learner_context_handler import LearnerContextHandler
from analogai.deepthink.presentation.presenters.learning.make_direct_statement_presenter import MakeDirectStatementPresenter
from analogai.deepthink.presentation.controllers.learning_controller import LearningController
from analogai.deepthink.presentation.factories.intents_factory import IntentsFactory
from analogai.deepthink.presentation.factories.interpreters_factory import InterpretersFactory
from analogai.deepthink.presentation.intents.intents_processor import IntentsProcessor
from analogai.deepthink.presentation.interpreters.interpreter_pipeline import InterpreterPipeline
from analogai.deepthink.presentation.pipeline.pipeline import MessagePipeline
from analogai.deepthink.presentation.preprocessing.previous_messages_stack import PreviousMessagesStack


def _create_domain_services() -> DomainServiceFactory:
    return DomainServiceFactory()


def _create_extensions_factory(domain_service_factory: DomainServiceFactory):
    from analogai.deepthink.startup.extensions_service_factory import ExtensionsServiceFactory
    return ExtensionsServiceFactory(domain_service_factory)


def _create_learning_use_cases(domain_service_factory: DomainServiceFactory, learning_presenter=None):
    from analogai.deepthink.application.usecases.learning.learn_statement.learn_statement_usecase import MakeStatementUseCase
    from analogai.deepthink.application.usecases.learning.make_direct_statement.usecase import MakeDirectStatementUseCase
    from analogai.deepthink.application.usecases.learning.make_notion_statement.usecase import MakeNotionStatementUseCase
    from analogai.deepthink.application.usecases.learning.make_conditional_statement.usecase import MakeConditionalStatementUseCase
    from analogai.deepthink.presentation.presenters.learning.make_conditional_statement_presenter import MakeConditionalStatementPresenter
    from analogai.deepthink.presentation.presenters.learning.make_notion_statement_presenter import MakeNotionStatementPresenter

    notion_service = domain_service_factory.get_notion_service()
    if learning_presenter is None:
        learning_presenter = MakeDirectStatementPresenter()
    direct_statement_service = domain_service_factory.get_direct_statement_service()
    context = LearnerContext()
    context_handler = LearnerContextHandler(context, notion_service)
    response_builder = LearnerResponseBuilder(context)
    make_direct_statement = MakeDirectStatementUseCase(
        statement_service=direct_statement_service,
        notion_service=notion_service,
        output_port=learning_presenter,
        context_handler=context_handler,
        response_builder=response_builder,
    )
    make_notion_statement = MakeNotionStatementUseCase(
        notion_service=notion_service,
        output_port=MakeNotionStatementPresenter(),
    )
    make_statement = MakeStatementUseCase(
        make_direct_statement=make_direct_statement,
        make_notion_statement=make_notion_statement,
    )
    causal_presenter = MakeConditionalStatementPresenter()
    make_conditional_statement = MakeConditionalStatementUseCase(
        domain_service_factory=domain_service_factory,
        output_port=causal_presenter,
    )
    return make_statement, make_conditional_statement




def _build_pipeline(
    domain_service_factory: DomainServiceFactory,
    notion_enrichment_enabled: bool | None = None,
    llm_gateway_instance=None,
) -> MessagePipeline:
    from analogai.deepthink.startup.extensions_service_factory import ExtensionsServiceFactory
    from analogai.deepthink.config.feature_config import FeatureConfig
    from analogai.deepthink.infrastructure.gateways.llm.llm_factory import LlmGatewayFactory
    extensions_factory = ExtensionsServiceFactory(domain_service_factory)
    belief_query_service = extensions_factory.get_belief_query_service()

    learning_presenter = MakeDirectStatementPresenter()

    make_statement, make_conditional_statement = _create_learning_use_cases(
        domain_service_factory, learning_presenter=learning_presenter
    )
    if llm_gateway_instance is not None:
        LlmGatewayFactory.set_default_gateway_instance(llm_gateway_instance)

    feature_config = FeatureConfig.from_environment()
    resolved_notion_enrichment_enabled = (
        feature_config.notion_enrichment_enabled
        if notion_enrichment_enabled is None
        else notion_enrichment_enabled
    )
    if resolved_notion_enrichment_enabled:
        from analogai.deepthink.features.notion_enrichment import create_and_register_notion_enrichment_observer
        from analogai.deepthink.features.notion_enrichment.adapters.llm_enrichment_gateway_adapter import LlmEnrichmentGatewayAdapter
        completion_provider = LlmGatewayFactory.create_notion_enrichment()
        enrichment_gateway = LlmEnrichmentGatewayAdapter(completion_provider)
        direct_statement_service = domain_service_factory.get_direct_statement_service()
        notion_service = domain_service_factory.get_notion_service()
        create_and_register_notion_enrichment_observer(
            statement_service=direct_statement_service,
            notion_service=notion_service,
            enrichment_gateway=enrichment_gateway,
        )
    learning_controller = LearningController(
        learn_statement_usecase=make_statement,
        make_conditional_statement_usecase=make_conditional_statement,
    )
    intents_factory = IntentsFactory(
        domain_service_factory=domain_service_factory,
        learning_controller=learning_controller,
    )
    intents_processor = IntentsProcessor(intents_factory)
    interpreters_factory = InterpretersFactory()
    interpreters_processor = InterpreterPipeline(interpreters_factory)
    return MessagePipeline(
        interpreters=interpreters_processor,
        intents_processor=intents_processor,
    )


def create_pipeline(
    domain_service_factory=None,
    notion_enrichment_enabled: bool | None = None,
    llm_gateway_instance=None,
):
    if domain_service_factory is None:
        domain_service_factory = _create_domain_services()
    return _build_pipeline(
        domain_service_factory,
        notion_enrichment_enabled=notion_enrichment_enabled,
        llm_gateway_instance=llm_gateway_instance,
    )

