from __future__ import annotations

from typing import Callable, Iterable, List, Protocol

from analogai.foundation.common.utils.expression_factory import ExpressionFactory
from analogai.foundation.common.utils.expressions_serializer import serialize_belief_expression

from analogai.deepthink.messaging.fact.services.fact_response_decorator import FactResponseDecorator
from analogai.deepthink.messaging.fact.services.fact_context_service import FactContextWindowService

class BeliefLineFormatter(Protocol):
    def format(self, belief) -> str:
        ...


class ExpressionBeliefLineFormatter:
    def __init__(
        self,
        expression_factory: ExpressionFactory,
        serializer: Callable,
    ) -> None:
        self._expression_factory = expression_factory
        self._serializer = serializer

    def format(self, belief) -> str:
        expression = self._expression_factory.propagate_belief_expression(belief)
        return self._serializer(expression)


class QuestionFactFormatter:
    def __init__(
        self,
        provenance_decorator: FactResponseDecorator | None = None,
        fact_context_service: FactContextWindowService | None = None,
        belief_line_formatter: BeliefLineFormatter | None = None,
    ) -> None:
        self._provenance_decorator = provenance_decorator
        self._fact_context_service = fact_context_service
        self._belief_line_formatter = belief_line_formatter or ExpressionBeliefLineFormatter(
            ExpressionFactory(),
            serialize_belief_expression,
        )

    def format_fact_lines(self, beliefs: Iterable) -> str:
        formatted = []
        for belief in beliefs:
            formatted.append(self.format_fact(belief))
        return "\n".join([line for line in formatted if line])

    def format_notions(self, notions: Iterable) -> str:
        formatted: List[str] = []
        for notion in notions:
            if not notion.attributes:
                continue
            formatted.append(str(notion))
        return "\n".join([line for line in formatted if line])

    def build_fact_block_text(self, beliefs: Iterable) -> str:
        belief_text = self.format_fact_lines(beliefs) if beliefs else ""
        return belief_text

    def format_fact(self, belief) -> str:
        base = self._belief_line_formatter.format(belief)
        return self._decorate_belief(base, belief)

    def _decorate_belief(self, belief_line: str, belief) -> str:
        if not belief_line:
            return belief_line
        if self._fact_context_service is not None:
            return belief_line
        if self._provenance_decorator is None:
            return belief_line
        return self._provenance_decorator.decorate_belief_line(belief_line, belief)
