import unittest

from src.aiel_sdk.integrations.firebase.remote import RemoteFirebase
from src.aiel_sdk.integrations.firebase.types import (
    FirebaseDocDeleteRequest,
    FirebaseDocGetRequest,
    FirebaseDocPutRequest,
    FirebaseDocQueryRequest,
)


class _FakeIntegrationsService:
    def __init__(self):
        self.calls = []

    def invoke_action(self, workspace_id, project_id, connection_id, action, payload=None, request_id=None):
        self.calls.append(
            {
                "workspace_id": workspace_id,
                "project_id": project_id,
                "connection_id": connection_id,
                "action": action,
                "payload": payload,
                "request_id": request_id,
            }
        )
        if action in {"firebase.doc.get", "firebase.doc.put"}:
            return {"found": True, "document": {"id": "d1"}}
        if action == "firebase.doc.delete":
            return {"deleted": True}
        if action == "firebase.doc.query":
            return {"documents": [{"id": "d1"}], "count": 1}
        if action == "firebase.ping":
            return {"ok": True}
        return {}


class _FakeClient:
    def __init__(self):
        self.integrations = _FakeIntegrationsService()


class RemoteFirebaseTests(unittest.TestCase):
    def test_doc_get_invokes_action(self):
        client = _FakeClient()
        fb = RemoteFirebase(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        out = fb.doc_get(FirebaseDocGetRequest(collection="users", doc_id="u1"), request_id="req_1")

        self.assertEqual(out.found, True)
        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "firebase.doc.get")
        self.assertEqual(call["payload"], {"params": {"collection": "users", "doc_id": "u1"}})
        self.assertEqual(call["request_id"], "req_1")

    def test_doc_put_invokes_action(self):
        client = _FakeClient()
        fb = RemoteFirebase(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        out = fb.doc_put(
            FirebaseDocPutRequest(collection="users", doc_id="u1", data={"name": "Alden"}, merge=True),
            request_id="req_2",
        )

        self.assertEqual(out.found, True)
        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "firebase.doc.put")
        self.assertEqual(
            call["payload"],
            {"params": {"collection": "users", "doc_id": "u1", "data": {"name": "Alden"}, "merge": True}},
        )

    def test_doc_delete_invokes_action(self):
        client = _FakeClient()
        fb = RemoteFirebase(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        out = fb.doc_delete(FirebaseDocDeleteRequest(collection="users", doc_id="u1"), request_id="req_3")

        self.assertEqual(out.deleted, True)
        self.assertEqual(client.integrations.calls[-1]["action"], "firebase.doc.delete")

    def test_doc_query_invokes_action(self):
        client = _FakeClient()
        fb = RemoteFirebase(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        out = fb.doc_query(
            FirebaseDocQueryRequest(collection="users", where=[["status", "==", "active"]], limit=10),
            request_id="req_4",
        )

        self.assertEqual(out.count, 1)
        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "firebase.doc.query")
        self.assertEqual(
            call["payload"],
            {"params": {"collection": "users", "where": [["status", "==", "active"]], "limit": 10}},
        )

    def test_ping_invokes_action(self):
        client = _FakeClient()
        fb = RemoteFirebase(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        out = fb.ping(request_id="req_5")

        self.assertEqual(out.ok, True)
        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "firebase.ping")
        self.assertEqual(call["payload"], {"params": {}})
        self.assertEqual(call["request_id"], "req_5")

    def test_validation(self):
        with self.assertRaises(ValueError):
            FirebaseDocGetRequest(collection="", doc_id="u1").to_params()
        with self.assertRaises(ValueError):
            FirebaseDocPutRequest(collection="users", doc_id="u1", data={}).to_params()
        with self.assertRaises(ValueError):
            FirebaseDocDeleteRequest(collection="users", doc_id="").to_params()
        with self.assertRaises(ValueError):
            FirebaseDocQueryRequest(collection="", limit=1).to_params()
        with self.assertRaises(ValueError):
            FirebaseDocQueryRequest(collection="users", limit=0).to_params()


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