import unittest

from analogai.foundation.modules.direct_statement.direct_statement import DirectStatement
from analogai.foundation.modules.notion.notion import Notion
from analogai.foundation.core.value_objects.relation import Relation
from analogai.foundation.modules.direct_statement.direct_statement_service import StatementService


class FakeStatementRepository:
    def __init__(self):
        self._statements = []

    def create(self, statement: DirectStatement) -> DirectStatement:
        self._statements.append(statement)
        return statement

    def delete(self, statement: DirectStatement) -> None:
        self._statements = [
            existing
            for existing in self._statements
            if existing.id != statement.id
        ]

    def find_by_id(self, statement_id: str):
        for statement in self._statements:
            if statement.id == statement_id:
                return statement
        return None

    def find_by_subject(self, subject_notion: Notion):
        return [
            statement
            for statement in self._statements
            if statement.subject_notion.id == subject_notion.id
        ]

    def find_by_subject_and_relation(self, subject_notion: Notion, relation: Relation, modifier=None):
        results = [
            statement
            for statement in self._statements
            if statement.subject_notion.id == subject_notion.id
            and statement.relation == relation
        ]
        if modifier is None:
            return results
        return [statement for statement in results if statement.modifier == modifier]

    def find_by_object(self, complement_notion: Notion):
        return [
            statement
            for statement in self._statements
            if statement.complement_notion.id == complement_notion.id
        ]

    def find_by_object_and_relation(self, complement_notion: Notion, relation: Relation, modifier=None):
        results = [
            statement
            for statement in self._statements
            if statement.complement_notion.id == complement_notion.id
            and statement.relation == relation
        ]
        if modifier is None:
            return results
        return [statement for statement in results if statement.modifier == modifier]

    def find_by_agent_id(self, agent_id: str, limit: int = 0, offset: int = 0):
        results = [
            statement
            for statement in self._statements
            if statement.agent_id == agent_id
        ]
        if limit <= 0:
            return results[offset:]
        return results[offset:offset + limit]

    def find_direct_statement(
        self,
        user_id: str,
        agent_id: str,
        subject_notion: Notion,
        relation: Relation,
        complement_notion: Notion,
        modifier=None,
    ):
        for statement in self._statements:
            if (
                statement.user_id == user_id
                and statement.agent_id == agent_id
                and statement.subject_notion.id == subject_notion.id
                and statement.complement_notion.id == complement_notion.id
                and statement.relation == relation
                and statement.modifier == modifier
            ):
                return statement
        return None


class TestStatementService(unittest.TestCase):
    def setUp(self):
        self.service = StatementService(FakeStatementRepository())
        self.user_id = "user_1"
        self.agent_id = "agent_1"
        self.subject_notion = Notion(
            user_id=self.user_id, agent_id=self.agent_id, caption="socrates", id="sub_1"
        )
        self.relation = Relation.from_string("sell")
        self.complement_notion = Notion(
            user_id=self.user_id, agent_id=self.agent_id, caption="iphone", id="obj_1"
        )

    def test_create_returns_statement(self):
        result = self.service.create(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
        )
        self.assertIsInstance(result, DirectStatement)
        self.assertEqual(result.subject_notion.id, self.subject_notion.id)
        self.assertEqual(result.complement_notion.id, self.complement_notion.id)
        self.assertEqual(result.relation, self.relation)

    def test_find_by_subject_returns_from_repository(self):
        statement = self.service.create(
            user_id=self.user_id,
            agent_id=self.agent_id,
            subject_notion=self.subject_notion,
            relation=self.relation,
            complement_notion=self.complement_notion,
        )
        result = self.service.find_by_subject(self.subject_notion)
        result_ids = [p.id for p in result]
        self.assertIn(statement.id, result_ids)

    # def test_has_statement_returns_true_when_statement_exists(self):
    #     self.service.create(
    #         user_id=self.user_id,
    #         agent_id=self.agent_id,
    #         subject_notion=self.subject_notion,
    #         relation=self.relation,
    #         complement_notion=self.complement_notion,
    #     )
    #     result = self.service.has_statement(
    #         self.subject_notion, Relation.from_string("sell"), self.complement_notion
    #     )
    #     self.assertTrue(result)

    # def test_has_statement_returns_false_when_no_match(self):
    #     result = self.service.has_statement(
    #         self.subject_notion, Relation.from_string("nonexistent"), self.complement_notion
    #     )
    #     self.assertFalse(result)


if __name__ == "__main__":
    unittest.main()