import unittest
from unittest import TestCase
from analogai.foundation.infrastructure.storage.in_memory.in_memory_storage_adapter_impl import InMemoryStorageAdapterImpl

class TestInMemoryStorageAdapterImpl(TestCase):
    def setUp(self):
        self.gateway = InMemoryStorageAdapterImpl()
        self.collection = "test_collection"

    def tearDown(self) -> None:
        self.gateway.clear()

    def test_store_and_retrieve_by_id(self):
        entity = {"id": "e1", "name": "n1", "value": "v1"}
        self.gateway.store(self.collection, entity)
        got = self.gateway.retrieve_by_id(self.collection, "e1")
        self.assertIsNotNone(got)
        self.assertEqual(got["id"], "e1")
        self.assertEqual(got["name"], "n1")
        self.assertEqual(got["value"], "v1")

    def test_retrieve_by_id_none_when_missing(self):
        got = self.gateway.retrieve_by_id(self.collection, "missing")
        self.assertIsNone(got)

    def test_retrieve_by_attributes_simple_match(self):
        e1 = {"id": "a", "name": "same", "value": "v1"}
        e2 = {"id": "b", "name": "same", "value": "v2"}
        e3 = {"id": "c", "name": "diff", "value": "v3"}
        self.gateway.store(self.collection, e1)
        self.gateway.store(self.collection, e2)
        self.gateway.store(self.collection, e3)
        results = self.gateway.retrieve_by_attributes(self.collection, {"name": "same"})
        self.assertEqual(len(results), 2)
        ids = {r["id"] for r in results}
        self.assertIn("a", ids)
        self.assertIn("b", ids)

    def test_retrieve_by_attributes_nested_match(self):
        e1 = {"id": "x", "name": "n", "nested": {"id": "n1"}}
        e2 = {"id": "y", "name": "n", "nested": {"id": "n2"}}
        self.gateway.store(self.collection, e1)
        self.gateway.store(self.collection, e2)
        results = self.gateway.retrieve_by_attributes(self.collection, {"nested.id": "n2"})
        self.assertEqual(len(results), 1)
        self.assertEqual(results[0]["id"], "y")

    def test_retrieve_by_attributes_no_match(self):
        e1 = {"id": "a1", "name": "x"}
        self.gateway.store(self.collection, e1)
        results = self.gateway.retrieve_by_attributes(self.collection, {"name": "z"})
        self.assertEqual(len(results), 0)

    def test_collection_isolation(self):
        e1 = {"id": "c1", "name": "n"}
        e2 = {"id": "c2", "name": "n"}
        self.gateway.store("collection_one", e1)
        self.gateway.store("collection_two", e2)
        r1 = self.gateway.retrieve_by_attributes("collection_one", {"name": "n"})
        r2 = self.gateway.retrieve_by_attributes("collection_two", {"name": "n"})
        self.assertEqual(len(r1), 1)
        self.assertEqual(r1[0]["id"], "c1")
        self.assertEqual(len(r2), 1)
        self.assertEqual(r2[0]["id"], "c2")

    def test_delete_existing_returns_true_and_removes(self):
        e = {"id": "d1"}
        self.gateway.store(self.collection, e)
        ok = self.gateway.delete(self.collection, "d1")
        self.assertTrue(ok)
        self.assertIsNone(self.gateway.retrieve_by_id(self.collection, "d1"))

    def test_delete_missing_returns_false(self):
        ok = self.gateway.delete(self.collection, "none")
        self.assertFalse(ok)

    def test_clear_removes_all(self):
        e1 = {"id": "e1"}
        e2 = {"id": "e2"}
        self.gateway.store(self.collection, e1)
        self.gateway.store(self.collection, e2)
        self.assertIsNotNone(self.gateway.retrieve_by_id(self.collection, "e1"))
        self.assertIsNotNone(self.gateway.retrieve_by_id(self.collection, "e2"))
        self.gateway.clear()
        self.assertIsNone(self.gateway.retrieve_by_id(self.collection, "e1"))
        self.assertIsNone(self.gateway.retrieve_by_id(self.collection, "e2"))

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