from __future__ import annotations

from typing import Iterable, List

from analogai.foundation.common.dtos.notion_expression import NotionExpression  # type: ignore[import-not-found]

from analogai.deepthink.application.value_objects.user_agent import UserAgent


class NotionSearchAdapter:
    def __init__(self, notion_service) -> None:
        self._notion_service = notion_service

    def search_notions(self, user_agent: UserAgent, entities: Iterable[str]) -> List:
        if self._notion_service is None:
            return []
        results: List = []
        seen = set()
        for entity in entities:
            if not entity:
                continue
            key = entity.strip().lower()
            if key in seen:
                continue
            seen.add(key)
            notion = self._notion_service.find(
                user_agent.agent_id,
                NotionExpression(caption=entity),
            )
            if notion is not None:
                results.append(notion)
        return results

    def expand_notions_from_beliefs(self, user_agent: UserAgent, notions: List, beliefs: Iterable) -> List:
        if self._notion_service is None:
            return notions
        results = list(notions) if notions else []
        seen = {_notion_identity(notion) or "" for notion in results}
        for belief in beliefs or []:
            for notion in _belief_notions(belief):
                if notion is None:
                    continue
                notion_id = _notion_id(notion)
                notion_caption = _notion_caption(notion)
                key = notion_id or notion_caption or str(notion)
                if key in seen:
                    continue
                if notion_caption:
                    fetched = self._notion_service.find(
                        user_agent.agent_id,
                        NotionExpression(caption=notion_caption),
                    )
                    if fetched is not None:
                        results.append(fetched)
                        seen.add(_notion_identity(fetched) or key)
                        continue
                results.append(notion)
                seen.add(key)
        return results


def _belief_notions(belief) -> tuple[object | None, object | None]:
    if belief is None:
        return (None, None)
    return (belief.subject_notion, belief.complement_notion)


def _notion_id(notion) -> str | None:
    if notion is None:
        return None
    return notion.id


def _notion_caption(notion) -> str | None:
    if notion is None:
        return None
    return notion.caption


def _notion_identity(notion) -> str | None:
    return _notion_id(notion) or _notion_caption(notion)
