from __future__ import annotations

from analogai.foundation.modules.fact.services.fact_service import FactServicePort
from analogai.foundation.modules.fact.source.repositories.fact_source_repository import FactSourceRepository
from analogai.foundation.modules.fact.source.fact_source import FactSource
from analogai.foundation.modules.fact.direct_statement_fact import DirectStatementFact
from analogai.foundation.modules.belief.belief_service import BeliefService
from analogai.foundation.common.logging.app_logger import app_logger


class FactSourceService:
    def __init__(
        self,
        fact_service: FactServicePort | None,
        belief_service: BeliefService | None,
        source_repository: FactSourceRepository | None = None,
    ) -> None:
        self._fact_service = fact_service
        self._belief_service = belief_service
        self._source_repository = source_repository

    def store_source(self, source: FactSource) -> FactSource | None:
        if source is None or self._source_repository is None:
            return None
        if not source.agent_id:
            app_logger.warning("FactSourceService store_source requires agent_id")
            return None
        self._source_repository.register_source(source)
        return source

    def get_source(self, source_id: str) -> FactSource | None:
        if not source_id or self._source_repository is None:
            return None
        return self._source_repository.get_source(source_id)

    def get_sources(self, agent_id: str) -> list[FactSource]:
        if not agent_id:
            return []
        if self._source_repository is not None:
            return self._source_repository.list_sources_for_agent(agent_id)
        return []

    def delete_source(self, source_id: str) -> dict[str, list[str]]:
        if self._fact_service is None or self._belief_service is None:
            app_logger.warning(
                "FactSourceService delete_source called without fact/belief services wired; "
                "source_id=%s",
                source_id,
            )
            raise ValueError("FactSourceService delete_source requires fact_service and belief_service")
        if not source_id:
            return {"fact_ids": [], "statement_ids": [], "belief_ids": []}
        if self._source_repository is not None:
            source = self._source_repository.get_source(source_id)
        else:
            source = None
        if source is None:
            return {"fact_ids": [], "statement_ids": [], "belief_ids": []}
        facts = self._fact_service.get_facts_by_source(source.id)
        if not facts:
            return {"fact_ids": [], "statement_ids": [], "belief_ids": []}
        turn_ids = {str(fact.turn_id) for fact in facts if fact.turn_id}
        belief_ids: list[str] = []
        for turn_id in turn_ids:
            belief_ids.extend(self._fact_service.get_belief_ids_for_turn(turn_id))
        belief_ids = [str(belief_id) for belief_id in belief_ids if belief_id]
        if source.agent_id:
            beliefs = self._belief_service.get_all_for_agent(source.agent_id)
            beliefs_by_id = {str(belief.id): belief for belief in beliefs if getattr(belief, "id", None)}
            if not belief_ids:
                statement_service = getattr(self._belief_service, "statement_service", None)
                for fact in facts:
                    if not isinstance(fact, DirectStatementFact):
                        continue
                    if statement_service is None:
                        break
                    statement = statement_service.find_by_id(fact.statement_id)
                    if statement is None:
                        continue
                    belief = self._belief_service.find(
                        statement.subject_notion,
                        statement.complement_notion,
                        statement.relation,
                    )
                    if belief is not None and getattr(belief, "id", None):
                        belief_ids.append(str(belief.id))
                belief_ids = list(dict.fromkeys(belief_ids))
            for belief_id in belief_ids:
                belief = beliefs_by_id.get(str(belief_id))
                if belief is None:
                    continue
                try:
                    self._belief_service.delete(belief)
                except Exception as exc:
                    app_logger.warning(
                        "FactSourceService failed to delete belief_id=%s source_id=%s: %s",
                        belief_id,
                        source.id,
                        exc,
                    )
        deleted_facts = self._fact_service.delete_facts_by_source(source.id)
        deleted_fact_ids = [str(fact.id) for fact in deleted_facts if fact.id]

        if self._source_repository is not None:
            try:
                self._source_repository.delete_source(source_id)
            except Exception as exc:
                app_logger.warning(
                    "Failed to delete source_id=%s from source repository: %s",
                    source_id,
                    exc,
                )

        return {
            "fact_ids": deleted_fact_ids,
            "statement_ids": [],
            "belief_ids": belief_ids,
        }
