from __future__ import annotations

from typing import List, Optional

from analogai.deepthink.application.value_objects.user_agent import UserAgent
from analogai.deepthink.messaging.question_answering.question_entity_service import (
    QuestionEntityExtractionService,
)
from analogai.deepthink.messaging.question_answering.services.formatting.fact_formatter import (
    QuestionFactFormatter,
)
from analogai.deepthink.messaging.question_answering.adapters.belief_search_adapter import (
    BeliefSearchAdapter,
)
from analogai.deepthink.messaging.question_answering.adapters.notion_search_adapter import (
    NotionSearchAdapter,
)
from analogai.deepthink.messaging.question_answering.adapters.fact_search_adapter import (
    FactSearchAdapter,
)
from analogai.deepthink.messaging.question_answering.services.background.belief_background_info_builder import (
    BeliefBackgroundInfoBuilder,
)
from analogai.deepthink.messaging.question_answering.services.background.fact_background_info_builder import (
    FactBackgroundInfoBuilder,
)
from analogai.foundation.common.logging.app_logger import app_logger  # type: ignore[import-not-found]
from analogai.deepthink.messaging.fact.enums.fact_search_mode import FactSearchMode


class QuestionPromptBackgroundInfoBuilder:
    def __init__(
        self,
        entity_extractor: QuestionEntityExtractionService,
        belief_retriever: BeliefSearchAdapter,
        notion_retriever: NotionSearchAdapter,
        belief_formatter: QuestionFactFormatter,
        fact_retriever: FactSearchAdapter | None = None,
    ) -> None:
        self._entity_extractor = entity_extractor
        self._belief_retriever = belief_retriever
        self._notion_retriever = notion_retriever
        self._belief_formatter = belief_formatter
        self._fact_retriever = fact_retriever
        self._belief_background_builder = BeliefBackgroundInfoBuilder(
            belief_retriever=self._belief_retriever,
            notion_retriever=self._notion_retriever,
            belief_formatter=self._belief_formatter,
        )
        self._fact_background_builder = FactBackgroundInfoBuilder(self._fact_retriever)

    def build_prompt_background_info(
        self,
        question_text: str,
        user_agent: UserAgent,
    ) -> tuple[Optional[tuple[str, List[str], str]], int, int, List, List, List[str], dict[str, str]]:
        fact_lookup: dict[str, str] = {}
        entities = self._entity_extractor.extract_entities(question_text)
        try:
            app_logger.info(
                "[QuestionPromptBackgroundInfoBuilder] entities=%s question='%s'",
                entities,
                question_text.strip(),
            )
        except Exception:
            pass
        try:
            app_logger.debug(
                "[QuestionPromptBackgroundInfoBuilder] entities_extracted=%s",
                entities,
            )
        except Exception:
            pass
        if not entities:
            try:
                app_logger.info("[QuestionPromptBackgroundInfoBuilder] no entities extracted")
            except Exception:
                pass
        beliefs, notions, notion_lines, belief_block, belief_count = self._belief_background_builder.build_background(
            user_agent,
            entities,
        )
        search_mode = (
            FactSearchMode.VECTOR_ONLY
            if not beliefs
            else FactSearchMode.VECTOR_THEN_TEXT
        )
        allow_question_facts = not entities
        fact_lookup = self._fact_background_builder.build_background(
            user_agent,
            question_text,
            entities,
            notions,
            allow_question_facts=allow_question_facts,
            search_mode=search_mode,
            fact_lookup=fact_lookup,
        )
        fact_list = list(fact_lookup.values())
        if not beliefs and not notions and not fact_lookup:
            try:
                app_logger.info(
                    "[QuestionPromptBackgroundInfoBuilder] empty beliefs/notions/turns entities=%s",
                    entities,
                )
            except Exception:
                pass
            return None, 0, 0, [], [], [], {}
        if not belief_block and notion_lines:
            belief_block = "\n".join(notion_lines)
        if not belief_block:
            belief_block = ""
        if fact_list:
            fact_block = "\n".join(f"CONVERSATION FACT: {line}" for line in fact_list)
            belief_block = f"{belief_block}\n{fact_block}" if belief_block else fact_block
        if not belief_block.strip():
            try:
                app_logger.info(
                    "[QuestionPromptBackgroundInfoBuilder] empty belief block entities=%s beliefs=%d notions=%d turns=%d",
                    entities,
                    len(beliefs or []),
                    len(notions or []),
                    len(fact_list),
                )
            except Exception:
                pass
            return None, 0, 0, [], notions, notion_lines, fact_lookup

        line_count = self._count_block_lines(belief_block)
        try:
            app_logger.info(
                "[QuestionPromptBackgroundInfoBuilder] background ready beliefs=%d lines=%d notions=%d turns=%d block_chars=%d",
                belief_count,
                line_count,
                len(notion_lines),
                len(fact_list),
                len(belief_block),
            )
        except Exception:
            pass

        return (
            (question_text.strip(), entities, belief_block),
            belief_count,
            line_count,
            beliefs,
            notions,
            notion_lines,
            fact_lookup,
        )

    @staticmethod
    def _count_block_lines(text: str) -> int:
        return sum(1 for line in text.splitlines() if line.strip())
