import unittest

from src.aiel_sdk.integrations.openai.remote import RemoteOpenAI
from src.aiel_sdk.integrations.openai.types import (
    OpenAIChatCompletionsCreateRequest,
    OpenAIEmbeddingsCreateRequest,
    OpenAIResponsesCreateJsonRequest,
    OpenAIResponsesCreateRequest,
)


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 == "openai.ping":
            return {"ok": True}
        return {"id": "resp_1", "ok": True}


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


class RemoteOpenAITests(unittest.TestCase):
    def test_responses_create_invokes_action(self):
        client = _FakeClient()
        oai = RemoteOpenAI(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        out = oai.responses_create(
            OpenAIResponsesCreateRequest(input="hello", model="gpt-4o-mini"),
            request_id="req_1",
        )

        self.assertEqual(out.raw.get("id"), "resp_1")
        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "openai.responses.create")
        self.assertEqual(call["payload"], {"params": {"input": "hello", "model": "gpt-4o-mini"}})
        self.assertEqual(call["request_id"], "req_1")

    def test_responses_create_json_invokes_action(self):
        client = _FakeClient()
        oai = RemoteOpenAI(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        _ = oai.responses_create_json(
            OpenAIResponsesCreateJsonRequest(
                input="extract fields",
                json_schema={"type": "object"},
                model="gpt-4.1-mini",
            ),
            request_id="req_2",
        )

        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "openai.responses.create_json")
        self.assertEqual(
            call["payload"],
            {
                "params": {
                    "input": "extract fields",
                    "model": "gpt-4.1-mini",
                    "json_schema": {"type": "object"},
                }
            },
        )

    def test_embeddings_create_invokes_action(self):
        client = _FakeClient()
        oai = RemoteOpenAI(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        _ = oai.embeddings_create(
            OpenAIEmbeddingsCreateRequest(input="hello", model="text-embedding-3-small", dimensions=256),
            request_id="req_3",
        )

        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "openai.embeddings.create")
        self.assertEqual(
            call["payload"],
            {"params": {"input": "hello", "model": "text-embedding-3-small", "dimensions": 256}},
        )

    def test_chat_completions_create_invokes_action(self):
        client = _FakeClient()
        oai = RemoteOpenAI(client=client, workspace_id="w1", project_id="p1", connection_id="c1")

        _ = oai.chat_completions_create(
            OpenAIChatCompletionsCreateRequest(
                model="gpt-4o-mini",
                messages=[{"role": "user", "content": "hello"}],
            ),
            request_id="req_4",
        )

        call = client.integrations.calls[-1]
        self.assertEqual(call["action"], "openai.chat.completions.create")
        self.assertEqual(
            call["payload"],
            {
                "params": {
                    "messages": [{"role": "user", "content": "hello"}],
                    "model": "gpt-4o-mini",
                }
            },
        )

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

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

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

    def test_validation(self):
        with self.assertRaises(ValueError):
            OpenAIResponsesCreateRequest(input=None).to_params()
        with self.assertRaises(ValueError):
            OpenAIResponsesCreateJsonRequest(input="x", json_schema=[]).to_params()
        with self.assertRaises(ValueError):
            OpenAIEmbeddingsCreateRequest(input="x", dimensions=0).to_params()
        with self.assertRaises(ValueError):
            OpenAIChatCompletionsCreateRequest(messages=[]).to_params()


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