from __future__ import annotations

from typing import Optional

from analogai.foundation.infrastructure.services.embedding_service import (
    EmbeddingService,
)
from analogai.foundation.settings import config as app_config
from analogai.foundation.modules.fact.repositories.fact_repository import FactRepository
from analogai.foundation.modules.fact.source.repositories.fact_source_repository import FactSourceRepository
from analogai.foundation.modules.fact.repositories.infrastructure.qdrant_fact_repository import (
    QdrantFactRepository,
)
from analogai.foundation.modules.fact.repositories.infrastructure.in_memory_fact_repository import (
    InMemoryFactRepository,
)
from analogai.foundation.modules.fact.source.repositories.infrastructure.in_memory_fact_source_repository import (
    InMemoryFactSourceRepository,
)
from analogai.foundation.modules.fact.source.repositories.infrastructure.mongo_fact_source_repository import (
    MongoFactSourceRepository,
)
from analogai.foundation.modules.fact.source.services.fact_source_service import FactSourceService
from analogai.foundation.modules.fact.services.fact_service import (
    FactServicePort,
    RepositoryBackedFactService,
)
from analogai.foundation.modules.fact.enums.fact_embedding_mode import FactEmbeddingMode
from analogai.foundation.modules.fact.subscribers.fact_observer_registry import (
    FactObserverRegistry,
)
from analogai.foundation.modules.fact.subscribers.fact_observer_builder import (
    FactObserverBuilder,
)


class FactServiceFactory:
    def __init__(
        self,
        embedding_service: Optional[EmbeddingService] = None,
        repository: Optional[FactRepository] = None,
        source_repository: Optional[FactSourceRepository] = None,
        source_service: Optional[FactSourceService] = None,
        statement_service: Optional[object] = None,
        notion_service: Optional[object] = None,
        observer_registry: Optional[FactObserverRegistry] = None,
    ):
        self._embedding_service = embedding_service
        self._repository = repository
        self._source_repository = source_repository
        self._source_service = source_service
        self._statement_service = statement_service
        self._notion_service = notion_service
        self._observer_registry = observer_registry or FactObserverRegistry()

    def create(self) -> FactServicePort:
        if self._statement_service is None or self._notion_service is None:
            raise ValueError("FactServiceFactory requires statement_service and notion_service")
        use_vector_search = bool(app_config.get("vector_search.enabled", True))
        embedding_mode = (
            FactEmbeddingMode.ENABLED
            if use_vector_search
            else FactEmbeddingMode.DISABLED
        )
        max_paragraphs_per_fact = app_config.get("limits.max_paragraphs_per_fact")
        if max_paragraphs_per_fact is None:
            max_paragraphs_per_fact = app_config.get("limits.max_sentences_per_fact")
        environment = app_config.get("ENVIRONMENT", "development")
        if self._repository is None:
            if environment in {"production", "testing"}:
                self._repository = QdrantFactRepository()
            else:
                self._repository = InMemoryFactRepository()
        if self._source_repository is None:
            if environment in {"production", "testing"}:
                self._source_repository = MongoFactSourceRepository()
            else:
                self._source_repository = InMemoryFactSourceRepository()
        if self._repository is not None:
            fact_service = RepositoryBackedFactService(
                self._repository,
                source_repository=self._source_repository,
                source_service=None,
                statement_service=self._statement_service,
                notion_service=self._notion_service,
                embedding_service=self._embedding_service,
                embedding_mode=embedding_mode,
                max_paragraphs_per_fact=max_paragraphs_per_fact,
            )
            if self._source_service is None and self._source_repository is not None:
                self._source_service = FactSourceService(
                    fact_service=fact_service,
                    belief_service=None,
                    source_repository=self._source_repository,
                )
            if self._source_service is not None:
                fact_service.set_source_service(self._source_service)
            self._register_observers(fact_service)
            return fact_service
        raise ValueError("FactServiceFactory requires a repository")

    def _register_observers(self, fact_service: FactServicePort) -> None:
        builder = FactObserverBuilder(
            fact_service=fact_service,
            registry=self._observer_registry,
        )
        builder.observe_statement_service(self._statement_service)
        builder.observe_notion_service(self._notion_service)

    def get_observer_registry(self) -> FactObserverRegistry:
        return self._observer_registry
