from abc import ABC, abstractmethod
from typing import List, Optional, Union

from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.modules.direct_statement.direct_statement import DirectStatement
from analogai.foundation.core.value_objects.modifier import Modifier
from analogai.foundation.core.value_objects.relation import Relation


class StatementServiceBase(ABC):
    @abstractmethod
    def create(
        self,
        user_id: str,
        agent_id: str,
        subject_notion: Notion,
        relation: Relation,
        complement_notion: Notion,
        probability: Union[float, int] = 1.0,
        validity: Union[float, int] = 1.0,
        modifier: Optional[Modifier] = None,
        quantity: Optional[float] = None,
        id: Optional[str] = None,
    ) -> DirectStatement:
        raise NotImplementedError

    @abstractmethod
    def update(self, statement: DirectStatement) -> DirectStatement:
        raise NotImplementedError

    @abstractmethod
    def find_by_id(self, statement_id: str) -> Optional[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def find(
        self,
        subject_notion: Notion,
        complement_notion: Notion,
        relation: Relation,
        modifier: Optional[Modifier] = None,
    ) -> Optional[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def find_by_agent_id(
        self,
        agent_id: str,
        limit: int = 0,
        offset: int = 0,
    ) -> List[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def find_by_subject(self, subject_notion: Notion) -> List[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def find_by_subject_and_relation(
        self,
        subject_notion: Notion,
        relation: Relation,
        modifier: Optional[Modifier] = None,
    ) -> List[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def find_by_object(self, complement_notion: Notion) -> List[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def find_by_object_and_relation(
        self,
        complement_notion: Notion,
        relation: Relation,
        modifier: Optional[Modifier] = None,
    ) -> List[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def search_by_subject_notion_and_relation(
        self,
        subject_notion: Notion,
        relation: Relation,
        modifier: Optional[Modifier] = None,
    ) -> List[DirectStatement]:
        raise NotImplementedError

    @abstractmethod
    def search_by_complement_notion_and_relation(
        self,
        complement_notion: Notion,
        relation: Relation,
        modifier: Optional[Modifier] = None,
    ) -> List[DirectStatement]:
        raise NotImplementedError

    # @abstractmethod
    # def has_statement(
    #     self,
    #     subject_notion: Notion,
    #     relation: Relation,
    #     complement_notion: Notion,
    # ) -> bool:
    #     raise NotImplementedError

    @abstractmethod
    def update_probability(self, statement: DirectStatement, probability: Union[float, int]) -> DirectStatement:
        raise NotImplementedError

    @abstractmethod
    def update_validity(self, statement: DirectStatement, validity: Union[float, int]) -> DirectStatement:
        raise NotImplementedError
