from __future__ import annotations

from abc import ABC, abstractmethod
from typing import Optional

from analogai.deepthink.application.value_objects.user_agent import UserAgent
from analogai.deepthink.messaging.question_answering.question_answering_service import (
    QuestionAnsweringService,
)
from analogai.deepthink.presentation.pipeline.pipeline import MessagePipeline
from analogai.deepthink.presentation.preprocessing.previous_messages_stack import PreviousMessagesStack
from analogai.deepthink.messaging.question_answering.enums.synthesized_text_type import (
    SynthesizedTextType,
)


class MessageCommand(ABC):
    @abstractmethod
    def execute(
        self,
        text: str,
        user_agent: UserAgent,
        stack: PreviousMessagesStack,
        synthesized_text_type: Optional[SynthesizedTextType] = None,
    ) -> Optional[str]:
        raise NotImplementedError


class RememberCommand(MessageCommand):
    def __init__(self, pipeline: MessagePipeline):
        self._pipeline = pipeline

    def execute(
        self,
        text: str,
        user_agent: UserAgent,
        stack: PreviousMessagesStack,
        synthesized_text_type: Optional[SynthesizedTextType] = None,
    ) -> Optional[str]:
        stack.add_user(text)
        result = self._pipeline.execute(
            raw_message=text,
            user_agent=user_agent,
            previous_messages_stack=stack,
        )
        if result is None:
            message_text = None
        else:
            try:
                message_text = result.message_text
            except AttributeError:
                message_text = None
        if message_text:
            stack.add_agent(message_text)
        return message_text


class SearchCommand(MessageCommand):
    def __init__(self, question_answering_service: QuestionAnsweringService):
        self._question_answering_service = question_answering_service

    def execute(
        self,
        text: str,
        user_agent: UserAgent,
        stack: PreviousMessagesStack,
        synthesized_text_type: Optional[SynthesizedTextType] = None,
    ) -> Optional[str]:
        stack.add_user(text)
        answer = self._question_answering_service.answer_question(
            question_text=text,
            user_agent=user_agent,
            synthesized_text_type=synthesized_text_type,
            previous_messages_stack=stack,
        )
        if answer:
            stack.add_agent(answer)
        return answer


class GenerateBackgroundInfoCommand:
    def __init__(self, question_answering_service: QuestionAnsweringService):
        self._question_answering_service = question_answering_service

    def execute(self, text: str, user_agent: UserAgent) -> str:
        return self._question_answering_service.build_question_background_info(
            question_text=text,
            user_agent=user_agent,
        )


__all__ = [
    "GenerateBackgroundInfoCommand",
    "MessageCommand",
    "RememberCommand",
    "SearchCommand",
]
